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