Object-C UIImage 和 CVPixelBufferRef 相互转换

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 基础

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 线程

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> OpenGL ES

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> GPUImage

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> AVFoundation

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> CocoaPods


一.CVPixelBufferRef 转 UIImage

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:CVPixelBufferRef 转 UIImage
//@Time:2022/01/21 07:20
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/

- (UIImage *)imageFromPixelBuffer:(CVPixelBufferRef)pixelBuffer {
    CIImage *ciImage = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer];
    CIContext *context = [CIContext new];
    CGImageRef cgimage = [context createCGImage:ciImage fromRect:[ciImage extent]];
    UIImage *image= [UIImage imageWithCGImage:cgimage];
    CGImageRelease(cgimage);
    return image;
}

二. UIImage 转 CVPixelBufferRef

注意:

kCVPixelFormatType_OneComponent8 是单通道的黑白数据;

kCVPixelFormatType_32ARGB 是带有颜色的 ARGB 数据;

kCVPixelFormatType_32BGRA 是带有颜色的 RGBA 数据;

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:UIImage 转 CVPixelBufferRef
//@Time:2022/01/21 07:20
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/



static uint32_t bitmapInfoWithPixelFormatType(OSType inputPixelFormat, bool hasAlpha){
    
    if (inputPixelFormat == kCVPixelFormatType_32BGRA) {
        uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
        if (!hasAlpha) {
            bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
        }
        return bitmapInfo;
    }else if (inputPixelFormat == kCVPixelFormatType_32ARGB) {
        uint32_t bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big;
        return bitmapInfo;
    }else if (inputPixelFormat == kCVPixelFormatType_OneComponent8) {
        uint32_t bitmapInfo = kCGImageAlphaNone;
        return bitmapInfo;
    }else{
        NSLog(@"不支持此格式");
        return 0;
    }
}

// alpha的判断
BOOL IsCGImageRefContainsAlpha(CGImageRef imageRef) {
    if (!imageRef) {
        return NO;
    }
    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
    BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone ||
                      alphaInfo == kCGImageAlphaNoneSkipFirst ||
                      alphaInfo == kCGImageAlphaNoneSkipLast);
    return hasAlpha;
}

// 此方法能还原真实的图片
- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image pixelFormatType:(OSType)pixelFormatType resizeSize:(CGSize)resizeSize {
//    CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
    
    BOOL hasAlpha = IsCGImageRefContainsAlpha(image);
    CFDictionaryRef empty = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             empty, kCVPixelBufferIOSurfacePropertiesKey,
                             nil];
    CVPixelBufferRef pxbuffer = NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, resizeSize.width, resizeSize.height, pixelFormatType, (__bridge CFDictionaryRef) options, &pxbuffer);
    
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
    
    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata;
    if (pixelFormatType == kCVPixelFormatType_OneComponent8) {
        pxdata = CVPixelBufferGetBaseAddressOfPlane(pxbuffer,0);
    }else {
        pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
    }
    NSParameterAssert(pxdata != NULL);
    
    CGColorSpaceRef colorSpace;
    size_t bytesPerRow;
    if (pixelFormatType == kCVPixelFormatType_OneComponent8) {
        colorSpace = CGColorSpaceCreateDeviceGray();
        bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pxbuffer, 0);
    }else {
        colorSpace = CGColorSpaceCreateDeviceRGB();
        bytesPerRow = CVPixelBufferGetBytesPerRow(pxbuffer);
    }
    uint32_t bitmapInfo = bitmapInfoWithPixelFormatType(pixelFormatType, (bool)hasAlpha);
    
    CGContextRef context = CGBitmapContextCreate(pxdata, resizeSize.width, resizeSize.height, 8, bytesPerRow, colorSpace, bitmapInfo);
    NSParameterAssert(context);
    
    CGContextDrawImage(context, CGRectMake(0, 0, resizeSize.width, resizeSize.height), image);
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
    
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    
    return pxbuffer;
}

三.猜你喜欢


未经允许不得转载:猿说编程 » Object-C UIImage 和 CVPixelBufferRef 相互转换
喜欢(0) 打赏

评论抢沙发

评论前必须登录!

文章付费之后,如果下载源码失败,请直接留言,博主看到消息会及时处理的,感谢配合!!!共勉!!

开始学习

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏