Hatena::Groupiphone-dev

Ni chicha, ni limona - 平均から抜けられない僕

2010-10-14

[AssetsLibrary] フォトライブラリの写真にExif情報を付けて保存する 00:40  [AssetsLibrary] フォトライブラリの写真にExif情報を付けて保存する - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [AssetsLibrary] フォトライブラリの写真にExif情報を付けて保存する - Ni chicha, ni limona - 平均から抜けられない僕  [AssetsLibrary] フォトライブラリの写真にExif情報を付けて保存する - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

iOS4.1から、カメラロールにデータを保存する際に画像のメタデータも一緒に保存できるようになりました。

つまり、iOS3以前ではトリッキーな方法でしか実現できなかったExif情報の付与も、ごく簡単にできるようになったわけです。


具体的には、ALAssetsLibraryクラスのwriteImageToSavedPhotosAlbum:metadata:completionBlock:メソッド、あるいはwriteImageDataToSavedPhotosAlbum:metadata:completionBlock:メソッドを使用します。両者の違いは画像データがCGImageRefか、NSDataかです。


イメージピッカーで選んだ写真を元に、コメントとシャッター速度の2つのExif情報を付けて保存するサンプルコードを以下に記します。

#import <AssetsLibrary/AssetsLibrary.h>
#import <ImageIO/ImageIO.h>

-(IBAction)takeButton:(id)sender {
  UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
  picker.sourceType = UIImagePickerControllerSourceTypeCamera;

  picker.delegate = self;
  [self presentModalViewController:picker animated:YES];
}

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
    NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];

    if (assetURL) {
        ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset *asset) {
            ALAssetRepresentation *representation;
            representation = [asset defaultRepresentation];

            // 元から付いているメタデータも残す
            NSMutableDictionary *metadata;
            metadata = [[NSMutableDictionary alloc]
                         initWithDictionary:[representation metadata]];

            // コメント、シャッター速度をExif情報として設定
            NSDictionary *exif = [NSDictionary dictionaryWithObjectsAndKeys:
                                  @"コメント",
                                  (NSString*)kCGImagePropertyExifUserComment,
                                  [NSNumber numberWithFloat:0.125f],
                                  (NSString*)kCGImagePropertyExifExposureTime,
                                  nil];
            [metadata setObject:exif
                         forKey:(NSString*)kCGImagePropertyExifDictionary];

            // カメラロールにメタデータを付けて書き込み
            ALAssetsLibrary* l = [[ALAssetsLibrary alloc] init];
            [l writeImageToSavedPhotosAlbum:[representation fullScreenImage]
                                      metadata:metadata
                            completionBlock:^(NSURL* url, NSError* e){
                                NSLog(@"Saved: %@<%@>", url, e);
                            }];
                            [metadata release];
            [l release];
        };
        
        ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease];
        [library assetForURL:assetURL
                 resultBlock:resultBlock
                failureBlock:^(NSError *error) {
                    NSLog(@"error:%@", error);
                }];
    } else { NSLog(@"error"); }
    
    [picker dismissModalViewControllerAnimated:YES];
}

事前にAssets Libraryフレームワークをプロジェクトに追加し、さらにExif情報を文字列リテラルで扱えるImageIOフレームワークも追加するのを忘れないようにお気を付けください。


こうして保存した画像をMac OS X上のプレビューアプリで見れば、Exif情報が付与されていることが分かります。


ちなみにAssets Libraryフレームワークでは、既存の写真を変更したり、削除したりすることはできません。新しいデータをカメラロールに保存できるのみです。

カメラロールくらいは変更・削除を許可してくれてもいいのになあと思いますが・・・。


それにしてもAssets Libraryフレームワークは超便利です。独自のイメージピッカーも自由に作れるようになりますし、ますます便利になりましたね!

参考サイト

イメージピッカーから選んだ写真の、Exif情報を取り出すときのサンプルコード。 @sumihiro さん。

ImageIOフレームワークとCoreGraphicsを使って、バンドル内にExif付きのデータを保存するサンプルコード。 @nakamura001 さん。

wavdevwavdev2011/01/10 09:39iOS4.2から [info objectForKey:UIImagePickerControllerReferenceURL]がNULL返すようになっちゃいましたね。iOS4.1ではOKだったんですが...ちょっと苦戦してます。