你如何覆盖图像元数据?

时间:2013-09-26 16:44:26

标签: ios objective-c cocoa metadata

如果使用CGImageDestination在原始图像元数据中已经存在key / val,我似乎无法正确地将图像元数据写入图像。如果原始元数据中没有key / val,它就可以正常工作。

几乎就像原始图像中的图像元数据属性优先于修改一样。这是我不知道的某种拜占庭格式问题,我需要以某种不寻常的方式填充键/ val,一个bug,还是?其他人看过这个吗?

下面的代码和输出,对于它正常工作的两种情况(如果值尚未设置)并且无法写入(如果该值已经设置为其他值)。

非常感谢任何帮助。

以下是创建图像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];

以下是元数据的实际修改:

- (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;
}

以下是图像具有密钥现有值的NSLog:

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...>
}
------------------------------

以下是图像没有密钥值的NSLog:

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...>
}
------------------------------

1 个答案:

答案 0 :(得分:3)

根据IPTC文档,描述字段绑定到TIFF和EXIF地址。更改TIFF中的值也会更新IPTC条目! 谢谢user2452250的提示。