iphone - UIImageJPEGRepresentation() 线程安全吗?

标签 iphone objective-c ios uiimage core-graphics

我正在缩放和裁剪一个 UIImage,我希望能够在一个线程安全的 block 中执行此操作。我在文档中找不到 UIImageJPEGRepresentation 是否线程安全。

在下面的代码中,我裁剪和缩放了一个 CGImage,然后我从中创建了一个 UIImage 并获得了 UIImageJPEGRepresentation。此 block 的最终目标是从缩放/裁剪版本中获取 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];
    });
});

我尝试使用 CGDataProviderRef 获取 NSData,但是当我最终获取 NSData 时,将其放入 UIImage 到 UIImageView 时什么也没有显示。

底线问题是。我可以使用 GCD 在 block 中的另一个线程中执行 [UIImage imageWithData:]UIImageJPEGRepresentation 吗?

最佳答案

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

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

这似乎是您可能需要嵌套 block 的情况。

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

Edit2:我刚刚注意到您正在调整图像大小,UIImage+Resize。这篇文章中链接了一个非常好的类,它的构建是为了以一种可靠的方式做到这一点:

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

您真的应该阅读整个页面以了解调整图像大小的细微差别。正如我所说,我确实在后台线程中使用它,即使它在内部执行的部分操作就是您正在执行的操作。

Edit3:如果您在 iOS4 或更高版本上运行,您可能需要研究使用 ImageIO 框架来输出图像,这更有可能是线程安全的:

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

这方面的示例代码很难找到,这里有一个使用 ImageIO 保存 PNG 图像的方法(基于“Programming With Quartz:2D and PDF graphics in Mac OS X”中的代码):

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

关于iphone - UIImageJPEGRepresentation() 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5808331/

相关文章:

objective-c - 预处理器指令可以用于为 Mac 和 iOS 导入不同的头文件吗?

ios - 获取 iPad 方向(N、E、S、W)

iPhone 邮件客户端阻止时间戳日历链接?

iphone - 比较两个 nsdatecomponents

ios - 在不显示 View 的情况下发送电子邮件

android - 使用多个 sdk 版本构建 cordova

ios - 使用 CGFLOAT_MAX 隐藏 UITableViewCell 分隔符

iphone - 前台iPhone应用导致我的后台应用崩溃

objective-c - 在不调用 presentViewController(或 dismissViewController)的情况下呈现 View Controller

iphone - 我们如何通过我们的服务器只为我们的客户发布我们的 ios 应用程序?