Last active
September 24, 2024 02:12
-
-
Save lacyrhoades/09d8a367125b6225df5038aec68ed9e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import MobileCoreServices | |
import ImageIO | |
let sourceOptions: [String: AnyObject] = [kCGImageSourceTypeIdentifierHint as String: kUTTypeJPEG] | |
let cfSourceOptions = sourceOptions as CFDictionary | |
let image = UIImage(named: "input.jpg")! | |
let data = UIImageJPEGRepresentation(image, 1.0) | |
let source: CGImageSource = CGImageSourceCreateWithData(data as! CFData, cfSourceOptions)! | |
let filepath = NSTemporaryDirectory().appending("out.jpg") | |
print("Output file:") | |
print(filepath) | |
let fileURL: URL = URL(fileURLWithPath: filepath) | |
let destination: CGImageDestination = CGImageDestinationCreateWithURL(fileURL as CFURL, kUTTypeJPEG, 1, nil)! | |
var makeTag = CGImageMetadataTagCreate( | |
kCGImageMetadataNamespaceTIFF, kCGImageMetadataPrefixTIFF, kCGImagePropertyTIFFMake, .string, "Make" as CFString | |
)! | |
var modelTag = CGImageMetadataTagCreate( | |
kCGImageMetadataNamespaceTIFF, kCGImageMetadataPrefixTIFF, kCGImagePropertyTIFFModel, .string, "Model" as CFString | |
)! | |
var metaDatas = CGImageMetadataCreateMutable() | |
var tagPath = "tiff:Make" as CFString | |
var result = CGImageMetadataSetTagWithPath(metaDatas, nil, tagPath, makeTag) | |
tagPath = "tiff:Model" as CFString | |
result = CGImageMetadataSetTagWithPath(metaDatas, nil, tagPath, modelTag) | |
let destOptions: [String: AnyObject] = [ | |
kCGImageDestinationMergeMetadata as String: NSNumber(value: 1), | |
kCGImageDestinationMetadata as String: metaDatas | |
] | |
let cfDestOptions = destOptions as CFDictionary | |
var error: Unmanaged<CFError>? | |
var errorPtr: UnsafeMutablePointer<CFError> | |
withUnsafeMutablePointer(to: &error, { ptr in | |
result = CGImageDestinationCopyImageSource(destination, source, cfDestOptions, ptr) | |
print(String(format: "Write image to file result: %@", result ? "Success" : "Failed")) | |
print(String(format: "With error: %@", error.debugDescription)) | |
}) | |
let writeResult = CGImageDestinationFinalize(destination) | |
// This is false, and you may see an error like: | |
// " ImageIO: finalize:2031: not allowed for image destination that was updated with CGImageDestinationCopyImageSource " | |
// But, in practice, it works. The file is there and the metadata is correct. | |
print(writeResult) |
And just a note to anyone trying this: you can only add data for tags that are "known". If you try to make your own tags they just disappear. Even the most minor errors in the strings, like the tagPath, will cause the data to disappear when it's saved. To add to the annoyance, Apple's documentation is wrong - most of the possible tags are shown as being CFString types, but there are many that are actually numbers and will fail to be saved if you don't provide a number. An example is TIFFOrientation, where it claims to be a CFString but you must provide a number using NSNumber(value:5) or it simply won't save.
@maurymarkowitz no idea about errorPtr
I ended up not having that line in production. Thanks for the tips too!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What is the purpose of line 52:
var errorPtr: UnsafeMutablePointer
It is not used anywhere, and Xcode complains about that.