So schreiben Sie benutzerdefinierte Metadaten in PNG-Bilder in iOS

Meine Anwendung sollte in der Lage sein, benutzerdefinierte Metadateneinträge in PNG-Bilder für den Export in das UIPasteboard zu schreiben.

Indem ich verschiedene Beiträge zu diesem Thema zusammengestellt habe, konnte ich die unten angegebene Klasse als Quelle finden.

Durch Auslösen der copyPressed-Methode mit einer Schaltfläche kann ich benutzerdefinierte Metadaten mit JPG-Bildern (EXIF) festlegen:

Image[6101:907] found jpg exif dictionary
Image[6101:907] checking image metadata on clipboard
Image[6101:907] {
    ColorModel = RGB;
    Depth = 8;
    Orientation = 1;
    PixelHeight = 224;
    PixelWidth = 240;
    "{Exif}" =     {
        ColorSpace = 1;
        PixelXDimension = 240;
        PixelYDimension = 224;
        UserComment = "Here is a comment";
    };
    "{JFIF}" =     {
        DensityUnit = 0;
        JFIFVersion =         (
            1,
            1
        );
        XDensity = 1;
        YDensity = 1;
    };
    "{TIFF}" =     {
        Orientation = 1;
    };
}

Obwohl ich die PNG-Metadaten einwandfrei lesen kann, kann ich scheinbar nicht darauf schreiben:

Image[6116:907] found png property dictionary
Image[6116:907] checking image metadata on clipboard
Image[6116:907] {
    ColorModel = RGB;
    Depth = 8;
    PixelHeight = 224;
    PixelWidth = 240;
    "{PNG}" =     {
        InterlaceType = 0;
    };
}

Nichts in der Dokumentation deutet jedoch darauf hin, dass dies fehlschlagen sollte und viele vorhanden sindPNG-spezifische Metadatenkonstanten schlägt vor, es sollte gelingen.

Meine Anwendung sollte PNG verwenden, um dies zu vermeidenJPGs verlustbehaftete Komprimierung.

Warum kann ich in iOS keine benutzerdefinierten Metadaten für ein PNG-Bild im Speicher festlegen?

Hinweis: Ich habe gesehendiese SO FrageDas Problem wird hier jedoch nicht behoben, da hier speziell das Schreiben von Metadaten in PNG-Bilder beschrieben wird.

IMViewController.m

#import "IMViewController.h"
#import <ImageIO/ImageIO.h>

@interface IMViewController ()

@end

@implementation IMViewController

- (IBAction)copyPressed:(id)sender
{
//    [self copyJPG];
    [self copyPNG];
}

-(void)copyPNG
{
    NSData *pngData = UIImagePNGRepresentation([UIImage imageNamed:@"wow.png"]);
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)pngData, NULL);
    NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
    NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
    NSMutableDictionary *dict = [[mutableMetadata objectForKey:(NSString *) kCGImagePropertyPNGDictionary] mutableCopy];

    if (dict) {
        NSLog(@"found png property dictionary");
    } else {
        NSLog(@"creating png property dictionary");
        dict = [NSMutableDictionary dictionary];
    }

    // set values on the root dictionary
    [mutableMetadata setObject:@"Name of Software" forKey:(NSString *)kCGImagePropertyPNGDescription];
    [mutableMetadata setObject:dict forKey:(NSString *)kCGImagePropertyPNGDictionary];

    // set values on the internal dictionary
    [dict setObject:@"works" forKey:(NSString *)kCGImagePropertyPNGDescription];

    CFStringRef UTI = CGImageSourceGetType(source);
    NSMutableData *data = [NSMutableData data];
    CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef) data, UTI, 1, NULL);

    if (!destination) {
        NSLog(@">>> Could not create image destination <<<");

        return;
    }

    CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef) mutableMetadata);

    BOOL success = CGImageDestinationFinalize(destination);

    if (!success) {
        NSLog(@">>> Error Writing Data <<<");
    }

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];

    [pasteboard setData:data forPasteboardType:@"public.png"];
    [self showPNGMetadata];
}

-(void)copyJPG
{
    NSData *jpgData = UIImageJPEGRepresentation([UIImage imageNamed:@"wow.jpg"], 1);
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) jpgData, NULL);
    NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
    NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
    NSMutableDictionary *exif = [[mutableMetadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];

    if (exif) {
        NSLog(@"found jpg exif dictionary");
    } else {
        NSLog(@"creating jpg exif dictionary");
    }

    // set values on the exif dictionary
    [exif setObject:@"Here is a comment" forKey:(NSString *)kCGImagePropertyExifUserComment];
    [mutableMetadata setObject:exif forKey:(NSString *)kCGImagePropertyExifDictionary];

    CFStringRef UTI = CGImageSourceGetType(source);
    NSMutableData *data = [NSMutableData data];
    CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef) data, UTI, 1, NULL);

    if(!destination) {
        NSLog(@">>> Could not create image destination <<<");

        return;
    }

    CGImageDestinationAddImageFromSource(destination,source, 0, (__bridge CFDictionaryRef) mutableMetadata);

    BOOL success = CGImageDestinationFinalize(destination);

    if (!success) {
        NSLog(@">>> Could not create data from image destination <<<");
    }

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];

    [pasteboard setData:data forPasteboardType:@"public.jpeg"];
    [self showJPGMetadata];
}

-(void)showJPGMetadata
{
    NSLog(@"checking image metadata on clipboard");

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
    NSData *data = [pasteboard dataForPasteboardType:@"public.jpeg"];

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL);

    NSLog(@"%@", metadata);
}

-(void)showPNGMetadata
{
    NSLog(@"checking image metadata on clipboard");

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
    NSData *data = [pasteboard dataForPasteboardType:@"public.png"];

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL);

    NSLog(@"%@", metadata);
}

@end

Antworten auf die Frage(1)

Ihre Antwort auf die Frage