強火で進め

このブログではプログラム関連の記事を中心に書いてます。

JPEGファイルのExif情報を読み書きする

※このプログラムはiOS 4以降対応です。それ以前のOSでは正しく動作しません。

(2013/12/16 追記)
iOS SDK 7だと不具合が発生しています。ご注意を!!

iOS SDK 7でImageIO Frameworkを使ってExif情報にユーザコメントを書き込む時は注意が必要 - 強火で進め
http://d.hatena.ne.jp/nakamura001/20131215/1387125345

(追記ここまで)

Exif情報の読み書きには ImgageIO.framework を使用しますのでこちらを追加してプログラムの先頭に

#import <ImageIO/ImageIO.h>

を追加します。

Exif情報を書き込んだJPEGファイルを書き出す場合は以下の様にします。

- (IBAction)exifExport {
	NSString *imgPath = [NSString stringWithFormat:@"%@/sample.jpg", [[NSBundle mainBundle] resourcePath]];
	CGImageSourceRef cgImage = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:imgPath], nil);
	NSMutableDictionary* exifDict = [[[NSMutableDictionary alloc] init] autorelease];

	[exifDict setObject:@"テストabc123" forKey:(NSString*)kCGImagePropertyExifUserComment];
	NSMutableData* imageData = [[[NSMutableData alloc] init] autorelease];
	CGImageDestinationRef dest = CGImageDestinationCreateWithData((CFMutableDataRef)imageData, CGImageSourceGetType(cgImage), 1, nil);
	CGImageDestinationAddImageFromSource(dest, cgImage, 0, 
										 (CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
														   exifDict, (NSString*)kCGImagePropertyExifDictionary, nil]);
	CGImageDestinationFinalize(dest);
	NSString *exportPath = [NSString stringWithFormat:@"%@/export.jpg", [[NSBundle mainBundle] resourcePath]];
	NSLog(@"exportPath : %@", exportPath);
	[imageData writeToFile:exportPath atomically:YES];
	CFRelease(cgImage);
	CFRelease(dest);
}

ここではアプリにの同梱した sample.jpg にコメント「テストabc123」を書き込んで export.jpg というファイル名で出力しています。

シミュレータで実行してコンソールに出力されたパスの export.jpg をMacの標準アプリ「プレビュー」で確認して下さい。プレビューでExif情報を確認する為には cmd+I でインスペクタを表示し、以下の部分を選択すると確認できます。
※シミュレータ上で作成したファイルの確認方法はこちらを参照下さい。

Exif情報を読み込む場合は以下の様になります。

- (IBAction)exifImport {
	NSString *imgPath = [NSString stringWithFormat:@"%@/sample.jpg", [[NSBundle mainBundle] resourcePath]];
	CGImageSourceRef cgImage = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:imgPath], nil);
	NSDictionary *metaDataDict = (NSDictionary *)CGImageSourceCopyPropertiesAtIndex(cgImage, 0, nil);
	if (metaDataDict) {
		NSDictionary *exifDict;
		exifDict = [metaDataDict objectForKey:(NSString *)kCGImagePropertyExifDictionary];
		if (exifDict && [exifDict count] > 0) {
			NSString *commentStr = [exifDict objectForKey:(NSString *)kCGImagePropertyExifUserComment];
			if (commentStr) {
				textView_.text = [NSString stringWithFormat:@"ユーザコメント : %@", commentStr];
			}
		}
	} else {
		textView_.text = [NSString stringWithString:@"Exif情報無し"];
	}
	[metaDataDict release];
	CFRelease(cgImage);
}

ここで使ったサンプルはこちらからDLできます。

参考サイト

こちらのプロジェクトの

BathyScaphe プロジェクト日本語トップページ - SourceForge.JP
http://sourceforge.jp/projects/bathyscaphe/

こちらのソース

View of /bathyscaphe/trunk/application/subproj/previewer/BSIPIToken.m - BathyScaphe - SourceForge.JP
http://sourceforge.jp/projects/bathyscaphe/svn/view/bathyscaphe/trunk/application/subproj/previewer/BSIPIToken.m?view=markup&root=bathyscaphe&pathrev=1177

Cocoa Wiki » CoreGraphicsでExifを扱う
http://cocoawiki.aerial.st/index.php?CoreGraphics%E3%81%A7Exif%E3%82%92%E6%89%B1%E3%81%86

Exif情報を保ったままカメラロールに保存する方法。

[AssetsLibrary] フォトライブラリの写真にExif情報を付けて保存する - Ni chicha, ni limona - 平均から抜けられない僕 - iPhoneアプリ開発グループ
http://iphone-dev.g.hatena.ne.jp/paella/20101014/1287070858