wake-up-neo.com

Konvertieren Sie UIImage in NSData, ohne UIImagePngrepresentation oder UIImageJpegRepresentation zu verwenden

Ich muss UIImage in NSData konvertieren, aber ohne UIImagePngRepresentation oder UIImageJpegRepresentation. Für Bilder aus Photolib kann ich die hier erwähnte Assetlib-Methode verwenden Bei Verwendung von ALAssetsLibrary und ALAsset nehmen Sie Image als NSData aus in diesem Fall muss ich UIImage direkt in Bytes mit Exif-Daten konvertieren. Wie kann ich das erreichen? Bitte helfen Sie

21
H Bastan

H Bastan,

Basierend auf Ihrem Kommentar:

... Ich möchte das aufgenommene Bild mit der Gerätekamera über die UIImagepicker-Delegatenmethode im Dokumentverzeichnis speichern.

Ihr Ziel real sieht so aus, dass Sie das Bild mit den EXIF-Daten im Dokumentverzeichnis speichern und nicht speziell die UIImage als NSData-Objekt mit den EXIF-Daten erhalten. In diesem Fall können Sie in Ihrer Implementierung von imagePickerController:didFinishPickingMediaWithInfo: Folgendes tun

// Get your image.
UIImage *capturedImage = [info objectForKey:UIImagePickerControllerOriginalImage];

// Get your metadata (includes the EXIF data).
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];

// Create your file URL.
NSFileManager *defaultManager = [NSFileManager defaultManager];
NSURL *docsURL = [[defaultManager URLsForDirectory:NSDocumentDirectory
                                         inDomains:NSUserDomainMask] lastObject];
NSURL *outputURL = [docsURL URLByAppendingPathComponent:@"imageWithEXIFData.jpg"];

// Set your compression quuality (0.0 to 1.0).
NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
[mutableMetadata setObject:@(1.0) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality];

// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, kUTTypeJPEG , 1, NULL);
if (imageDestination == NULL ) {

    // Handle failure.
    NSLog(@"Error -> failed to create image destination.");
    return;
}

// Add your image to the destination.
CGImageDestinationAddImage(imageDestination, capturedImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata);

// Finalize the destination.
if (CGImageDestinationFinalize(imageDestination) == NO) {

    // Handle failure.
    NSLog(@"Error -> failed to finalize the image.");
}

CFRelease(imageDestination);

Von meinen Tests war die Ausführungszeit ungefähr gleich oder schneller als die Ausführung:

NSData *data = UIImageJPEGRepresentation(capturedImage, 1.0);
[data writeToURL:outputURL atomically:YES];

... und Sie behalten die EXIF-Daten!

Sie können es auch an eine Hintergrundwarteschlange senden, wenn Sie sicherstellen möchten, dass Ihre Benutzeroberfläche reaktionsfähig bleibt:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

    // Do the image saving here...
});

Wichtiger Hinweis: Sie müssen den ImageIO.framework und MobileCoreServices.framework zu den Erstellungsphasen Ihres Ziels hinzufügen und sie in die Klasse importieren, in der Sie das Bild speichern:

#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

Andere Hinweise Ich verstehe, dass in diesem Fall beim Speichern des Bildes, wie im Beispiel vorgeschlagen, kein Generierungsverlust entsteht. Wir verwenden die UIImage-Eigenschaft CGImage und laut Dokumentation heißt es:

Die zugrunde liegenden Quarzbilddaten

17
Wes

Ich hatte ein ähnliches Problem, aber aus Sicherheitsgründen wollte ich die Daten nicht wie von Wes vorgeschlagen in das Standarddateisystem schreiben. Ich wollte auch Metadaten zu meinem Bild hinzufügen können. Meine Lösung war wie folgt:

- (NSData *)dataFromImage:(UIImage *)image metadata:(NSDictionary *)metadata mimetype:(NSString *)mimetype
{
    NSMutableData *imageData = [NSMutableData data];
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mimetype, NULL);
    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, uti, 1, NULL);

    if (imageDestination == NULL)
    {
        NSLog(@"Failed to create image destination");
        imageData = nil;
    }
    else
    {
        CGImageDestinationAddImage(imageDestination, image.CGImage, (__bridge CFDictionaryRef)metadata);

        if (CGImageDestinationFinalize(imageDestination) == NO)
        {
            NSLog(@"Failed to finalise");
            imageData = nil;
        }
        CFRelease(imageDestination);
    }

    CFRelease(uti);

    return imageData;
}

Um es zu verwenden, würden Sie Folgendes tun:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
    NSString *mimeType = @"image/jpeg"; // ideally this would be dynamically set. Not defaulted to a jpeg!

    // you could add to the metadata dictionary (after converting it to a mutable copy) if you needed to.

    // convert to NSData
    NSData *imageData = [self dataFromImage:image metadata:metadata mimetype:mimeType];

    // ...
}
21
Taz

Sie können so etwas versuchen. Nicht sicher, ob es die beste Methode ist. Aber einen Versuch wert. Wenn die Bild-URL verfügbar ist, können Sie initWithContentsOfUrl versuchen.

NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"];
0
Anil