2014年1月22日

在iOS應用程式中使用相機與存取相簿

使用行動裝置時,相機可說是最常被使用到的設備之一。因此,對開發者而言,瞭解如何藉由系統API使用相機及存取相簿,也是不可不知的基本功。以下介紹幾個在iOS上常用的方法:

透過UIImagePickerController使用相機、讀取相簿

UIImagePickerController是UIViewController的子類別。顧名思義,此類別不僅實作了常用的相機與相簿功能,還提供了基本的UI界面,讓開發者不需再勞心於UI的設計與實作。

使用UIImagePickerController,只要先建立其物件,設定相關參數,再透過presentViewController將它呈現在畫面上即可。而參數的部分說明如下:

  1. sourceType

    指定使用相機還是從相簿中挑選相片。UIImagePickerControllerSourceTypeCamera為使用相機,UIImagePickerControllerSourceTypePhotoLibrary則是從相簿中挑選相片。

  2. delegate

    此處的delegate物件指的是實作UIImagePickerControllerDelegate的物件。 此物件將接收使用者拍完照片或選好相片後的事件,以處理接收到的相片資訊。

  3. allowsEditing

    允許使用者在UIImagePickerController的畫面中編輯、修改相片。

以下為使用UIImagePickerController來使用相機的範例:

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];

//檢查是否支援此Source Type(相機)
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    //設定影像來源為相機
    imagePicker.sourceType =  UIImagePickerControllerSourceTypeCamera;
    imagePicker.delegate = self;
    imagePicker.allowsEditing = YES;

    //顯示UIImagePickerController
    [self presentViewController:imagePicker animated:YES completion:^{}];
}
else {
    //提示使用者,目前設備不支援相機
}

而delegate物件必須實作以下方法,在使用者按下確定時處理得到的相片資訊,範例如下:

//使用者按下確定時
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    //取得剛拍攝的相片(或是由相簿中所選擇的相片)
    UIImage *image=[info objectForKey:UIImagePickerControllerEditedImage];

    //設定ImageView的Image物件,例如:
    //yourImageView.image = image;

    [picker dismissViewControllerAnimated:YES completion:^{}];
}

//使用者按下取消時
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    //一般情況下沒有什麼特別要做的事情

    [picker dismissViewControllerAnimated:YES completion:^{}];
}

由以上範例不難注意到,imagePickerController:didFinishPickingMediaWithInfo:只有接收到一張相片的資訊。在選擇使用相機直接拍攝相片的情況下,這點沒有什麼問題;但若是由相簿中挑選相片的情況下,這不就意味著一次只能挑選一張相片?

是的,這就是使用UIImagePickerController最大的不便所在。

使用UIImagePickerController由相簿中挑選相片時,是不支援多選的。一次僅能挑選一張相片。

因此,以下將再介紹另一種存取相簿的方式。

使用AssetsLibrary存取相簿

AssetsLibrary提供較高的自由度讓開發者存取相簿;當然相對地,就不像UIImagePickerController有現成UI可以直接使用。開發者必須自行將取得的UIImage呈現在畫面上。

AssetsLibrary使用列舉的方式,讓程式讀取相片資訊。每一張相片的資訊存放在一個ALAsset物件中,此物件提供thumbnaildefaultRepresentation兩個方法,分別用以取得縮圖及原圖的UIImage物件。使用AssetsLibrary的範例如下:

ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];

[library enumerateGroupsWithTypes:ALAssetsGroupAll
    usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    [group setAssetsFilter:[ALAssetsFilter allPhotos]];
    [group enumerateAssetsUsingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop)
     {
         //讀取一張張的相片。當alAsset會變為nil時,表示已經列舉完所以
         if (alAsset) {
             //取得縮圖
             UIImage* thumbnailImage = [UIImage imageWithCGImage:[alAsset thumbnail]];

             //取得原圖
             UIImage* image = [UIImage imageWithCGImage:[[alAsset defaultRepresentation] fullResolutionImage]];

             //處理縮圖及原圖...
         }
     }];
}
 failureBlock: ^(NSError *error) {
     //依據error進行錯誤處理
 }];

ALAssetsLibrary除了能讀取相簿外,也能夠將圖片儲存到相簿中,範例如下:

UIImage* image;

//設定要儲存的image物件
//image = your image...

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
    if (error) {
        //錯誤處理
    }
}];

補充:調整圖片大小

由相機、相簿取得圖片後,調整圖片大小也是常常遇到的需求。以下追加介紹調整圖片大小的方法:

    //原圖片物件
    UIImage* imageToResize;     

    //設定需要調整大小的圖片物件
    //oriImage = ...

    //設定欲調整的新大小
    CGSize destinationSize = CGSizeMake(120.0, 160.0);

    UIGraphicsBeginImageContext(destinationSize);
    [oriImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];

    //取得調整過大小的UIImage物件
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

結語

在iOS應用程式中使用相機、讀取相片其實並不困難,卻是很常見的需求。這也是iOS開發者必備的基本功之一,請務必謹記在心。