开发者

(iphone) is there a function call(UIImage related) I shouldn't do in non-main thread here?

I'm trying to create UIImage from background thread.

I wonder if any call I use here shouldn't be done in background.

Thank you

// defined below 
CGContextRef context = CreateARGBBitmapContext(entireRect.size);                                                                                                                                                                                                        

CGContextDrawImage(context, rect, originalImage.CGImage);                                                                                                                                                                                                                    

CGImageRef imageRef = CGBitmapContextCreateImage(context);                                                                                                                                                                                                                  
UIImage* img = [UIImage imageWithCGImage: imageRef];                                                                                                                                                                                                                  
CGImageRelease(imageRef);                                                                                                                                                                                                                  

CGContextRelease(context);                                                                                                                                                                                                                                     

return img;        

Where CreateARGBBitmapContext is defined as below.

CGContextRef CreateARGBBitmapContext(CGSize size)
{
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    // Get image width, height. We'll use the entire image.                                                                                                                                                                                                                   
    size_t pixelsWide = size.width;
    size_t pixelsHigh = size.height;

    // Declare the number of bytes per row. Each pixel in the bitmap in this                                                                                                                                                                                                  
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and                                                                                                                                                          开发者_高级运维                                      
    // alpha.                                                                                                                                                                                                                                                                 
    bitmapBytesPerRow   = (pixelsWide * 4);
//  bitmapBytesPerRow = (int) round( pow( 2.0, trunc( log((double) bitmapBytesPerRow) / log(2.0) ) + 1.0 ) );                                                                                                                                                                 
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

    // Use the generic RGB color space.                                                                                                                                                                                                                                       
    colorSpace = CGColorSpaceCreateDeviceRGB();

    if (colorSpace == NULL)
    {
        fprintf(stderr, "Error allocating color space\n");
        return NULL;
    }

    // Allocate memory for image data. This is the destination in memory                                                                                                                                                                                                      
    // where any drawing to the bitmap context will be rendered.                                                                                                                                                                                                              
    NSMutableData* mutableData = [NSMutableData dataWithLength: bitmapByteCount];
    bitmapData = [mutableData mutableBytes];
    if (bitmapData == NULL)
    {
        fprintf (stderr, "Memory not allocated!");
        CGColorSpaceRelease( colorSpace );
        return NULL;
    }

    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits                                                                                                                                                                                                         
    // per component. Regardless of what the source image format is                                                                                                                                                                                                           
    // (CMYK, Grayscale, and so on) it will be converted over to the format                                                                                                                                                                                                   
    // specified here by CGBitmapContextCreate.                                                                                                                                                                                                                               
    context = CGBitmapContextCreate (bitmapData,
                                     pixelsWide,
                                     pixelsHigh,
                                     8,      // bits per component    
                                    bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaPremultipliedFirst);
    if (context == NULL)
    {
        fprintf (stderr, "Context not created!");
    }

    // Make sure and release colorspace before returning                                                                                                                                                                                                                      
    CGColorSpaceRelease( colorSpace );

    return context;
}


The following line should be in the main thread:

UIImage* img = [UIImage imageWithCGImage: imageRef];      

The rest of the code looks like it would be ok to be in a different thread.

Any interaction with UIKit must be in the main thread. That's why creating a UIImage (or even something like setting the image of a UIImageView) must be done in the main thread. Fortunately, the heavy work, like downloading an image or probably even drawing one as you're doing, can be done in a separate thread. Then, you return to the main thread just to create the UIImage.

Using Grand Central Dispatch and some blocks, the following code might work for you:

dispatch_queue_t drawingQueue = dispatch_queue_create("Drawing image", NULL); dispatch_async(drawingQueue, ^{ CGContextRef context = CreateARGBBitmapContext(entireRect.size); CGContextDrawImage(context, rect, originalImage.CGImage); CGImageRef imageRef = CGBitmapContextCreateImage(context); dispatch_async(dispatch_get_main_queue(), ^{ UIImage* img = [UIImage imageWithCGImage: imageRef]; CGImageRelease(imageRef); }); }); dispatch_release(drawingQueue);

If you're not familiar with Grand Central Dispatch, try googling it. I'm afraid I don't know of a good tutorial for it. Hope this is helpful.

CORRECTION:

My response above is wrong. The UIImage CAN be created in the main thread.

While most interaction with UIKit must be done in the main thread, there are a few exceptions, including UIImage, UIColor, UIFont and Core Graphics. These are all threadsafe.

(Note that I believe UIImageView is not threadsafe. So that if you were to set the image of a UIImageView, then you would have to return to the main thread. A variation of the above code would still be useful for interaction with other UIKit objects, and should not do any damage in this case-- other than unnecessarily complicating things.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜