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