首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UIImageJPEGRepresentation()线程安全吗?

UIImageJPEGRepresentation()线程安全吗?
EN

Stack Overflow用户
提问于 2011-04-28 01:48:08
回答 3查看 5.9K关注 0票数 9

我正在缩放和裁剪一个UIImage,我希望能够在线程安全的块中做到这一点。我在文档中找不到UIImageJPEGRepresentation是否是线程安全的。

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

代码语言:javascript
复制
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在一个块中的另一个线程中执行[UIImage imageWithData:]UIImageJPEGRepresentation吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-04-28 02:25:31

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

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

这看起来像是您可能需要嵌套块的情况。

编辑:我发现我自己的代码确实在后台线程中调用了[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图像的方法(基于“用Quartz编程: Mac中的2D和PDF图形”中的代码):

代码语言:javascript
复制
// 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 );
}
票数 8
EN

Stack Overflow用户

发布于 2011-04-28 07:23:22

苹果的官方立场是UIKit的任何部分都不是线程安全的。但是,您的其余代码似乎是基于Quartz的,当以您使用的方式使用它时,它是线程安全的。

您可以在后台线程上执行所有操作,然后在main上调用UIImageJPEGRepresentation()

代码语言:javascript
复制
// ...
CGImageRef ref = CGBitmapContextCreateImage(bitmap);

dispatch_async(dispatch_get_main_queue(), ^ {
    NSData *finalData = UIImageJPEGRepresentation([UIImage imageWithCGImage:ref], 1.0);
    [self.delegate sendNSDataBack:finalData];
});

CGContextRelease(bitmap);
CGImageRelease(ref);
票数 2
EN

Stack Overflow用户

发布于 2011-04-28 07:15:28

我认为它是线程安全的,因为我做了类似的事情来调整UIImage的大小,或者在后台线程中将图像数据存储到数据库中。并且,主线程有时被命名为UI线程。任何关于更新屏幕的操作都应该在UI线程上执行。但是,UIImage是用于存储图像数据的对象。它不是从UIView派生的子类。因此,它是线程安全的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5808331

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档