UIImageJPEGRepresentation()线程安全吗?

ric*_*son 9 iphone core-graphics objective-c uiimage ios

我正在缩放和裁剪a UIImage,我希望能够在一个线程安全的块中完成它.我在文档中找不到是否UIImageJPEGRepresentation是线程安全的.

在下面的代码中,我裁剪并缩放a CGImage,然后我UIImage从中创建一个并获得UIImageJPEGRepresentation.这个块的最终目标是NSData*从缩放/裁剪版本中获取.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    CGImageRef imageRef = photo.CGImage;
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    CGContextRef bitmap;

    if (photo.imageOrientation == UIImageOrientationUp || photo.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, kFINAL_WIDTH, kFINAL_HEIGHT, CGImageGetBitsPerComponent(imageRef), 0, colorSpaceInfo, bitmapInfo);
    } else {
        bitmap = CGBitmapContextCreate(NULL, kFINAL_HEIGHT, kFINAL_WIDTH, CGImageGetBitsPerComponent(imageRef), 0, colorSpaceInfo, bitmapInfo);
    }

    CGContextSetInterpolationQuality(bitmap, kCGInterpolationHigh);
    CGContextDrawImage(bitmap, drawRect, imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);

    NSData *finalData = UIImageJPEGRepresentation([UIImage imageWithCGImage:ref], 1.0);

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.delegate sendNSDataBack:finalData];
    });
});
Run Code Online (Sandbox Code Playgroud)

我尝试使用CGDataProviderRef获取NSData,但是当我最终获得NSData时,将它放入UIImage中的UIImageView中显示任何内容.

所以底线问题是.我所能做的[UIImage imageWithData:],并UIImageJPEGRepresentation在使用GCD块另一个线程?

Ken*_*ner 8

您可以在后台使用UIImageJPEGRepresentation()(我在当前项目中以这种方式使用它).

但是你不能做的是按照你在后台做的方式创建一个UIImage,[UIImage imagewithCGImage]调用必须在主线程中进行(根据经验,所有UIKit调用都应该在主线程上完成).

这似乎是您可能需要嵌套块的情况.

编辑:我发现自己的代码[UIImage imagewithCGImage]在后台线程中调用,但我仍然怀疑在某些情况下可能会导致问题.但我的代码确实有效.

Edit2:我刚刚注意到你正在调整图像大小,UIImage + Resize.在这篇文章中有一个非常好的类链接,它是以一种强大的方式构建的:

http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

你应该真正阅读整个页面,以了解调整图像大小的细微差别.正如我所说,我确实从后台线程中使用它,即使它内部的部分内容就是你正在做的事情.

编辑3:如果您在iOS4或更高版本上运行,您可能希望使用ImageIO框架来输出图像,这更可能是线程安全的:

http://developer.apple.com/graphicsimaging/workingwithimageio.html

很难找到示例代码,这是一种使用ImageIO保存PNG图像的方法(基于"使用Quartz编程:Mac OS X中的2D和PDF图形"中的代码):

// You'll need both ImageIO and MobileCoreServices frameworks to have this compile
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

void exportCGImageToPNGFileWithDestination( CGImageRef image, CFURLRef url)
{
    float resolution = 144;
    CFTypeRef keys[2];
    CFTypeRef values[2];
    CFDictionaryRef options = NULL;

    // Create image destination to go into URL, using PNG
    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL( url, kUTTypePNG, 1, NULL);

    if ( imageDestination == NULL )
    {
        fprintf( stderr, "Error creating image destination\n");
        return;
    }

    // Set the keys to be the X and Y resolution of the image
    keys[0] = kCGImagePropertyDPIWidth;
    keys[1] = kCGImagePropertyDPIHeight;

    // Create a number for the DPI value for the image
    values[0] = CFNumberCreate( NULL, kCFNumberFloatType, &resolution );
    values[1] = values[0];

    // Options dictionary for output
    options = CFDictionaryCreate(NULL,
                                 (const void **)keys,
                                 (const void **)values,
                                 2,
                                 &kCFTypeDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    CFRelease(values[0]);

    // Adding the image to the destination
    CGImageDestinationAddImage( imageDestination, image, options );
    CFRelease( options );

    // Finalizing writes out the image to the destination
    CGImageDestinationFinalize( imageDestination );
    CFRelease( imageDestination );
}
Run Code Online (Sandbox Code Playgroud)