前回、書き込む方の記事を書かなかったので、今から書きます。
とりあえず、コードを貼ります。
import UIKit
import AVFoundation
class ViewController: UIViewController, CameraButtonDelegate, AVCapturePhotoCaptureDelegate {
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()
exifSample.read(imageData)
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 {
let exif = NSMutableDictionary()
exif.setObject("take a picture!!", forKey: kCGImagePropertyExifUserComment as! NSCopying)
let metaData = NSMutableDictionary()
metaData.setObject(exif, forKey: kCGImagePropertyExifDictionary as! NSCopying)
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 {
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にコードがあるのでご参考までに。
https://github.com/2takaanthony85/ReadAndWriteExif