Swift

写真のExif情報変えて、ハワイに行ったふりをするカメラアプリ

More than 1 year has passed since last update.

画像+119.jpg

はじめに

TBS「写真から住所を特定します」ドヤ顔でExif情報を解説 [2014/07/25]
http://kenmonews.blog15.mmm.me/mmmblog-entry-5433.html

スマートフォンのカメラアプリの多くが、GPSからの位置情報を画像のメタデータに埋め込んでしまう事が原因で
家の住所や、個人が特定されてしまうといったことが問題になっています。

今回は、安全なカメラアプリを作る事を前提に、Exifメタ情報が埋め込まれないようにするだけでなく、
すべての写真情報に「ハワイのワイキキビーチ」の座標を埋め込んで、
「夏休みハワイに行ったんやで」と自慢できるアプリが作れないか試してみました。

(※注)
FacebookやTwitterなどはアップロードするときに安全のためにメタ情報は削除されるようになっています。
(ただし、その他の掲示板やブログなどでは、メタ情報がそのまま残ってしまうものもあります)

Exifとは

(引用)Exifとは、デジタルカメラで撮影した画像データに、情報を追加して保存できる、画像ファイル形式の規格。
撮影した画像データと併せて、撮影した日時や場所、カメラの機種、絞り値、画素数、ISO感度といった情報を記録することができる。
http://www.sophia-it.com/content/Exif

カメラ撮影を行う

UIImagePickerController ... 簡単に撮影できるがUIのカスタマイズなどができない
AVFoundation.framework ... シャッター音、フィルターetcカスタマイズができる

カメラ撮影を行う為にはどちらを使っても良いのですが
UIImagePickerControllerの場合は、手軽な反面、写真を撮影した画像にフィルターをかけたり画像を合成したり、
細かい操作ができないという不便さがあるので、AVFoundationを使用してみます。

    //非同期で静止画をキャプチャ
    dispatch_async(self.sessionQueue, {
        //キャプチャを撮る+自動的にシャッター音が鳴る
        self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.stillImageOutput.connectionWithMediaType(AVMediaTypeVideo), completionHandler: {
            (imageDataSampleBuffer: CMSampleBuffer?, error: NSError?) -> Void in

            //CoreMediaのままではUIKitで使いにくいので変換
            var imageData: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer?)
            var image: UIImage = UIImage(data: imageData)
    })

Exif情報を作成する

Exif情報のキーは「kCGImagePropertyExifDictionary」が定義されています。
この中にGPSの情報を始め、カメラの機種など色々な情報を詰め込むことができます。
例として写真のコメントを自由に記述できる「kCGImagePropertyExifUserComment」にコメントを記述してみます

            //EXIF情報を作成する
            var exif = NSMutableDictionary() 

            //Exifに写真のコメントをセットする
            exif.setObject("I love Waikiki Beach",forKey:kCGImagePropertyExifUserComment)

            //メタデータを作成する
            var metaData = NSMutableDictionary()
            metaData.setObject(exif,forKey:kCGImagePropertyExifDictionary)

次に本題であるGPSの情報にワイキキビーチの座標を入れた偽のメタ情報を作成します

            //ワイキキビーチの位置情報を作成する
            var gps = NSMutableDictionary()
            gps.setObject("N",forKey:kCGImagePropertyGPSLatitudeRef)
            gps.setObject(21.275468,forKey:kCGImagePropertyGPSLatitude)
            gps.setObject("W",forKey:kCGImagePropertyGPSLongitudeRef)
            gps.setObject(157.825294,forKey:kCGImagePropertyGPSLongitude)
            gps.setObject(0,forKey:kCGImagePropertyGPSAltitudeRef)
            gps.setObject(0,forKey:kCGImagePropertyGPSAltitude)

            //ExifにGPS情報をセットする
            exif.setObject(gps,forKey:kCGImagePropertyGPSDictionary);

撮影された画像を保存する

通常撮影された画像をアルバムに保存する手段として
「UIImageWriteToSavedPhotosAlbum」を使用することが多いと思います。
しかし、この関数ではメタ情報を保存することができない為「AssetsLibrary」を使用します。

            //メタデータを保存するためにはAssetsLibraryを使用する
            var library : ALAssetsLibrary = ALAssetsLibrary()
            library.writeImageToSavedPhotosAlbum(image.CGImage,metadata: metaData, completionBlock:{
                (assetURL: NSURL!, error: NSError!) -> Void in
                println("Success")
            })

撮影した写真をFacebookにあげてみましょう。

写真をアップするときに、ワイキキ周辺の情報が出てくるようになりましたね!

IMG_2619.jpg

IMG_2618.jpg

おしまい

えっと、写真に埋め込まれた位置情報に誰が気付くんだよとか、お土産を要求されたらどうすんのさとか、
いろいろと課題はありますが、基本的なカメラアプリの作り方とExifのいじり方が
理解できたところで今回の記事はおしまいとなります〜。

今回のソースコード
https://github.com/oggata/GeolocationCameraDemo

参考

https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/CGImageProperties_Reference/Reference/reference.html#//apple_ref/doc/constant_group/EXIF_Dictionary_Keys

OpenCVを利用したリアルタイムフィルタリングの基本
http://dev.classmethod.jp/smartphone/iphone/opencv-video/

シャッター音の鳴らないカメラアプリを実装する
http://qiita.com/shu223/items/851c3cfa8ca076a5ece3