update: 2012/07/23
reference:
1. The iOS 5 Developer's Cookbook, 3/e
2. iphone - CATransform3D vs. CGAffineTransform? - Stack Overflow
A. 開啟 ViewController.m 檔案, 修改如下:
....
// step 1:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//@add
self.applyFilter = NO;
self.isUsingFrontCamera = NO;
....
}
....
// step 2:
//@add:建立相機 Session
- (void)establishCamera:(uint)whichCamera
{
....
// Choose camera
/*
self.isUsingFrontCamera = NO;
if ((whichCamera == kCameraFront) && [Filter4CamHelper frontCameraAvailable])
{
self.isUsingFrontCamera = YES;
}
*/
//@update
if ((whichCamera == kCameraFront) && [Filter4CamHelper frontCameraAvailable])
{
self.isUsingFrontCamera = YES;
}
else
{
self.isUsingFrontCamera = NO;
}
....
}
....
// step 3:
//@add: "鏡頭切換"
- (void)switchCameras
{
if (![Filter4CamHelper numberOfCameras] > 1) return;
self.isUsingFrontCamera = !self.isUsingFrontCamera;
if ((self.isUsingFrontCamera == YES) && ![Filter4CamHelper frontCameraAvailable]) {
self.isUsingFrontCamera = NO;
}
AVCaptureDevice *newDevice = self.isUsingFrontCamera ? [Filter4CamHelper frontCamera] : [Filter4CamHelper backCamera];
[self.session beginConfiguration];
// Remove existing inputs
for (AVCaptureInput *input in [self.session inputs])
[self.session removeInput:input];
// Change the input
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:newDevice error:nil];
[self.session addInput:captureInput];
[self.session commitConfiguration];
}
....
編譯並執行:
預設後置鏡頭:
1. 當設備垂直擺放: 物體左右相反.
(說明: "麥斯威爾" 應該要從右往左排列)
B. 有關 "前置鏡頭": 左右相反與上下顛倒之問題:
1. 說明:
a. 方向轉變的調整, 在 ViewController.m 檔案的
captureOutput:didOutputSampleBuffer:fromConnection: 方法中,
(1). 先呼叫了: orientationTransform: 方法, 對整個螢幕作方向調整;
(2). 後來再呼叫: filterOrientationTransform: 方法, 只對套用濾鏡的
顯示範圍作方向調整.
b. 由於目前的問題, 是使用前置鏡頭時, 整個螢幕產生左右相反(垂直擺放)
與上下顛倒(水平擺放)之問題, 因此要對 orientationTransform: 方法作調整.
c. 先看看之前在 orientationTransform: 方法中, 對方向轉變的調整:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGAffineTransform affineTransform; // 仿射轉換
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
affineTransform = CGAffineTransformMakeRotation(-M_PI / 2);
}
....
return [sourceImage imageByApplyingTransform:affineTransform];
備註: 在這邊使用了 CGAffineTransform(仿射轉換) 來處理方向的問題,
但是如果要處理左右相反的問題, 就需要使用 CATransform3D.
d. CGAffineTransform 與 CATransform3D 的差異:
(1). CGAffineTransform 是線性的 2D 轉換, 適用於 NSViews, UIViews
與其它 2D 的 Core Graphics 基礎上.
(2). CATransform3D 是架構在 Core Animation 上的三維投影轉換, 適用於
CALayers 上. CATransform3D 有與 OpenGL 的 model view 矩陣相同的
內部結構, 這是因為 Core Animation 是建立在 OpenGL 的基礎上.
(例如: CALayers 是由 OpenGL 的 textures 包裹而成的)
**********************************************************
2. 測試: "設備垂直擺放", 開啟 ViewController.m 檔案, 修改如下:
....
//@add for orientation Transform(方向轉變的調整)
- (CIImage *)orientationTransform:(CIImage *)sourceImage
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGAffineTransform affineTransform; // 仿射轉換
CATransform3D transform3D = CATransform3DIdentity; // 3D 轉換
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
//@add for 3D Transform
if (self.isUsingFrontCamera) {
// 將整個 GLKView 對 Y 軸作 180 度旋轉
transform3D = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f);
self.glView.layer.transform = transform3D;
}
affineTransform = CGAffineTransformMakeRotation(-M_PI / 2);
}
....
return [sourceImage imageByApplyingTransform:affineTransform];
}
....
編譯並執行:
設備垂直擺放, 切換到前置鏡頭:
a. "麥斯威爾" 從右往左排列是正確的.
b. 變成左右相反的有: TableView(Cell位置與文字), 4 個 button(排列位置與文字)
....
//@add for orientation Transform(方向轉變的調整)
- (CIImage *)orientationTransform:(CIImage *)sourceImage
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGAffineTransform affineTransform; // 仿射轉換
CATransform3D transform3D = CATransform3DIdentity; // 3D 轉換
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
//@add for 3D Transform
if (self.isUsingFrontCamera) {
// 將整個 GLKView 對 Y 軸作 180 度旋轉
transform3D = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f);
self.glView.layer.transform = transform3D;
self.filterListTableView.layer.transform = transform3D;
self.saveButton.layer.transform = transform3D;
self.switchButton.layer.transform = transform3D;
self.torchButton.layer.transform = transform3D;
self.observerButton.layer.transform = transform3D;
}
affineTransform = CGAffineTransformMakeRotation(-M_PI / 2);
}
....
return [sourceImage imageByApplyingTransform:affineTransform];
}
....
編譯並執行:
設備垂直擺放, 切換到前置鏡頭:
a. TableView(Cell位置與文字)已正確顯示了.
b. 4 個 button 的文字顯示正確.
c. 4 個 button 的排列位置, 從左到右應該是: Save, Switch, Torch, Observe.
....
//@add for orientation Transform(方向轉變的調整)
- (CIImage *)orientationTransform:(CIImage *)sourceImage
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGAffineTransform affineTransform; // 仿射轉換
CATransform3D transform3D = CATransform3DIdentity; // 3D 轉換
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
//@add for 3D Transform
if (self.isUsingFrontCamera) {
// 將整個 GLKView 對 Y 軸作 180 度旋轉
transform3D = CATransform3DMakeRotation(M_PI, 0.0f, 1.0f, 0.0f);
self.glView.layer.transform = transform3D;
self.filterListTableView.layer.transform = transform3D;
self.saveButton.layer.transform = transform3D;
self.switchButton.layer.transform = transform3D;
self.torchButton.layer.transform = transform3D;
self.observerButton.layer.transform = transform3D;
//@update for Button position
[self.saveButton setFrame:CGRectMake(241, 420, 66, 40)];
[self.switchButton setFrame:CGRectMake(164, 420, 66, 40)];
[self.torchButton setFrame:CGRectMake(87, 420, 66, 40)];
[self.observerButton setFrame:CGRectMake(10, 420, 66, 40)];
}
affineTransform = CGAffineTransformMakeRotation(-M_PI / 2);
}
....
return [sourceImage imageByApplyingTransform:affineTransform];
}
....
編譯並執行:
設備垂直擺放, 切換到前置鏡頭: 4 個 button 的排列位置已正確了.
備註: 在之後的修正實作時, 會將 4 個 button 加到一個 UIView 之下,
再調整此 UIView 的方向與位置.
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。