Convertir UIImage en NSData sans utiliser Uiimagepngreprésentation ou Uiimagejpegreprésentation

je dois convertir UIImage en NSData mais sans utiliser UIImagePngRepresentation ou UIImageJpegRepresentation , pour les images de photolib je peux utiliser la méthode assetlib comme mentionné ici en utilisant ALAssetsLibrary et ALAsset prendre L'Image comme NSData , mais pour l'image capturée , l'url assset n'est pas là donc dans ce cas , je dois convertir UIImage directement en octets avec exif data, comment puis-je accomplir cela ? s'il vous plaît aider

20
demandé sur Community 2013-03-06 09:33:57

3 réponses

H Bastan,

basé sur votre commentaire:

...Je veux sauver le retour d'image capturé par appareil photo, par la méthode uiimagepicker delegate dans le répertoire de document...

il ressemble à votre réel objectif est de sauver l'image avec des données EXIF au répertoire de documents et de ne pas spécifiquement obtenir L'UIImage comme un objet NSData avec les données EXIF. Dans ce cas, vous pouvez faire ce qui suit dans votre mise en œuvre de imagePickerController:didFinishPickingMediaWithInfo:

// 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);

D'après mes tests, le temps d'exécution était à peu près le même ou plus rapide que le temps d'exécution:

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

...et tu peux garder les données D'EXIF!

vous pouvez également l'envoyer dans une file d'attente en arrière-plan si vous voulez vous assurer que votre interface reste réactive:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

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

Note importante: vous aurez besoin de ajoutez le ImageIO.framework et le MobileCoreServices.framework aux phases de construction de votre cible et importez - les dans la classe où vous effectuez la sauvegarde d'image:

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

autres notes Je crois comprendre que dans ce cas, nous ne créons pas une perte de génération lorsque nous sauvegardons l'image telle que proposée dans l'exemple. Nous utilisons la propriété CGImage D'UIImage et comme la documentation l'indique:

les données D'image de Quartz sous-jacentes

17
répondu Wes 2013-04-07 04:46:41

j'ai eu un problème similaire, mais pour des raisons de SÉCURITÉ Je ne voulais pas écrire les données dans le système de fichiers par défaut comme suggéré par Wes. Je voulais aussi pouvoir ajouter des métadonnées à mon image. Ma solution était la suivante:

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

pour l'utiliser, vous feriez ce qui suit:

- (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
répondu Taz 2013-09-19 10:40:49

Vous pouvez essayer quelque chose comme cela. Vous ne savez pas si c'est la meilleure méthode. Mais vaut le coup. Incase L'URL de l'image est disponible, vous pouvez essayer initWithContentsOfUrl

NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"];
0
répondu Anil 2013-03-06 09:32:07