使用GPUImage做美颜非常方便,内置已经提供了一个GPUImagePicture作为图片输入Filter。
GPUImagePicture的实现方法是读取图片数据,将其写入到GPUImageFramebuffer,是一种非常高效的方案。我的方案是将image转为CMSampleBufferRef,这样就能复用视频的处理代码。转换代码如下
- (CVPixelBufferRef)pixelBufferFromUIImage:(UIImage *)image {
CGSize frameSize = CGSizeMake(CGImageGetWidth(image.CGImage),CGImageGetHeight(image.CGImage));
NSDictionary *options =
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey,
[NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey, nil];
CVPixelBufferRef pxbuffer = NULL;
int cropWidth = (int)CGImageGetWidth(image.CGImage) & ~15;
int cropHeight = (int)CGImageGetHeight(image.CGImage) & ~1;
CVReturn status =
CVPixelBufferCreate(kCFAllocatorDefault, cropWidth, cropHeight, 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, cropWidth, cropHeight,8, CVPixelBufferGetBytesPerRow(pxbuffer),rgbColorSpace,(CGBitmapInfo)kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context, CGRectMake(0, 0, cropWidth, cropHeight), image.CGImage);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
有个坑的地方是,在后面处理的时候会遇到CVOpenGLESTextureCacheCreateTextureFromImage
返回-6638错误,看了官方文档才找到解决方案 https://developer.apple.com/library/archive/qa/qa1781/_index.html
上效果图