2017-06-06 19 views
1

Ich versuche, ein uiimage zu kopieren und die Metadaten zu ändern, ohne das Bild neu zu codieren, um keine JPG-Artefakte zu verursachen (ich kenne den Code unten Reencodes, aber das ist nur so, dass es ausgeführt werden kann testen). CGImageDestinationCopyImageSource soll die Quelle eines Bildes kopieren, ohne es neu zu codieren, aber wenn ich diese Funktion verwende, scheitert CGImageDestinationFinalize. Ich versuche, diese technische Anmerkung zu folgen https://developer.apple.com/library/content/qa/qa1895/_index.html Irgendeine Idee, warum CGImageDestinationFinalize mit dem folgenden Code scheitern würde?CGImageDestinationFinalize schlägt fehl, wenn CGImageDestinationCopyImageSource

-(NSData *)copyImageAndChangeMetaData:(UIImage *)image { 

    NSData *imageData = UIImageJPEGRepresentation(image, 1.0); 

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); 
    NSLog(@" source: 0x%x", source); 
    if (source == NULL) { 
     NSLog(@" source is NULL"); 
    } 

    CFStringRef UTI = CGImageSourceGetType(source); 
    NSLog(@" UTI: %@", (__bridge NSString *)UTI); 
    if (UTI == NULL) { 
     NSLog(@" UTI is NULL"); 
    } 

    NSMutableData *dest_data = [NSMutableData data]; 
    CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)dest_data, UTI, 1, NULL); 
    if (!destination) 
    { 
     NSLog(@"Image Data Error: Could not create image destination"); 
    } 

    CFMutableDictionaryRef metadata = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 

    int orient = 8; 
    CFNumberRef orientRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &orient); 
    CFDictionarySetValue(metadata, kCGImageDestinationOrientation, orientRef); 

    CFStringRef dateStringRef = CFStringCreateWithCString(kCFAllocatorDefault, "2017-06-06T17:31:46Z", kCFStringEncodingASCII); 
    CFDictionarySetValue(metadata, kCGImageDestinationDateTime, dateStringRef); 

    CFErrorRef errorRef = nil; 
    if (!CGImageDestinationCopyImageSource(destination, source, metadata, &errorRef)) { 
     CFStringRef error_description = CFErrorCopyDescription(errorRef); 

     NSString *errorDescription = (__bridge NSString *)error_description; 
     NSLog(@"Image Data Error: Error copying image data: %@", errorDescription); 

     CFRelease(error_description); 
    } 

    BOOL success = NO; 
    success = CGImageDestinationFinalize(destination); 
    if (!success) 
    { 
     NSLog(@"Image Data Error: Could not finalize image"); 
    } 
    if (source != NULL) { 
     CFRelease(source); 
    } 

    if (destination != NULL) { 
     CFRelease(destination); 
    } 

    return dest_data; 
} 

Antwort

3

Nach HeaderDoc Dokumentation von Apple für CGImageDestinationCopyImageSource() Funktion in der Datei <ImageIO/CGImageDestination.h>:

CGImageDestinationFinalize() soll nicht später genannt werden - das Ergebnis wird zu dem Ziel, wenn diese Funktion zurückkehrt gespeichert.

+0

Das ist eine sehr seltsame API, alles in allem betrachtet. –