Skip to content

Instantly share code, notes, and snippets.

@JoeOsborn
Forked from PaulSolt/ImageHelper.h
Created July 21, 2011 16:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save JoeOsborn/1097527 to your computer and use it in GitHub Desktop.
Save JoeOsborn/1097527 to your computer and use it in GitHub Desktop.
A UIImage to BGRA8 conversion category
/*
* The MIT License
*
* Copyright (c) 2011 Paul Solt, PaulSolt@gmail.com
* Modifications Copyright (c) 2011 Joe Osborn, josborn@universalhappymaker.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/*
* Changes from origin:
* * ImageHelper is now a category on UIImage with convention-following method names
* * We now convert to and from BGRA8 for better drawing performance
* * To simplify malloc/free responsibilities, the bitmap context is now created within
* the to-RGBA8 (now BGRA8) conversion method. Before, its bitmap could leak if the
* context creation method were used improperly.
* * An unnecessary memory copy was removed.
* * An unnecessary context creation and image draw were removed.
*/
#import <Foundation/Foundation.h>
@interface UIImage(ImageHelper)
/** Converts a UIImage to BGRA8 bitmap.
@return a BGRA8 bitmap owned by the caller of length image.size.width*image.size.height, or NULL if memory could not be allocated
*/
- (unsigned char *)newBGRA8Bitmap;
/** Converts a BGRA8 bitmap to a UIImage. Transfers ownership of the bitmap to the newly allocated object. This is to avoid cases where client code naively manipulates or frees the buffer immediately after calling this method; CGDataProvider is used internally and Quartz is much cleverer with memory than you or I.
@param size - the size in pixels
@param scale - the image scale
@param buffer - the BGRA8 bitmap, consumed by this method. do not
attempt to modify or use buffer in any way after calling this method.
@return an image of the given size composed of the bytes in buffer
*/
+ (UIImage *)imageWithSize:(CGSize)size
scale:(CGFloat)scale
fromBGRA8Bitmap:(unsigned char *)buffer;
@end
/*
* The MIT License
*
* Copyright (c) 2011 Paul Solt, PaulSolt@gmail.com
* Modifications Copyright (c) 2011 Joe Osborn, josborn@universalhappymaker.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#import "UIImage_ImageHelper.h"
void ProviderReleaseMem(void*, const void*, size_t);
void ProviderReleaseMem(void*info, const void*mem, size_t size) {
free((void *)mem);
}
@implementation UIImage(ImageHelper)
- (unsigned char *)newBGRA8Bitmap {
CGImageRef image = self.CGImage;
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
uint8_t *bitmapData;
size_t bitsPerPixel = 32;
size_t bitsPerComponent = 8;
size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
size_t bytesPerRow = width * bytesPerPixel;
size_t bufferLength = bytesPerRow * height;
colorSpace = CGColorSpaceCreateDeviceRGB();
if(!colorSpace) {
NSLog(@"Error allocating color space RGB\n");
return NULL;
}
// Allocate memory for image data
bitmapData = (uint8_t *)calloc(bufferLength, sizeof(uint8_t));
if(!bitmapData) {
NSLog(@"Error allocating memory for bitmap\n");
CGColorSpaceRelease(colorSpace);
return NULL;
}
//Also known as "BGRA8", thank you Duncan http://osdir.com/ml/quartz-dev/2009-05/msg00031.html
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
//Create bitmap context with this memory block (which we still own,
//although we will transfer ownership to the caller on return).
context = CGBitmapContextCreate(bitmapData,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace,
bitmapInfo); // RGBA
if(!context) {
free(bitmapData);
NSLog(@"Bitmap context not created");
}
CGColorSpaceRelease(colorSpace);
if(!context) {
return NULL;
}
CGRect rect = CGRectMake(0, 0, width, height);
// Draw image into the context to get the raw image data
CGContextDrawImage(context, rect, image);
CGContextRelease(context);
return bitmapData;
}
+ (UIImage *)imageWithSize:(CGSize)size
scale:(CGFloat)scale
fromBGRA8Bitmap:(unsigned char *)buffer {
size_t width = size.width;
size_t height = size.height;
size_t bitsPerComponent = 8;
size_t bitsPerPixel = 32;
size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
size_t bufferLength = width * height * bytesPerPixel;
size_t bytesPerRow = 4 * width;
//caller no longer owns the buffer
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, ProviderReleaseMem);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
if(colorSpaceRef == NULL) {
NSLog(@"Error allocating color space");
CGDataProviderRelease(provider);
return nil;
}
//Also known as "BGRA8", thank you Duncan http://osdir.com/ml/quartz-dev/2009-05/msg00031.html
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorSpaceRef,
bitmapInfo,
provider, // data provider
NULL, // decode
YES, // should interpolate
renderingIntent);
UIImage *ret = [UIImage imageWithCGImage:iref
scale:scale
orientation:UIImageOrientationUp];
CGImageRelease(iref);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
//caller must not free the buffer! it's in Quartz's hands now.
return ret;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment