I can't seem to get image metadata to be written to the image correctly if the key/val is already present in the original image metadata with CGImageDestination. It works just fine if it they key/val is not present in the original metadata.
It's almost as though image metadata properties in the original image take precedence over modifications. Is this some kind of byzantine formatting issue I am not aware of, where I need to populate the key/val in some unusual way, a bug, or? Anyone else seen this?
Code and output below, for both cases where it works properly (if the value is not already set) and fails to write (if the value is already set to something else).
Any help appreciated greatly appreciated.
Here is where/how I create the image NSData:
// convert the existing asset to nsdata to overwrite itself
ALAssetRepresentation* rep = [asset defaultRepresentation];
Byte* buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
NSData* imageData = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
// write the metadata directly into the nsdata of the image itself
NSData* newImage = [self writeMetadataIntoImageData:imageData metadata:newMetadata];
Here is the actual modification of the metadata:
- (NSData*)writeMetadataIntoImageData:(NSData*)imageData metadata:(NSMutableDictionary*)metadataAsMutable
{
// create an imagesourceref
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);
// read and log pre write metadata
NSDictionary* metadata = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source,0,NULL));
NSLog(@"Before:\n------------------------------%@\n------------------------------", metadata);
// set the new metadata keys here
NSMutableDictionary* iptc = [metadataAsMutable[(NSString*)kCGImagePropertyIPTCDictionary] mutableCopy];
if (!iptc)
{
iptc = [NSMutableDictionary dictionaryWithCapacity:1];
}
iptc[(NSString*)kCGImagePropertyIPTCCaptionAbstract] = @"Hardcoded Caption";
metadataAsMutable[(NSString*)kCGImagePropertyIPTCDictionary] = iptc;
// log the new metadata as we want it written
NSLog(@"Parameter:\n------------------------------%@\n------------------------------", metadataAsMutable);
// this is the type of image (e.g., public.jpeg)
CFStringRef UTI = CGImageSourceGetType(source);
// create a new data object and write the new image into it
NSMutableData *dest_data = [NSMutableData data];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)dest_data,UTI,1,NULL);
if(!destination)
{
NSLog(@"Error: Could not create image destination");
}
// add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
CGImageDestinationAddImageFromSource(destination,source,0, (__bridge CFDictionaryRef) metadataAsMutable);
BOOL success = NO;
success = CGImageDestinationFinalize(destination);
if(!success)
{
NSLog(@"Error: Could not create data from image destination");
}
// read and log post write metadata
CGImageSourceRef source2;
source2 = CGImageSourceCreateWithData((__bridge CFDataRef) dest_data, NULL);
NSDictionary *metadata2 = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source2,0,NULL));
NSLog(@"After:\n------------------------------%@\n------------------------------", metadata2);
// cleanup
CFRelease(destination);
// return the new data
return dest_data;
}
Here are the NSLogs for when the image has an existing value for the key:
Before:
------------------------------{
<...snip...>
"{IPTC}" = {
"Caption/Abstract" = Blurry;
DateCreated = 20130923;
DigitalCreationDate = 20130923;
DigitalCreationTime = 173815;
Keywords = (
fake
);
SupplementalCategory = (
fake
);
TimeCreated = 173815;
};
<...snip...>
}
------------------------------
Parameter:
------------------------------{
<...snip...>
"{IPTC}" = {
"Caption/Abstract" = "Hardcoded Caption";
DateCreated = 20130923;
DigitalCreationDate = 20130923;
DigitalCreationTime = 173815;
Keywords = (
fake
);
SupplementalCategory = (
fake
);
TimeCreated = 173815;
};
<...snip...>
}
------------------------------
After:
------------------------------{
<...snip...>
"{IPTC}" = {
"Caption/Abstract" = Blurry;
DateCreated = 20130923;
DigitalCreationDate = 20130923;
DigitalCreationTime = 173815;
Keywords = (
fake
);
SupplementalCategory = (
fake
);
TimeCreated = 173815;
};
<...snip...>
}
------------------------------
Here are the NSLogs for when the image has no value for the key:
Before:
------------------------------{
<...snip...>
"{IPTC}" = {
DateCreated = 20130925;
DigitalCreationDate = 20130925;
DigitalCreationTime = 192856;
Keywords = (
fake
);
SupplementalCategory = (
fake
);
TimeCreated = 192856;
};
<...snip...>
}
------------------------------
Parameter:
------------------------------{
<...snip...>
"{IPTC}" = {
"Caption/Abstract" = "Hardcoded Caption";
DateCreated = 20130925;
DigitalCreationDate = 20130925;
DigitalCreationTime = 192856;
Keywords = (
fake
);
SupplementalCategory = (
fake
);
TimeCreated = 192856;
};
<...snip...>
}
------------------------------
After:
------------------------------{
<...snip...>
"{IPTC}" = {
"Caption/Abstract" = "Hardcoded Caption";
DateCreated = 20130925;
DigitalCreationDate = 20130925;
DigitalCreationTime = 192856;
Keywords = (
fake
);
SupplementalCategory = (
fake
);
TimeCreated = 192856;
};
<...snip...>
}
------------------------------
In the metadata screen, you can change the Date/Time taken next to the field Date Time Original under Camera Data (exif). You can also batch change dates by selecting multiple files and changing the date the same way for a group of images.
Navigate to the folder holding the images you want to edit. Select the file (or files) you wish to delete metadata from. Right-click and select Properties, then Details. Select Remove Properties and Personal Information.
To edit the metadata on image files, right-click the file and select Properties. In the image properties, click on the Details tab. The details tab shows all the metadata contained within the photograph. You can quickly edit the information by clicking the value field next to the property.
According to the IPTC documentation the description field is bound to the TIFF and EXIF address. changing the value in the TIFF it updates also the IPTC entry! thank you user2452250 for the tip.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With