2013-03-04 10 views
12

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

Durch Aneinanderfügen verschiedener Beiträge zu diesem Thema konnte ich die unten angegebene Quelle als Quelle finden.

Auslösen der copyPressed Methode mit einem Knopf, ich bin in der Lage benutzerdefinierte Metadaten mit JPG-Bilder (EXIF) einzustellen:

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 in der Lage bin, die PNG-Metadaten einfach gut zu lesen, kann ich‘ t scheinen, um es zu 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; 
    }; 
} 

jedoch nichts in der Dokumentation schlägt vor, dies nicht gelingen sollte und die Anwesenheit vieler PNG-specific metadata constants schlägt sollte es gelingen.

Meine Anwendung sollte PNG verwenden, um JPG's lossy compression zu vermeiden.

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

Hinweis: Ich habe gesehen this SO question, aber es befasst sich nicht das Problem hier, wie Metadaten speziell in PNG-Bilder geschrieben werden.

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 

Antwort

4

Wenn Sie versuchen, Ihr Bild mit geänderten Metadaten

[data writeToFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"test.png"] 
     atomically:YES]; 

Und als es sehen können in Finder Eigenschaften zu speichern. Sie werden sehen, dass das Feld kCGImagePropertyPNGDescription erfolgreich eingerichtet wurde.

enter image description here

Aber wenn Sie versuchen, Metadaten dieser neuen Datei gelesen wird, wird kCGImagePropertyPNGDescription verloren.

Nach einigen Recherchen fand ich, dass PNG Metadaten nicht enthält. Aber es kann XMP metadata enthalten. Jedoch scheint ImageIO nicht mit XMP zu arbeiten.
Vielleicht können Sie versuchen, ImageMagic oder libexif zu verwenden.

Nützliche Links:
PNG Specification
Reading/Writing image XMP on iPhone/Objective-c
Does PNG support metadata fields like Author, Camera Model, etc?
Does PNG contain EXIF data like JPG?
libexif.sourceforge.net

+0

Gut zu wissen. Scheinbar kann iOS PNG-Metadaten nicht aus Dateien mit meiner Methode lesen. Wenn ich eine Möglichkeit hätte, PNG-Metadaten zu lesen, könnte ich eine Lösung haben. Wenn iOS Konstanten wie kCGImagePropertyPNGDescription hat, würde ich lieber keine externen Bibliotheken verwenden und würde lieber wissen, wie man das nur mit iOS-Bibliotheken macht. –

+0

Stellen Sie sich vor, Sie können Metadaten zum Bild hinzufügen, sind Sie sicher, dass andere Software diese Informationen lesen wird? Aus welchem ​​Grund möchten Sie Metadaten hinzufügen? –

+0

hast du eine Antwort gefunden? – Crashalot

Verwandte Themen