不使用UIImagePng表示或UIImageJpegRepresentation将UIImage转换为NSData

时间:2013-03-06 05:33:58

标签: ios uiimage nsdata assets uiimagepngrepresentation

我需要将UIImage转换为NSData但不使用UIImagePngRepresentationUIImageJpegRepresentation,对于来自photolib的图片,我可以使用此处提到的assetlib方法Using ALAssetsLibrary and ALAsset take out Image as NSData ,但是对于捕获的图像,assset url不存在,因此在这种情况下我需要将UIImage直接转换为带有exif数据的字节,我该如何实现?请帮忙

3 个答案:

答案 0 :(得分:21)

我遇到了类似的问题,但出于安全考虑,我不想按照Wes的建议将数据写入默认文件系统。我还希望能够为我的图像添加元数据。我的解决方案如下:

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

要使用它,您需要执行以下操作:

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

    // ...
}

答案 1 :(得分:17)

H Bastan,

根据您的评论:

  

...我想通过设备相机保存捕获的图像,通过文档目录中的UIImagepicker委托方法...

看起来你的真正的目标是将带有EXIF数据的图像保存到文档目录中,而不是专门将UIImage作为带有EXIF数据的NSData对象。在这种情况下,您可以在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);

从我的测试中,执行时间与执行时间大致相同或更快:

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

...你可以保留EXIF数据!

如果您想确保您的用户界面保持响应,您也可以将其调度到后台队列:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

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

重要提示:您需要将ImageIO.frameworkMobileCoreServices.framework添加到目标的构建阶段,然后将其导入到保存图像的类中: / p>

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

其他说明 我的理解是,在这种情况下,我们不会在保存图像时产生代丢失,如示例中所提出的那样。我们正在使用UIImage的CGImage属性,并且文档说明:

  

底层的Quartz图像数据

答案 2 :(得分:0)

你可以尝试这样的事情。不确定它是否是最好的方法。但值得一试。如果图片网址可用,您可以尝试initWithContentsOfUrl

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