- (CGColorSpaceRef)getScreenColorspace
{
if (!_screenColorspace)
{
CMProfileRef systemProfile = NULL;
OSStatus status = CMGetSystemProfile(&systemProfile);
NSParameterAssert( noErr == status);
_screenColorspace = CGColorSpaceCreateWithPlatformColorSpace(systemProfile);
CMCloseProfile(systemProfile);
}
return _screenColorspace;
}
- (size_t)optimalRowBytesForWidth: (size_t)width bytesPerPixel: (size_t)bytesPerPixel
{
size_t rowBytes = width * bytesPerPixel;
//Widen rowBytes out to a integer multiple of 16 bytes
rowBytes = (rowBytes + 15) & ~15;
//Make sure we are not an even power of 2 wide.
//Will loop a few times for rowBytes <= 16.
while( 0 == (rowBytes & (rowBytes - 1) ) )
rowBytes += 16;
return rowBytes;
}
- (UInt32 const *)createPremultipliedRGBA_8888_BitmapForCIImage: (CIImage *)image rowBytes: (size_t *)rowBytes
{
NSParameterAssert( image != nil );
NSParameterAssert( rowBytes != NULL );
// - Get the geometry of the image
CGRect extent = [image extent];
CGRect zeroRect = {CGPointZero, extent.size};
NSParameterAssert( CGRectIsInfinite(extent) == NO );
size_t destWidth = (size_t)extent.size.width;
size_t destHeight = (size_t)extent.size.height;
// - Create contexts
CGContextRef cgContext = NULL;
CIContext *ciContext = nil;
size_t bitsPerComponent = 8;
size_t bytesPerRow = [self optimalRowBytesForWidth: destWidth bytesPerPixel: 4];
CGColorSpaceRef colorspace = [self getScreenColorspace];
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
UInt32 *bitmapData = malloc(bytesPerRow * destHeight);
if (bitmapData)
{
cgContext = CGBitmapContextCreate(bitmapData, destWidth, destHeight, bitsPerComponent, bytesPerRow, colorspace, bitmapInfo);
if (cgContext)
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
(id)colorspace, kCIContextOutputColorSpace,
(id)colorspace, kCIContextWorkingColorSpace,
nil];
ciContext = [CIContext contextWithCGContext: cgContext options: options];
if (ciContext)
success = YES;
}
}
NSParameterAssert( cgContext != NULL && ciContext != nil );
// - Render the image into the contexts
CGContextClearRect(cgContext, zeroRect);
[ ciContext drawImage: image atPoint: CGPointZero fromRect: extent];
CGContextFlush(cgContext);
// - Get the geometry of the context
*rowBytes = CGBitmapContextGetBytesPerRow(cgContext);
CGContextRelease(cgContext);
return bitmapData;
}