I am debugging an app layout issue where I'm comparing thousands of screenshots of the application and checking for anomalies. I want to add some debugging information to the UIImage when it is saved to disk so I can compare them later as I read across all the written screenshots. I am currently looking at CGImageProperties which has good references online like https://ikyle.me/blog/2020/ios-metadata-from-file. Unfortunately, this never seems to work for me on my local iOS simulator (where I am running this code).
Screenshot code:
UIGraphicsBeginImageContextWithOptions(element.size, NO, screen.scale);
[view drawViewHierarchyInContext....];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
So, now I am trying to add some properties to this image:
NSData *imageData = UIImagePNGRepresentation(image);
// NOTE: This can be any property that allows a long string.
NSDictionary *prop = @{ (NSString *)kCGImagePropertyGPSLongitudeRef: @"E" };
// Get source of the file.
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);
CFStringRef UTI = CGImageSourceGetType(source);
// Create empty data to be written to.
NSMutableData *updatedData = [NSMutableData data];
// Create a destination and add the source data with the properties.
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)updatedData, UTI, 1, NULL);
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)[prop mutableCopy]);
CGImageDestinationFinalize(destination);
CFRelease(destination);
CFRelease(source);
UIImage *imageWithProperties = [UIImage updatedData];
At this point, I have an image that will hopefully have the new properties added to them. However, if I try to get the properties:
CGImageSourceRef sourceForImageWithProperties = CGImageSourceCreateWithData((__bridge CFDataRef)UIImagePNGRepresentation(imageWithProperties), NULL);
CFDictionaryRef imagePropertiesDict = CGImageSourceCopyPropertiesAtIndex(sourceForImageWithProperties, 0, NULL);
NSLog(@"%@", (__bridge NSDictionary *)(imagePropertiesDict));
This unfortunately, has never worked for me even though most example seem to be the same as above. Properties invariably are:
{
ColorModel = RGB;
Depth = 8;
HasAlpha = 1;
PixelHeight = 132;
PixelWidth = 1059;
ProfileName = "sRGB IEC61966-2.1";
"{Exif}" = {
ColorSpace = 1;
PixelXDimension = 1059;
PixelYDimension = 132;
};
"{PNG}" = {
Chromaticities = (
"0.3127",
"0.329",
"0.64",
"0.33",
"0.3",
"0.6000000000000001",
"0.15",
"0.06"
);
Gamma = "0.45455";
InterlaceType = 0;
sRGBIntent = 0;
};
}
I'd love to know what I am doing wrong here. I have also tried the following:
- Writing the properties and saving the image to disk using NSFileManager and then trying to read back from the saved image.
- Extracting the CGImage out from the UIImage using code similar to Converting CGImageRef to NSData and then adding the properties and then creating a new UIImage with this CGImage and getting the properties out from both the CGImage and UIImage. This has also had no major changes to the properties.
- Trying to get the properties before
UIGraphicsEndImageContext()
, just to try.
Can anyone please try to explain what I am missing here? To repro, take the code above (get a UIImage in any way and then update the metadata). Does this method no longer work with Xcode 14 and iOS 16?
I just need to attach some data / metadata as an NSArray or an NSString to an image that's saved to disk. Note: associated objects
will not work for me. Any other possible solutions would be appreciated.