2012年7月25日 星期三

Filter4Cam 實作: 24. 影像方向調整之五

since: 2012/07/25
update: 2012/07/25

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

拍照

A. 說明:
     1. 要產生的圖片, 不需要再次從 filter 取得 CIImage 的輸出:
         self.ciImage = [self.coreImageFilter outputImage], 直接使用 self.ciImage 即可, 
         因為 self.ciImage 會在之前的處理過程中, 採用原始影像套用濾鏡.

     2. ALAssetOrientation 的值, 可有以下 8 種:
         ALAssetOrientationUp;
         ALAssetOrientationUpMirrored; 
         ALAssetOrientationDown;
         ALAssetOrientationDownMirrored;
         ALAssetOrientationRight;
         ALAssetOrientationRightMirrored;
         ALAssetOrientationLeft;
         ALAssetOrientationLeftMirrored;

     3. "擷取的濾鏡影像範圍"(fromRect:) 與 drawFilteredImage: 方法中,
          drawImage:inRect:fromRect: 裡的 fromRect: 設定值相同

     4. 使用 ALAssetsLibraryCGImageRef 儲存到相簿裡的函式有二個:
          a. writeImageToSavedPhotosAlbum:metadata:completionBlock:
          b. writeImageToSavedPhotosAlbum:orientation:completionBlock:

     5. 依照 "設備擺放方向", "前後置鏡頭" 與 "設備上次擺放方向" 來調整
         產生圖片的方向.

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

B. 開啟 ViewController.m 檔案, 修改如下:
....
//@update: "拍照": 只截取濾鏡範圍的影像
- (void)savePhoto
{   
    // 產生 CGImageRef
    CGImageRef cgImage = nil;
   
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
   
    ALAssetOrientation ALAOrientation = ALAssetOrientationUp;
       
    // ################################################# //
    // A. 設備擺放方向為: "垂直" 或 "垂直 180 度" 或 "水平向右" 或 "水平向左" //
    // ################################################# //
    if (orientation == UIDeviceOrientationPortrait ||
        orientation == UIDeviceOrientationPortraitUpsideDown ||
        orientation == UIDeviceOrientationLandscapeRight ||
        orientation == UIDeviceOrientationLandscapeLeft)
    { 
        ///////////////////////////////////////
        // 1. 擷取濾鏡影像範圍
        //
       
        // 設備垂直擺放
        if (orientation == UIDeviceOrientationPortrait)
        {
            cgImage = [self.coreImageContext createCGImage:self.ciImage fromRect:CGRectMake(23, -557.5, 274, 274)];
        }
        // 設備垂直 180 度擺放
        else if (orientation == UIDeviceOrientationPortraitUpsideDown)
        {
            cgImage = [self.coreImageContext createCGImage:self.ciImage fromRect:CGRectMake(-458.5, 83, 274, 274)];
        }
        // "設備水平向右擺放" 或 "設備水平向左擺放"
        else if (orientation == UIDeviceOrientationLandscapeRight ||
                 orientation == UIDeviceOrientationLandscapeLeft)
        {
            cgImage = [self.coreImageContext createCGImage:self.ciImage fromRect:CGRectMake(123.5, 23.5, 274, 274)];
        }
       
        ///////////////////////////////////////
        // 2. "前置鏡頭" 影像方向
        //
       
        // 前置鏡頭
        if (self.isUsingFrontCamera)
        {           
            // 設備水平向左擺放
            if (orientation == UIDeviceOrientationLandscapeLeft)
            {
                ALAOrientation = ALAssetOrientationDownMirrored;
            }
            // 其它: 垂直, 垂直 180 度, 水平向右
            else
            {
                ALAOrientation = ALAssetOrientationUpMirrored;
            }
           
            // 將 CGImageRef 儲存到相簿裡
            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
           
            [library writeImageToSavedPhotosAlbum:cgImage orientation:ALAOrientation
                                  completionBlock:^(NSURL *assetURL, NSError *error) {
                                     
                              // 釋放 CGImage, 這是一個 callback block, 當處理完畢時才會觸發.
                                      CGImageRelease(cgImage);
                                  }];
        }
       
        ///////////////////////////////////////
        // 3. "後置鏡頭" 影像方向
        //
       
        // 後置鏡頭
        else
        {
            // 設備水平向右擺放
            if (orientation == UIDeviceOrientationLandscapeRight)
            {              
                ALAOrientation = ALAssetOrientationDown;
               
                // 將 CGImageRef 儲存到相簿裡
                ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
               
                [library writeImageToSavedPhotosAlbum:cgImage orientation:ALAOrientation
                                      completionBlock:^(NSURL *assetURL, NSError *error) {
                                         
                                  // 釋放 CGImage, 這是一個 callback block, 當處理完畢時才會觸發.
                                          CGImageRelease(cgImage);
                                      }];
            }
            // 其它: 垂直, 垂直 180 度, 水平向左  
            else {
                // 將 CGImageRef 儲存到相簿裡
                ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
               
                [library writeImageToSavedPhotosAlbum:cgImage
                                             metadata:[self.ciImage properties]
                                      completionBlock:^(NSURL *assetURL, NSError *error) {
                                         
                                    // 釋放 CGImage, 這是一個 callback block, 當處理完畢時才會觸發.
                                          CGImageRelease(cgImage);
                                      }];
            }
        }
    }
    // ############################### //
    // B. 設備擺放方向為: "朝上" 或 "朝下" 或 "未知" //
    // ############################### //
    else if(orientation == UIDeviceOrientationFaceUp ||
            orientation == UIDeviceOrientationFaceDown ||
            orientation == UIDeviceOrientationUnknown)
    {
        ///////////////////////////////////////
        // 1. 擷取濾鏡影像範圍
        //
       
        // 上次為直擺
        if (lastOrientation == Portrait)
        {
            cgImage = [self.coreImageContext createCGImage:self.ciImage fromRect:CGRectMake(23, -557.5, 274, 274)];
        }
        // 上次為直擺且上下顛倒
        else if (lastOrientation == PortraitUpsideDown)
        {
            cgImage = [self.coreImageContext createCGImage:self.ciImage fromRect:CGRectMake(-458.5, 83.5, 274, 274)];
        }
        // 上次為 "橫擺朝右" 或上次為 "橫擺朝左"
        else if (lastOrientation == LandscapeRight ||
                   lastOrientation == LandscapeLeft)   

        {
            cgImage = [self.coreImageContext createCGImage:self.ciImage fromRect:CGRectMake(123.5, 23.5, 274, 274)];
        }
        else
        {
            NSLog(@"savePhoto: orientation = FaceUp/FaceDown/Unknown, lastOrientation not defined!");
        }


        ///////////////////////////////////////
        // 2. "前置鏡頭" 影像方向
        //
       
        if (self.isUsingFrontCamera)
        {           
            // 上次為 "橫擺朝左"
            if (lastOrientation == LandscapeLeft)
            {
                ALAOrientation = ALAssetOrientationDownMirrored;
            }
            // 其它: 上次為 "直擺", "直擺且上下顛倒" 或 "橫擺朝右"
            else
            {
                ALAOrientation = ALAssetOrientationUpMirrored;
            }
           
            // 將 CGImageRef 儲存到相簿裡
            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
           
            [library writeImageToSavedPhotosAlbum:cgImage orientation:ALAOrientation
                                  completionBlock:^(NSURL *assetURL, NSError *error) {
                                     
                              // 釋放 CGImage, 這是一個 callback block, 當處理完畢時才會觸發.
                                      CGImageRelease(cgImage);
                                  }];
        }

        ///////////////////////////////////////
        // 3. "後置鏡頭" 影像方向
        //
       
        // 後置鏡頭
        else
        {
            // 上次為 "橫擺朝右"
            if (lastOrientation == LandscapeRight)    
            {              
                ALAOrientation = ALAssetOrientationDown;
               
                // 將 CGImageRef 儲存到相簿裡
                ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
               
                [library writeImageToSavedPhotosAlbum:cgImage orientation:ALAOrientation
                                      completionBlock:^(NSURL *assetURL, NSError *error) {
                                         
                                    // 釋放 CGImage, 這是一個 callback block, 當處理完畢時才會觸發.
                                          CGImageRelease(cgImage);
                                      }];
            }
            else {
                // 將 CGImageRef 儲存到相簿裡
                ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
               
                [library writeImageToSavedPhotosAlbum:cgImage
                                             metadata:[self.ciImage properties]
                                      completionBlock:^(NSURL *assetURL, NSError *error) {
                                         
                                  // 釋放 CGImage, 這是一個 callback block, 當處理完畢時才會觸發.
                                          CGImageRelease(cgImage);
                                      }];
            }
        }
    }
    else
    {
        NSLog(@"savePhoto: No orientation match!");
    }
}
....

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

C. 編譯並執行:

     1. 先將 buttonView 的 backgroundColor 註解後, 再編譯並執行.
     // ViewController.m
....
// 用來放所有按鈕的 View
- (UIView *)buttonView
{
    if (_buttonView == nil) {
        _buttonView = [[UIView alloc] init];
        //@測試使用
        //_buttonView.backgroundColor = [UIColor redColor];    
    }
   
    return _buttonView;
}
....

     2. 設備水平向右擺放:
         (相機鏡頭在右後方, 功能按鈕遠離相機鏡頭位置)

     3. 拍照結果:

沒有留言:

張貼留言

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