Meta data dictionary of UIImage does not got value

2019-04-17 03:50发布

问题:

While saving screenshot image I am trying to change meta data of UIImage object for custom title and description of image.

Imported headers

#import <AssetsLibrary/AssetsLibrary.h>
#import <ImageIO/ImageIO.h>
#import <ImageIO/CGImageProperties.h>

Inside my method

  NSData* dataOfImageFromGallery = UIImageJPEGRepresentation(imageToSave, 1.0);
  CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)dataOfImageFromGallery, NULL);

    NSMutableDictionary* metaData = (NSMutableDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(imageSource,0,NULL)); //--> metaData dictionary without ITPC key

    if (imageSource == NULL) {
        // Error loading image
        NSLog(@"ERROR while loading screenshot image: %@",error);
        return;
    }

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:NO], (NSString *)kCGImageSourceShouldCache,
                             nil];
    CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (CFDictionaryRef)options);


    CFDictionaryRef exif = CFDictionaryGetValue(imageProperties, kCGImagePropertyExifDictionary);

    if (exif) {
        NSString *dateTakenString = (NSString *)CFDictionaryGetValue(exif, kCGImagePropertyExifDateTimeOriginal);
        NSLog(@"Date Taken: %@", dateTakenString);
    }

    // set image name and keywords in IPTC metadata
    NSString *iptcKey = (NSString *)kCGImagePropertyIPTCDictionary;

    NSMutableDictionary *iptcMetadata = metaData[iptcKey];
    iptcMetadata[(NSString *)kCGImagePropertyIPTCObjectName] = @"ImageTitle";
    iptcMetadata[(NSString *)kCGImagePropertyIPTCKeywords] = @"some keywords";
    metaData[iptcKey] = iptcMetadata; 

    //write the image data to the assets library (camera roll)
    ALAssetsLibrary * library = [[ALAssetsLibrary alloc] init];
    [library writeImageToSavedPhotosAlbum:imageToSave.CGImage metadata:metaData completionBlock:nil];

Problem : The metaData dictionary has got only below objects with keys

Where kCGImagePropertyIPTCDictionary in the metaData is emtpy! Please let me know where I can find value for key {IPTC} ?

UPDATE : Reference taken from here

回答1:

A bit late, but here's how I did it:

Have a class (let's call it MetadataClass) with class method:

+ (void)addMetadata:(NSDictionary *)metadataToAdd toImageDataSampleBuffer:(CMSampleBufferRef)imageDataSampleBuffer
{
    // Grab metadata of image
    CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate);
    NSMutableDictionary *imageMetadata = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary *)metadataDict];
    CFRelease(metadataDict);

    for( NSString *metadataName in metadataToAdd )
    {
        id metadata = [metadataToAdd valueForKey:metadataName];

        if( [metadata isKindOfClass:NSDictionary.class] )
        {
            NSMutableDictionary *subDict = [imageMetadata valueForKey:metadataName];
            if( !subDict )
            {
                subDict = [NSMutableDictionary dictionary];
                [imageMetadata setValue:subDict forKey:metadataName];
            }
            [subDict addEntriesFromDictionary:metadata];
        }
        else if( [metadata isKindOfClass:NSString.class] )
            [imageMetadata setValue:metadata forKey:metadataName];
        else if( [metadata isKindOfClass:NSValue.class] )
            [imageMetadata setValue:metadata forKey:metadataName];
    }

    // set the dictionary back to the buffer
    CMSetAttachments(imageDataSampleBuffer, (CFMutableDictionaryRef)imageMetadata, kCMAttachmentMode_ShouldPropagate);
}

And how I use it:

    NSDictionary *iptc = @{
    (NSString *)kCGImagePropertyIPTCObjectTypeReference : @"kCGImagePropertyIPTCObjectTypeReference",
    (NSString *)kCGImagePropertyIPTCObjectAttributeReference : @"kCGImagePropertyIPTCObjectAttributeReference",
    (NSString *)kCGImagePropertyIPTCObjectName : @"kCGImagePropertyIPTCObjectName",
    (NSString *)kCGImagePropertyIPTCEditStatus : @"kCGImagePropertyIPTCEditStatus",
    (NSString *)kCGImagePropertyIPTCEditorialUpdate : @"kCGImagePropertyIPTCEditorialUpdate",
    (NSString *)kCGImagePropertyIPTCUrgency : @"kCGImagePropertyIPTCUrgency",
    (NSString *)kCGImagePropertyIPTCSubjectReference : @"kCGImagePropertyIPTCSubjectReference",
    (NSString *)kCGImagePropertyIPTCCategory : @"kCGImagePropertyIPTCCategory",
    (NSString *)kCGImagePropertyIPTCSupplementalCategory : @"kCGImagePropertyIPTCSupplementalCategory",
    (NSString *)kCGImagePropertyIPTCFixtureIdentifier : @"kCGImagePropertyIPTCFixtureIdentifier",
    (NSString *)kCGImagePropertyIPTCKeywords : @"kCGImagePropertyIPTCKeywords",
    (NSString *)kCGImagePropertyIPTCContentLocationCode : @"kCGImagePropertyIPTCContentLocationCode",
    (NSString *)kCGImagePropertyIPTCContentLocationName : @"kCGImagePropertyIPTCContentLocationName",
    (NSString *)kCGImagePropertyIPTCReleaseDate : @"kCGImagePropertyIPTCReleaseDate",
    (NSString *)kCGImagePropertyIPTCReleaseTime : @"kCGImagePropertyIPTCReleaseTime",
    (NSString *)kCGImagePropertyIPTCExpirationDate : @"kCGImagePropertyIPTCExpirationDate",
    (NSString *)kCGImagePropertyIPTCExpirationTime : @"kCGImagePropertyIPTCExpirationTime",
    (NSString *)kCGImagePropertyIPTCSpecialInstructions : @"kCGImagePropertyIPTCSpecialInstructions",
    (NSString *)kCGImagePropertyIPTCActionAdvised : @"kCGImagePropertyIPTCActionAdvised",
    (NSString *)kCGImagePropertyIPTCReferenceService : @"kCGImagePropertyIPTCReferenceService",
    (NSString *)kCGImagePropertyIPTCReferenceDate : @"kCGImagePropertyIPTCReferenceDate",
    (NSString *)kCGImagePropertyIPTCReferenceNumber : @"kCGImagePropertyIPTCReferenceNumber",
    (NSString *)kCGImagePropertyIPTCDateCreated : @"kCGImagePropertyIPTCDateCreated",
    (NSString *)kCGImagePropertyIPTCTimeCreated : @"kCGImagePropertyIPTCTimeCreated",
    (NSString *)kCGImagePropertyIPTCDigitalCreationDate : @"kCGImagePropertyIPTCDigitalCreationDate",
    (NSString *)kCGImagePropertyIPTCDigitalCreationTime : @"kCGImagePropertyIPTCDigitalCreationTime",
    (NSString *)kCGImagePropertyIPTCOriginatingProgram : <CFBundleName>,
    (NSString *)kCGImagePropertyIPTCProgramVersion : <CFBundleVersion>,
    (NSString *)kCGImagePropertyIPTCObjectCycle : @"kCGImagePropertyIPTCObjectCycle",
    (NSString *)kCGImagePropertyIPTCByline : @"kCGImagePropertyIPTCByline",
    (NSString *)kCGImagePropertyIPTCBylineTitle : @"kCGImagePropertyIPTCBylineTitle",
    (NSString *)kCGImagePropertyIPTCCity : @"kCGImagePropertyIPTCCity",
    (NSString *)kCGImagePropertyIPTCSubLocation : @"kCGImagePropertyIPTCSubLocation",
    (NSString *)kCGImagePropertyIPTCProvinceState : @"kCGImagePropertyIPTCProvinceState",
    (NSString *)kCGImagePropertyIPTCCountryPrimaryLocationCode : @"kCGImagePropertyIPTCCountryPrimaryLocationCode",
    (NSString *)kCGImagePropertyIPTCCountryPrimaryLocationName : @"kCGImagePropertyIPTCCountryPrimaryLocationName",
    (NSString *)kCGImagePropertyIPTCOriginalTransmissionReference : @"kCGImagePropertyIPTCOriginalTransmissionReference",
//    (NSString *)kCGImagePropertyIPTCHeadline: : @"kCGImagePropertyIPTCHeadline",
    (NSString *)kCGImagePropertyIPTCCredit : @"kCGImagePropertyIPTCCredit",
    (NSString *)kCGImagePropertyIPTCSource : @"kCGImagePropertyIPTCSource",
    (NSString *)kCGImagePropertyIPTCCopyrightNotice : @"kCGImagePropertyIPTCCopyrightNotice",
    (NSString *)kCGImagePropertyIPTCContact : @"kCGImagePropertyIPTCContact",
    (NSString *)kCGImagePropertyIPTCCaptionAbstract : @"kCGImagePropertyIPTCCaptionAbstract",
    (NSString *)kCGImagePropertyIPTCWriterEditor : @"kCGImagePropertyIPTCWriterEditor",
    (NSString *)kCGImagePropertyIPTCImageType : @"kCGImagePropertyIPTCImageType",
    (NSString *)kCGImagePropertyIPTCImageOrientation : @"kCGImagePropertyIPTCImageOrientation",
    (NSString *)kCGImagePropertyIPTCLanguageIdentifier : @"kCGImagePropertyIPTCLanguageIdentifier",
    (NSString *)kCGImagePropertyIPTCStarRating : @"kCGImagePropertyIPTCStarRating",
    (NSString *)kCGImagePropertyIPTCCreatorContactInfo : @"kCGImagePropertyIPTCCreatorContactInfo",
    (NSString *)kCGImagePropertyIPTCRightsUsageTerms : @"kCGImagePropertyIPTCRightsUsageTerms",
    (NSString *)kCGImagePropertyIPTCScene : @"kCGImagePropertyIPTCScene",
    (NSString *)kCGImagePropertyIPTCContactInfoCity : @"kCGImagePropertyIPTCContactInfoCity",
    (NSString *)kCGImagePropertyIPTCContactInfoCountry : @"kCGImagePropertyIPTCContactInfoCountry",
    (NSString *)kCGImagePropertyIPTCContactInfoAddress : @"kCGImagePropertyIPTCContactInfoAddress",
    (NSString *)kCGImagePropertyIPTCContactInfoPostalCode : @"kCGImagePropertyIPTCContactInfoPostalCode",
    (NSString *)kCGImagePropertyIPTCContactInfoStateProvince : @"kCGImagePropertyIPTCContactInfoStateProvince",
    (NSString *)kCGImagePropertyIPTCContactInfoEmails : @"kCGImagePropertyIPTCContactInfoEmails",
    (NSString *)kCGImagePropertyIPTCContactInfoPhones : @"kCGImagePropertyIPTCContactInfoPhones",
    (NSString *)kCGImagePropertyIPTCContactInfoWebURLs : @"kCGImagePropertyIPTCContactInfoWebURLs" };

    NSDictionary<NSString *, NSNumber *> *orientation = @{(NSString *)kCGImagePropertyOrientation : <image orientation as NSNumber> };

// Create a new mutable Dictionary and insert the IPTC sub-dictionary and the base orientation property.
    NSMutableDictionary *d = [NSMutableDictionary dictionary];
    d[(NSString *)kCGImagePropertyIPTCDictionary] = iptc;
    [d addEntriesFromDictionary:orientation];

    [MetadataClass addMetadata:d toImageDataSampleBuffer:imageDataSampleBuffer];

You can now create a NSData object containing the JPEG representation of the image, including the metadata:

NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]

And then, you can save the file using:

[jpegData writeToFile:<path of JPEG file> atomically:YES];