ネイティブiOSアプリのEXIFタグに座標を追加します

すべてのiOSデバイスにインストールされている「写真」アプリケーションを使用すると、ユーザーの写真だけでなく、これらの写真が撮影された場所のマークも表示できることは誰もが知っています。 標準カメラを使用して写真を撮ると、現在の位置に関する情報が画像内のEXIFタグに自動的に入力され、地図上に新しいマークが表示されます。 この画像は、友人に送信したり、インターネットに投稿したりできます。 そして、記録された座標の助けを借りて、誰もがそのような素晴らしいショットが撮影された場所を見ることができます。 すべてが美しく快適です。

この小さなトピックのヒントは、この機能を繰り返すカメラを使用して独自のアプリケーションを作成し、(おそらく)受信した画像でいくつかのアクションを実行する必要がある場合に役立ちます(私の場合、ユーザーがいるWebサイトに新鮮な写真をアップロードする必要がありました地図上の写真や場所を表示できます)。

3つの小さな段階を区別します。これらを実装することで、目的の結果を得ることができます。
  1. デバイスのカメラから画像を受信する
  2. ユーザー座標の定義
  3. 画像に座標を書き込む

最初の2つのポイントに自分で対処するのが難しくないことを願っています。最も興味深い点である座標の記録方法について詳しく説明します。

画像を取得する(UIImagePickerControllerから私から)
UIImage *pickedImage = [[info objectForKey:UIImagePickerControllerOriginalImage] retain]; 

次に、(CLLocationクラスの)位置オブジェクトがすでにあるはずです。
 CLLocationDegrees exifLatitude = location.coordinate.latitude; CLLocationDegrees exifLongitude = location.coordinate.longitude; 

座標をEXIFタグに書き込まれる文字列に変換します
 NSString *latRef; NSString *lngRef; if (exifLatitude < 0.0) { exifLatitude = exifLatitude * -1.0f; latRef = @"S"; } else { latRef = @"N"; } if (exifLongitude < 0.0) { exifLongitude = exifLongitude * -1.0f; lngRef = @"W"; } else { lngRef = @"E"; } 

データとキーの名前を使用して辞書を作成します。
kCGImagePropertyGPSTimeStamp
kCGImagePropertyGPSLatitude
kCGImagePropertyGPSLongitude
kCGImagePropertyGPSLatitudeRef
kCGImagePropertyGPSLongitudeRef
 NSDictionary* locDict = [[NSDictionary alloc] initWithObjectsAndKeys: location.timestamp, (NSString*)kCGImagePropertyGPSTimeStamp, latRef, (NSString*)kCGImagePropertyGPSLatitudeRef, [NSNumber numberWithFloat:exifLatitude], (NSString*)kCGImagePropertyGPSLatitude, lngRef, (NSString*)kCGImagePropertyGPSLongitudeRef, [NSNumber numberWithFloat:exifLongitude], (NSString*)kCGImagePropertyGPSLongitude, nil]; 

別の辞書を作成し、上の行で作成されたlocDictを含めます。 ここで重要なのはkCGImagePropertyGPSDictionaryです
 NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init]; [metadata setObject:locDict forKey:(NSString*)kCGImagePropertyGPSDictionary]; [locDict release]; 

クラスNSDataのオブジェクトを作成し、イメージからバイトを入力します
 NSData *image = UIImageJPEGRepresentation(pickedImage, 90); 

次の魔法のコード行は、ALAssetsLibraryクラスのオブジェクトを作成します。このクラスは、写真アルバムとビデオアルバムへのアクセスを提供します(さらに、ドキュメントで詳細を確認できます)。 次に、作成したメタデータ辞書を使用して、デバイスのフォトアルバムに写真を保存します。 writeImageDataToSavedPhotosAlbumメソッドはこれに役立ち、同時に必要なEXIFタグを書き込みます。
 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeImageDataToSavedPhotosAlbum:image metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error){ if (error) { // TODO: error handling } else { // TODO: success handling } }]; [library release]; 

フォトアルバムでのみ写真が必要な場合は、ここで停止できます。 しかし、さらに先に進みます。 写真を保存する必要があるdest_dataオブジェクトを作成します
 NSMutableData *dest_data = [NSMutableData data]; 

写真のリファレンスを作成する
 CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)image, NULL); if (!source) { NSLog(@"***Could not create image source ***"); } 

タイプを示す
 CFStringRef UTI = CGImageSourceGetType(source); 

受信したデータを書き込む場所を指定します(dest_data内)
 CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)dest_data,UTI,1,NULL); if(!destination) { NSLog(@"***Could not create image destination ***"); } 

メタデータディクショナリを使用してデータを書き込みます(はい、すべて同じです)。
 CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef) metadata); [metadata release]; 

チェックします
 BOOL success = NO; success = CGImageDestinationFinalize(destination); if(!success) { NSLog(@"***Could not create data from image destination ***"); } 

メモリを消去することを忘れないでください
 CFRelease(destination); CFRelease(source); 

これで、目的のタグで画像を保存するdest_dataオブジェクトができました。 あなたの裁量で使用することができます。

ヘッダーファイルに次の行を追加します
 #import <CoreFoundation/CoreFoundation.h> #import <AssetsLibrary/ALAssetsLibrary.h> #import <ImageIO/ImageIO.h> 

そして、必要なフレームワークを接続することを忘れないでください。

終わりのない質問と最後まで読んでくれたすべての人への答えをくれたstackoverflowに感謝します。

Source: https://habr.com/ru/post/J122889/


All Articles