2012年7月24日 星期二

Filter4Cam 實作: 20. 影像方向調整之一

since: 2012/07/24
update: 2012/07/24

reference:
1. The iOS 5 Developer's Cookbook, 3/e

前置準備

A. 說明
     1. 如果使用圖像挑選器(image picker), 系統會自動處理跟方向有關的問題.
         在這個專案裡是使用 AVFoundation 來存取相機, 因此必須自行根據不同的
         情況(使用前置或後置相機, 裝置擺放方向) 來處理影像緩衝區裡的原始資料,
         以使影像的呈現保持正向.

     2. 這個專案沒有使用到  AVFoundation 的 AVCaptureVideoPreviewLayer 類別,
         它提供了即時圖像預覽的圖層, 可以將其嵌入到視圖裡.

     3. 由於整個調整的內容範圍較廣, 會等到這一系列的調整都完成後, 再進行編譯.

     4. 關於 "影像方向調整" 這部分, 使用了土法煉鋼的方式(費時費力),
         修改得有點複雜了, 僅供參考. (希望以後能有較好的解決方式)

----------------------------------------------------------------------------------------

B. 新增: radians(弧度) 與 degrees(角度) 轉換函式
     1. 開啟 Filter4CamHelper.h 檔案, 修改如下:
....
@end

// Convert between radians(弧度) and degrees(角度)
CGFloat DegreesToRadians(CGFloat degrees);
CGFloat RadiansToDegrees(CGFloat radians);

****************************************

     2. 開啟 Filter4CamHelper.m 檔案, 修改如下:
....
@end

//@add: Convert between radians(弧度) and degrees(角度)
CGFloat DegreesToRadians(CGFloat degrees)
{
    return degrees * M_PI / 180;
};

CGFloat RadiansToDegrees(CGFloat radians)
{
    return radians * 180 / M_PI;
};

----------------------------------------------------------------------------------------

C. 定義: 儲存 "設備上次的擺放方向"
     開啟 ConstantDefined.h 檔案, 修改如下:
....
////////////////////////////////////////////////////////////////////
// 設備上次的擺放方向(目前不記錄:FaceUp, FaceDown, 與 Unknown)
//
//
enum kLastOrientation
{
    Portrait,           // 直擺
    PortraitUpsideDown, // 直擺, 上下顛倒
    LandscapeRight,     // 橫擺朝右
    LandscapeLeft,      // 橫擺朝左
    FaceUp,             // 面朝上
    FaceDown,           // 面朝下
    Unknown             // 未知
};

#endif

----------------------------------------------------------------------------------------

D. 修改函式名稱
     1. 說明:
         在 ViewController.m 中的
         captureOutput: didOutputSampleBuffer:fromConnection: 方法裡,
         呼叫了 filterOrientationTransform: 來將 "濾鏡範圍" 內的影像內容
         畫到 render buffer, 將其函式名稱改成: drawFilteredImage: 以符實情.

****************************************

     2. 開啟 ViewController.h 檔案, 修改如下:
....
//@add for orientation Transform
- (CIImage *)orientationTransform:(CIImage *)sourceImage; // 轉換原始影像的方向
//- (void)filterOrientationTransform:(CIImage *)sourceImage;  // 方向轉變的調整
- (void)drawFilteredImage:(CIImage *)filteredImage; // 畫出 "濾鏡範圍" 內的影像(含方向轉變的調整)
....

****************************************

     3. 開啟 ViewController.m 檔案, 修改如下:
....
// step 1:
//@add for filter Orientation Transform (方向轉變的調整)
//- (void)filterOrientationTransform:(CIImage *)sourceImage
// 畫出 "濾鏡範圍" 內的影像(含方向轉變的調整)
- (void)drawFilteredImage:(CIImage *)filteredImage
....

// step 2:
....
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
....
//[self filterOrientationTransform:ciImage];
// 畫出 "濾鏡範圍" 內的影像(含方向轉變的調整)
[self drawFilteredImage:self.ciImage];
....
}
....

----------------------------------------------------------------------------------------

E. 新增: 記錄上次是否為前置鏡頭之變數
    1. 開啟 ViewController.h 檔案, 修改如下:
....
@interface ViewController : GLKViewController <AVCaptureVideoDataOutputSampleBufferDelegate, UITableViewDelegate, UITableViewDataSource>
{
....
    BOOL isUsingFrontCamera; // 目前使用前置鏡頭?
    BOOL isLastFrontCamera; // 上次是前置鏡頭?
....
    // 設備上次的擺放方向(目前不記錄:FaceUp, FaceDown, 與 Unknown)
    //
    // Portrait,           // 直擺
    // PortraitUpsideDown, // 直擺, 上下顛倒
    // LandscapeRight,     // 橫擺朝右
    // LandscapeLeft,      // 橫擺朝左
    // FaceUp,             // 面朝上
    // FaceDown,           // 面朝下
    // Unknown             // 未知
    enum kLastOrientation lastOrientation;
}
....
@property (assign) BOOL isUsingFrontCamera;
@property (assign) BOOL isLastFrontCamera;
....

****************************************

    2. 開啟 ViewController.m 檔案, 修改如下:
....// step 1:
@synthesize isUsingFrontCamera = _isUsingFrontCamera;
@synthesize isLastFrontCamera = _isLastFrontCamera;
....

// step 2:
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
   
    //@add
    self.applyFilter = NO;
    self.isUsingFrontCamera = NO; // 預設為後置鏡頭
    self.isLastFrontCamera = NO;  // 預設上次為後置鏡頭
    lastOrientation = Unknown; // 設備上次的擺放方向: 未知
....
}
....

----------------------------------------------------------------------------------------


F. 新增: 用來放所有按鈕的 View

    1.
開啟 ViewController.h 檔案, 修改如下:
....
@interface ViewController : GLKViewController <AVCaptureVideoDataOutputSampleBufferDelegate, UITableViewDelegate, UITableViewDataSource>
{
....
    //@add for Camera Overlay UI
    UIImageView *filterLensImageView;   
    UITableView *filterListTableView;
    UIView *buttonView;       // 用來放所有按鈕的 View
    UIButton *saveButton;     // "拍照" 按鈕
    UIButton *switchButton;   // "鏡頭切換" 按鈕
    UIButton *torchButton;    // "閃光燈切換" 按鈕
    UIButton *observerButton; // "觀察者模式" 按鈕
....
}
....
//@add for Camera Overlay UI
@property (nonatomic, strong) UIImageView *filterLensImageView;
@property (nonatomic, strong) UITableView *filterListTableView;
@property (nonatomic, strong) UIView *buttonView;
@property (nonatomic, strong) UIButton *saveButton;
@property (nonatomic, strong) UIButton *switchButton;
@property (nonatomic, strong) UIButton *torchButton;
@property (nonatomic, strong) UIButton *observerButton;
....


****************************************


    2.
開啟 ViewController.m 檔案, 修改如下:
....
// step01:
//@add for Camera Overlay UI
@synthesize filterLensImageView = _filterLensImageView;
@synthesize filterListTableView = _filterListTableView;
@synthesize buttonView = _buttonView;
@synthesize saveButton = _saveButton;
@synthesize switchButton = _switchButton;
@synthesize torchButton = _torchButton;
@synthesize observerButton = _observerButton;
....

// step02:
#pragma mark Getter
....
// 用來放所有按鈕的 View
- (UIView *)buttonView
{
    if (_buttonView == nil) {
        _buttonView = [[UIView alloc] init];
        _buttonView.backgroundColor = [UIColor redColor]; // 測試使用
    }
   
    return _buttonView;
}
....

// step03:
//@add for setting camera Overlay
- (void)cameraOverlay
{  
....
    /*
    [self.view addSubview:self.saveButton];
    [self.view addSubview:self.switchButton];
    [self.view addSubview:self.torchButton];
    [self.view addSubview:self.observerButton];
    */
    //@update: add buttonView  
    [self.view addSubview:self.buttonView];
    [self.buttonView addSubview:self.saveButton];
    [self.buttonView addSubview:self.switchButton];
    [self.buttonView addSubview:self.torchButton];
    [self.buttonView addSubview:self.observerButton];
....
}
....

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。