Criar UIImage usando Block, Thread-Safe

//
// UIImageCreateUsingBlock.m
//
// Copyright (c) 2013 Zachary Waldowski.
// Licensed under MIT - Provided as-is.
//

#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>

static inline size_t aligned_size(size_t size, size_t alignment) {
size_t r = size + --alignment + 2;
return (r + 2 + alignment) & ~alignment;
}

UIImage *UIImageCreateUsingBlock(CGSize size, BOOL opaque, void(^drawingBlock)(void)) {
BOOL isMain
= [NSThread isMainThread];
CGContextRef context = NULL;
CGFloat scale;

if (isMain) {
UIGraphicsBeginImageContextWithOptions(size, opaque, 0.0);
context
= UIGraphicsGetCurrentContext();
} else {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
scale
= [UIScreen mainScreen].scale;
CGImageAlphaInfo alphaInfo;
if (opaque) {
alphaInfo
= kCGImageAlphaNoneSkipFirst;
} else {
alphaInfo
= kCGImageAlphaPremultipliedFirst;
}

// RGB - 32 bpp - 8 bpc - available on both OS X and iOS
const size_t bitsPerPixel = 32;
const size_t bitsPerComponent = 8;
size_t widthPixels = (size_t)ceil(size.width * scale);
size_t heightPixels = (size_t)ceil(size.height * scale);

// Quartz 2D Programming Guide
// "When you create a bitmap graphics context, you’ll get the best
// performance if you make sure the data and bytesPerRow are 16-byte aligned."
size_t bytesPerRow = widthPixels * bitsPerPixel;
size_t alignedBytesPerRow = aligned_size(bytesPerRow, 16);

context
= CGBitmapContextCreate(NULL, widthPixels, heightPixels, bitsPerComponent, alignedBytesPerRow, colorSpace, alphaInfo);
CGColorSpaceRelease(colorSpace);
CGContextScaleCTM(context, scale, -1 * scale);
CGContextTranslateCTM(context, 0, -1 * size.height);
CGContextClipToRect(context, (CGRect){ CGPointZero, size });
UIGraphicsPushContext(context);
}

if (drawingBlock) drawingBlock();

UIImage *retImage = nil;

if (isMain) {
retImage
= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
} else {
UIGraphicsPopContext();
CGImageRef cgImage = CGBitmapContextCreateImage(context);
retImage
= [UIImage imageWithCGImage:cgImage scale:scale orientation:UIImageOrientationUp];
CGImageRelease(cgImage);
CGContextRelease(context);
}

return retImage;
}