CVPixelBufferRef与UIImage的互相转换

来源:互联网 发布:调度数据网络交流 编辑:程序博客网 时间:2024/06/15 18:19

CVPixelBufferRefUIImage的互相转换

////  ViewController.m//  test_image_covert_data_01////  Created by jeffasd on 2016/9/30.//  Copyright © 2016年 jeffasd. All rights reserved.//#import "ViewController.h"#define RETAINED_BUFFER_COUNT 4@interface ViewController ()@property (nonatomic, assign) CVPixelBufferPoolRef pixelBufferPool;@end@implementation ViewController#pragma CVPixelBufferRef与UIImage的互相转换- (void)viewDidLoad {    [super viewDidLoad];        self.pixelBufferPool = NULL;        UIImage *image = [UIImage imageNamed:@"atlastest"];    CVPixelBufferRef pixelBuffer = [self CVPixelBufferRefFromUiImage:image];    //CVPixelBufferRef pixelBuffer = [self pixelBufferFasterFromImage:image];    //CVPixelBufferRef pixelBuffer = [[self class] pixelBufferFromCGImage:image.CGImage];    //UIImage *covertImage = [[self class] imageFromCVPixelBufferRef0:pixelBuffer];    //UIImage *covertImage = [[self class] imageFromCVPixelBufferRef1:pixelBuffer];    //UIImage *covertImage = [[self class] imageFromCVPixelBufferRef2:pixelBuffer];//    covertImage = nil;//        UIImage *decodeImage = [[self class] decodeImageWithImage:image];    decodeImage = nil;        CVPixelBufferRef pixelBuffer1 = [self pixelBufferFromImageWithPool:NULL image:image];    pixelBuffer1 = nil;        //covertImage = nil;}static OSType inputPixelFormat(){    //注意CVPixelBufferCreate函数不支持 kCVPixelFormatType_32RGBA 等格式 不知道为什么。    //支持kCVPixelFormatType_32ARGB和kCVPixelFormatType_32BGRA等 iPhone为小端对齐因此kCVPixelFormatType_32ARGB和kCVPixelFormatType_32BGRA都需要和kCGBitmapByteOrder32Little配合使用    //注意当inputPixelFormat为kCVPixelFormatType_32BGRA时bitmapInfo不能是kCGImageAlphaNone,kCGImageAlphaLast,kCGImageAlphaFirst,kCGImageAlphaOnly。    //注意iPhone的大小端对齐方式为小段对齐 可以使用宏 kCGBitmapByteOrder32Host 来解决大小端对齐 大小端对齐必须设置为kCGBitmapByteOrder32Little。    //return kCVPixelFormatType_32RGBA;//iPhone不支持此输入格式!!!    return kCVPixelFormatType_32BGRA;    //return kCVPixelFormatType_32ARGB;}static uint32_t bitmapInfoWithPixelFormatType(OSType inputPixelFormat){    /*     CGBitmapInfo的设置     uint32_t bitmapInfo = CGImageAlphaInfo | CGBitmapInfo;          当inputPixelFormat=kCVPixelFormatType_32BGRA CGBitmapInfo的正确的设置 只有如下两种正确设置     uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;     uint32_t bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;          typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {     kCGImageAlphaNone,                For example, RGB.     kCGImageAlphaPremultipliedLast,   For example, premultiplied RGBA     kCGImageAlphaPremultipliedFirst,  For example, premultiplied ARGB     kCGImageAlphaLast,                For example, non-premultiplied RGBA     kCGImageAlphaFirst,               For example, non-premultiplied ARGB     kCGImageAlphaNoneSkipLast,        For example, RBGX.     kCGImageAlphaNoneSkipFirst,       For example, XRGB.     kCGImageAlphaOnly                 No color data, alpha data only     };          当inputPixelFormat=kCVPixelFormatType_32ARGB CGBitmapInfo的正确的设置 只有如下两种正确设置     uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big;     uint32_t bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big;     */    if (inputPixelFormat == kCVPixelFormatType_32BGRA) {        //uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;        //此格式也可以        uint32_t bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;        return bitmapInfo;    }else if (inputPixelFormat == kCVPixelFormatType_32ARGB){        uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big;        //此格式也可以        //uint32_t bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big;        return bitmapInfo;    }else{        NSLog(@"不支持此格式");        return 0;    }}static CVPixelBufferPoolRef createPixelBufferPoolInner( int32_t width, int32_t height, OSType pixelFormat, int32_t maxBufferCount ){    CVPixelBufferPoolRef outputPool = NULL;        NSDictionary *sourcePixelBufferOptions = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(pixelFormat),                                                (id)kCVPixelBufferWidthKey : @(width),                                                (id)kCVPixelBufferHeightKey : @(height),                                                //(id)kCVPixelFormatOpenGLESCompatibility : @(YES),                                                (id)kCVPixelBufferIOSurfacePropertiesKey : @{ /*empty dictionary*/ } };        NSDictionary *pixelBufferPoolOptions = @{ (id)kCVPixelBufferPoolMinimumBufferCountKey : @(maxBufferCount) };        CVPixelBufferPoolCreate( kCFAllocatorDefault, (__bridge CFDictionaryRef)pixelBufferPoolOptions, (__bridge CFDictionaryRef)sourcePixelBufferOptions, &outputPool );        return outputPool;}static CVPixelBufferPoolRef createCVPixelBufferPoolRef(int32_t imageWidth, int32_t imageHeight){    OSType pixelFormat = inputPixelFormat();    int32_t maxRetainedBufferCount = RETAINED_BUFFER_COUNT;    CVPixelBufferPoolRef bufferPool = createPixelBufferPoolInner( imageWidth, imageHeight, pixelFormat, maxRetainedBufferCount );    if ( ! bufferPool ) {        NSLog( @"Problem initializing a buffer pool." );    }    NSLog( @"success initializing a buffer pool." );    return bufferPool;}- (CVPixelBufferRef)pixelBufferFromImageWithPool:(CVPixelBufferPoolRef)pixelBufferPool image:(UIImage *)image{    CVPixelBufferRef pxbuffer = NULL;        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,                             nil];        size_t width =  CGImageGetWidth(image.CGImage);    size_t height = CGImageGetHeight(image.CGImage);    size_t bytesPerRow = CGImageGetBytesPerRow(image.CGImage);#if 0    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(image.CGImage);#endif    void *pxdata = NULL;        if (pixelBufferPool == NULL){        NSLog(@"pixelBufferPool is null!");        CVPixelBufferPoolRef bufferPool = createCVPixelBufferPoolRef((int32_t)width, (int32_t)height);        self.pixelBufferPool = bufferPool;        pixelBufferPool = bufferPool;    }        CVReturn status = CVPixelBufferPoolCreatePixelBuffer (NULL, pixelBufferPool, &pxbuffer);    if (pxbuffer == NULL) {        status = CVPixelBufferCreate(kCFAllocatorDefault, width,                                     height, inputPixelFormat(), (__bridge CFDictionaryRef) options,                                     &pxbuffer);    }        NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);    CVPixelBufferLockBaseAddress(pxbuffer, 0);    pxdata = CVPixelBufferGetBaseAddress(pxbuffer);    NSParameterAssert(pxdata != NULL);    #if 1 - 此去掉alpha通道效率更高    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;        //对于生成CVPixelBufferRef无法使用此方法但是对于解码图片可以使用此方法//    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image.CGImage);//    if (alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaOnly) {//        alphaInfo = kCGImageAlphaNoneSkipFirst;//    } else if (alphaInfo == kCGImageAlphaFirst) {//        alphaInfo = kCGImageAlphaPremultipliedFirst;//    } else if (alphaInfo == kCGImageAlphaLast) {//        alphaInfo = kCGImageAlphaPremultipliedLast;//    }//    bitmapInfo |= alphaInfo;        bitmapInfo = bitmapInfoWithPixelFormatType(inputPixelFormat());        size_t bitsPerComponent = CGImageGetBitsPerComponent(image.CGImage);        CGContextRef context = CGBitmapContextCreate(pxdata, width,                                                 height,bitsPerComponent,bytesPerRow, rgbColorSpace,                                                 bitmapInfo);    NSParameterAssert(context);    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));    CGContextDrawImage(context, CGRectMake(0, 0, width,height), image.CGImage);    CGColorSpaceRelease(rgbColorSpace);    CGContextRelease(context);#else //- 此方法获取的图片可能无法还原真实的图片    CFDataRef  dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));    GLubyte  *imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);    #if 0    CFIndex length = CFDataGetLength(dataFromImageDataProvider);    memcpy(pxdata,imageData,length);    #else    CVPixelBufferCreateWithBytes(kCFAllocatorDefault,width,height,inputPixelFormat(),imageData,bytesPerRow,NULL,NULL,(__bridge CFDictionaryRef)options,&pxbuffer);    #endif    CFRelease(dataFromImageDataProvider);#endif        return pxbuffer;}/** UIImage covert to CVPixelBufferRef *///方法1 此方法能还原真实的图片- (CVPixelBufferRef)CVPixelBufferRefFromUiImage:(UIImage *)img {    CGSize size = img.size;    CGImageRef image = [img CGImage];        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];    CVPixelBufferRef pxbuffer = NULL;    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height, inputPixelFormat(), (__bridge CFDictionaryRef) options, &pxbuffer);        NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);        CVPixelBufferLockBaseAddress(pxbuffer, 0);    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);    NSParameterAssert(pxdata != NULL);        CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();        //CGBitmapInfo的设置    //uint32_t bitmapInfo = CGImageAlphaInfo | CGBitmapInfo;        //当inputPixelFormat=kCVPixelFormatType_32BGRA CGBitmapInfo的正确的设置    //uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;    //uint32_t bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;        //当inputPixelFormat=kCVPixelFormatType_32ARGB CGBitmapInfo的正确的设置    //uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big;    //uint32_t bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big;        uint32_t bitmapInfo = bitmapInfoWithPixelFormatType(inputPixelFormat());        CGContextRef context = CGBitmapContextCreate(pxdata, size.width, size.height, 8, 4*size.width, rgbColorSpace, bitmapInfo);    NSParameterAssert(context);        CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);        CGColorSpaceRelease(rgbColorSpace);    CGContextRelease(context);        return pxbuffer;}/** UIImage covert to CVPixelBufferRef *///方法2 注意此方法在处理某些图片时可能无法还原真实的图片- (CVPixelBufferRef)pixelBufferFasterFromImage:(UIImage *)image{        CVPixelBufferRef pxbuffer = NULL;    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,                             nil];        size_t width =  CGImageGetWidth(image.CGImage);    size_t height = CGImageGetHeight(image.CGImage);    size_t bytesPerRow = CGImageGetBytesPerRow(image.CGImage);        CFDataRef  dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));    GLubyte  *imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);        //kCGImageAlphaNoneSkipLast,       /* For example, RBGX. */        CGColorSpaceRef colorspace = CGImageGetColorSpace(image.CGImage);    CGImageAlphaInfo alphainfo = CGImageGetAlphaInfo(image.CGImage);    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(image.CGImage);    const CGFloat *decode = CGImageGetDecode(image.CGImage);    NSString *str = CGImageGetUTType(image.CGImage);    //    kCVPixelFormatType_32ARGB         = 0x00000020, /* 32 bit ARGB *///    kCVPixelFormatType_32BGRA         = 'BGRA',     /* 32 bit BGRA *///    kCVPixelFormatType_32ABGR         = 'ABGR',     /* 32 bit ABGR */不能使用//    kCVPixelFormatType_32RGBA         = 'RGBA',     /* 32 bit RGBA */不能使用        //CVPixelBufferCreateWithBytes这里是很耗时的,要重新创建。    //此方法获取的CVPixelBufferRef不一定正确 如原始图片的CGImageAlphaInfo为kCGImageAlphaNoneSkipLast由于pixelFormatType没有RBGX类型的格式就没法还原原始的图片。    CVPixelBufferCreateWithBytes(kCFAllocatorDefault,width,height,kCVPixelFormatType_32BGRA,imageData,bytesPerRow,NULL,NULL,(__bridge CFDictionaryRef)options,&pxbuffer);    CFRelease(dataFromImageDataProvider);    CVPixelBufferRetain(pxbuffer);        return pxbuffer;}+ (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image{    CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:                             [NSNumber numberWithBool:NO], kCVPixelBufferCGImageCompatibilityKey,                             [NSNumber numberWithBool:NO], kCVPixelBufferCGBitmapContextCompatibilityKey,                             nil];    CVPixelBufferRef pxbuffer = NULL;    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width,                                          frameSize.height,  kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef) options,                                          &pxbuffer);    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);    CVPixelBufferLockBaseAddress(pxbuffer, 0);    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();    CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width,                                                 frameSize.height, 8, 4*frameSize.width, rgbColorSpace,                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),                                           CGImageGetHeight(image)), image);//这个站CPU 相当高    CGColorSpaceRelease(rgbColorSpace);    CGContextRelease(context);    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);    return pxbuffer;}//CVPixelBufferRef 是 CMSampleBufferRef 解码后的数据/** UIImage covert to CMSampleBufferRef *//** CVPixelBufferRef covert to UIImage */+ (UIImage *)imageFromCVPixelBufferRef0:(CVPixelBufferRef)pixelBuffer{    // MUST READ-WRITE LOCK THE PIXEL BUFFER!!!!    CVPixelBufferLockBaseAddress(pixelBuffer, 0);    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);    CIContext *temporaryContext = [CIContext contextWithOptions:nil];    CGImageRef videoImage = [temporaryContext                             createCGImage:ciImage                             fromRect:CGRectMake(0, 0,                                                 CVPixelBufferGetWidth(pixelBuffer),                                                 CVPixelBufferGetHeight(pixelBuffer))];        UIImage *uiImage = [UIImage imageWithCGImage:videoImage];    CGImageRelease(videoImage);    CVPixelBufferRelease(pixelBuffer);    return uiImage;}static OSStatus CreateCGImageFromCVPixelBuffer(CVPixelBufferRef pixelBuffer, CGImageRef *imageOut){    OSStatus err = noErr;    OSType sourcePixelFormat;    size_t width, height, sourceRowBytes;    void *sourceBaseAddr = NULL;    CGBitmapInfo bitmapInfo;    CGColorSpaceRef colorspace = NULL;    CGDataProviderRef provider = NULL;    CGImageRef image = NULL;    sourcePixelFormat = CVPixelBufferGetPixelFormatType( pixelBuffer );    if ( kCVPixelFormatType_32ARGB == sourcePixelFormat )        bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst;    else if ( kCVPixelFormatType_32BGRA == sourcePixelFormat )        bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst;    else        return -95014; // only uncompressed pixel formats    sourceRowBytes = CVPixelBufferGetBytesPerRow( pixelBuffer );    width = CVPixelBufferGetWidth( pixelBuffer );    height = CVPixelBufferGetHeight( pixelBuffer );    CVPixelBufferLockBaseAddress( pixelBuffer, 0 );    sourceBaseAddr = CVPixelBufferGetBaseAddress( pixelBuffer );    colorspace = CGColorSpaceCreateDeviceRGB();    CVPixelBufferRetain( pixelBuffer );    provider = CGDataProviderCreateWithData( (void *)pixelBuffer, sourceBaseAddr, sourceRowBytes * height, ReleaseCVPixelBuffer);    image = CGImageCreate(width, height, 8, 32, sourceRowBytes, colorspace, bitmapInfo, provider, NULL, true, kCGRenderingIntentDefault);    if ( err && image ) {        CGImageRelease( image );        image = NULL;    }    if ( provider ) CGDataProviderRelease( provider );    if ( colorspace ) CGColorSpaceRelease( colorspace );    *imageOut = image;    return err;}static void ReleaseCVPixelBuffer(void *pixel, const void *data, size_t size){    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)pixel;    CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );    CVPixelBufferRelease( pixelBuffer );}+(UIImage *)imageFromCVPixelBufferRef1:(CVPixelBufferRef)pixelBuffer{    UIImage *image;    @autoreleasepool {        CGImageRef cgImage = NULL;        CVPixelBufferRef pb = (CVPixelBufferRef)pixelBuffer;        CVPixelBufferLockBaseAddress(pb, kCVPixelBufferLock_ReadOnly);        OSStatus res = CreateCGImageFromCVPixelBuffer(pb,&cgImage);        if (res == noErr){            image= [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationUp];        }        CVPixelBufferUnlockBaseAddress(pb, kCVPixelBufferLock_ReadOnly);        CGImageRelease(cgImage);    }    return image;}//第二种+(UIImage *)imageFromCVPixelBufferRef2:(CVPixelBufferRef)pixelBuffer{    CVPixelBufferRef pb = (CVPixelBufferRef)pixelBuffer;    CVPixelBufferLockBaseAddress(pb, kCVPixelBufferLock_ReadOnly);    int w = CVPixelBufferGetWidth(pb);    int h = CVPixelBufferGetHeight(pb);    int r = CVPixelBufferGetBytesPerRow(pb);    int bytesPerPixel = r/w;    unsigned char *buffer = CVPixelBufferGetBaseAddress(pb);    UIGraphicsBeginImageContext(CGSizeMake(w, h));    CGContextRef c = UIGraphicsGetCurrentContext();    unsigned char *data = CGBitmapContextGetData(c);    if (data != NULL) {        int maxY = h;        for(int y = 0; y<maxY; y++) {            for(int x = 0; x<w; x++) {                int offset = bytesPerPixel*((w*y)+x);                data[offset] = buffer[offset];     // R                data[offset+1] = buffer[offset+1]; // G                data[offset+2] = buffer[offset+2]; // B                data[offset+3] = buffer[offset+3]; // A            }        }    }    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    CVPixelBufferUnlockBaseAddress(pb, kCVPixelBufferLock_ReadOnly);    return img;}/** CMSampleBufferRef covert to UIImage *//** CMSampleBufferRef covert to CVPixelBufferRef *//** decode compress image to bitmap iamge */+ (UIImage *)decodeImageWithImage:(UIImage *)imageToPredraw{    // Always use a device RGB color space for simplicity and predictability what will be going on.    CGColorSpaceRef colorSpaceDeviceRGBRef = CGColorSpaceCreateDeviceRGB();    // Early return on failure!    if (!colorSpaceDeviceRGBRef) {        NSLog(@"Failed to `CGColorSpaceCreateDeviceRGB` for image %@", imageToPredraw);        return imageToPredraw;    }        // "In iOS 4.0 and later, and OS X v10.6 and later, you can pass NULL if you want Quartz to allocate memory for the bitmap." (source: docs)    void *data = NULL;    size_t width = imageToPredraw.size.width;    size_t height = imageToPredraw.size.height;    size_t bitsPerComponent = CHAR_BIT;//一个像素的单个组成部分的位数 如RGBA 此值指定R,G,B,A,每个分量占的位数为8bit。    #if 1    // Even when the image doesn't have transparency, we have to add the extra channel because Quartz doesn't support other pixel formats than 32 bpp/8 bpc for RGB:    // kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst, kCGImageAlphaPremultipliedLast    // (source: docs "Quartz 2D Programming Guide > Graphics Contexts > Table 2-1 Pixel formats supported for bitmap graphics contexts")    size_t numberOfComponents = CGColorSpaceGetNumberOfComponents(colorSpaceDeviceRGBRef) + 1; // 4: RGB + A    size_t bitsPerPixel = (bitsPerComponent * numberOfComponents);//一个像素点占用的位数 如RGBA=8*4    size_t bytesPerPixel = (bitsPerPixel / BYTE_SIZE);//一个像素点占用的字节数    size_t bytesPerRow = (bytesPerPixel * width);//一行的全部像素占用的字节数#else    size_t bytesPerRow = 0;//对于CGBitmapContextCreate函数当bytesPerRow=0系统不仅会为我们自动计算,而且还会进行 cache line alignment 的优化#endif        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;        CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageToPredraw.CGImage);    // If the alpha info doesn't match to one of the supported formats (see above), pick a reasonable supported one.    // "For bitmaps created in iOS 3.2 and later, the drawing environment uses the premultiplied ARGB format to store the bitmap data." (source: docs)    if (alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaOnly) {        alphaInfo = kCGImageAlphaNoneSkipFirst;    } else if (alphaInfo == kCGImageAlphaFirst) {        alphaInfo = kCGImageAlphaPremultipliedFirst;    } else if (alphaInfo == kCGImageAlphaLast) {        alphaInfo = kCGImageAlphaPremultipliedLast;    }    // "The constants for specifying the alpha channel information are declared with the `CGImageAlphaInfo` type but can be passed to this parameter safely." (source: docs)    bitmapInfo |= alphaInfo;        // Create our own graphics context to draw to; `UIGraphicsGetCurrentContext`/`UIGraphicsBeginImageContextWithOptions` doesn't create a new context but returns the current one which isn't thread-safe (e.g. main thread could use it at the same time).    // Note: It's not worth caching the bitmap context for multiple frames ("unique key" would be `width`, `height` and `hasAlpha`), it's ~50% slower. Time spent in libRIP's `CGSBlendBGRA8888toARGB8888` suddenly shoots up -- not sure why.    //data为NULL系统自动分配内存空间    CGContextRef bitmapContextRef = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpaceDeviceRGBRef, bitmapInfo);    CGColorSpaceRelease(colorSpaceDeviceRGBRef);    // Early return on failure!    if (!bitmapContextRef) {        NSLog(@"Failed to `CGBitmapContextCreate` with color space %@ and parameters (width: %zu height: %zu bitsPerComponent: %zu bytesPerRow: %zu) for image %@", colorSpaceDeviceRGBRef, width, height, bitsPerComponent, bytesPerRow, imageToPredraw);        return imageToPredraw;    }        // Draw image in bitmap context and create image by preserving receiver's properties.    CGContextDrawImage(bitmapContextRef, CGRectMake(0.0, 0.0, imageToPredraw.size.width, imageToPredraw.size.height), imageToPredraw.CGImage);    CGImageRef predrawnImageRef = CGBitmapContextCreateImage(bitmapContextRef);    UIImage *predrawnImage = [UIImage imageWithCGImage:predrawnImageRef scale:imageToPredraw.scale orientation:imageToPredraw.imageOrientation];    CGImageRelease(predrawnImageRef);    CGContextRelease(bitmapContextRef);        // Early return on failure!    if (!predrawnImage) {        NSLog(@"Failed to `imageWithCGImage:scale:orientation:` with image ref %@ created with color space %@ and bitmap context %@ and properties and properties (scale: %f orientation: %ld) for image %@", predrawnImageRef, colorSpaceDeviceRGBRef, bitmapContextRef, imageToPredraw.scale, (long)imageToPredraw.imageOrientation, imageToPredraw);        return imageToPredraw;    }        return predrawnImage;}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end


原创粉丝点击