前回、書き込む方の記事を書かなかったので、今から書きます。
とりあえず、コードを貼ります。
import UIKit import AVFoundation class ViewController: UIViewController, CameraButtonDelegate, AVCapturePhotoCaptureDelegate { //viewDidLoadなど省略しています func takePicture() { let settings = AVCapturePhotoSettings() self.output.capturePhoto(with: settings, delegate: self) } func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { if let imageData = photo.fileDataRepresentation() { let exifSample = ExifSample() //exif読み込み exifSample.read(imageData) //exif書き込み exifSample.write(imageData) } }
import UIKit import ImageIO import MobileCoreServices class ExifSample: NSObject { //書き込み func write(_ data: Data) { let ciImage = CIImage(data: data) if let ci = ciImage { //exifの生成 let exif = NSMutableDictionary() exif.setObject("take a picture!!", forKey: kCGImagePropertyExifUserComment as! NSCopying) //メタデータの生成 let metaData = NSMutableDictionary() metaData.setObject(exif, forKey: kCGImagePropertyExifDictionary as! NSCopying) //ciimageをcgimageに変換 let context = CIContext(options: nil) let cgImage = context.createCGImage(ci, from: ci.extent) //書き込まれる画像データと書き込む情報の保存先の生成 let imageData = NSMutableData() let dest: CGImageDestination? = CGImageDestinationCreateWithData(imageData, kUTTypeJPEG, 1, nil) if let wrappedDest = dest, let wrappedCgImage = cgImage { //書き込み //新しく書き込まれた画像データはimageDataに保存される CGImageDestinationAddImage(wrappedDest, wrappedCgImage, metaData) CGImageDestinationFinalize(wrappedDest) //書き込み確認 confirm(imageData) } else { print("wrappedDest is nil") } } else { print("ci is nil") } } //書き込み確認 func confirm(_ newData: NSMutableData) { let newString = newData.base64EncodedString(options: .lineLength64Characters) let decode = Data(base64Encoded: newString, options: .ignoreUnknownCharacters) if let wrappedData = decode { let newCiImage = CIImage(data: wrappedData) if let wrappedNewCi = newCiImage { print(wrappedNewCi.properties) } else { print("wrappedCi is nil") } } } }
ということで、ViewController側のphotoOutputで撮影した画像データ(imageData)を渡してExifSampleのwriteで書き込みを行なっています。
書き込み時にはImageI/Oフレームワーク で提供されているCGImageDestinationなどを使いました。
書き込みたい情報はNSMutableDictionary型の変数にキーと値をセットしています。
最初のexifは「"{Exif}"」キーの下の階層にあるので、最終的には「"{Exif}"」キーの値としてセットして書き込まなければなりません。
ということで上の階層の辞書としてmetaData(こいつも NSMutableDictionary型)でキーにkCGImagePropertyExifDictionaryを指定し、先ほどのexifをセットしています。
撮影した画像データはCGImageに変換して扱っています。
CGImageDestinationCreateWithDataでCGDestinationオブジェクトを作っています。
NSMutableData型のimageDataが書き込む画像データを入れるところです。(書き込み場所の指定)
kUTTypeJPEGで書き込み後のデータタイプを指定、
1は画像ファイル中の画像数(今回は撮影した画像なので1枚)、
optionsは何かあればということですが、特にないのでnilです。
CGImageDestinationAddImageでimageDataに画像データとexif情報が追加されます。
CGImageDestinationFinalize(wrappedDest)で実際に書き込みが行われて、がっちゃんこって感じです。
元々のCGImageが更新されるようなイメージを描いていたのですが、実際には新しいものができる感じっぽいです。(だからimageDataがあると思っている。)
ちなみにCGDestinationっていうのはCGImageDestinationCreateWithDataであったようにどこに書き込むのかの場所を決めたり、
CGImageDestinationAddImage、CGImageDestinationFinalizeのように実際にデータを書き込んだりすることができるオブジェクトです。
(この辺は、ドキュメントやブログを参考に解釈したので、間違っていたらコメントをください。。。)
今回はデータオブジェクトに書き込みをしましたが、URLとかでも行けるっぽいです。
今回のブログの参考資料
CGImageDestination | Apple Developer Documentation
CGImageDestinationCreateWithData(_:_:_:_:) - Image I/O | Apple Developer Documentation
最後にgithubにコードがあるのでご参考までに。