之前我的一篇笔记iOS实时美颜并获取原图里面写了如何实现实时的美颜滤镜,本篇作为补充说下如何给一张图片美颜。
还是使用之前提到的GPUImageBeautifyFilter
// 原图
UIImage * sourceImage = [UIImage imageNamed:@"notBeauty.png"];
GPUImageBeautifyFilter *beautyFilter = [[GPUImageBeautifyFilter alloc] init];
//设置要渲染的区域
[beautyFilter forceProcessingAtSize:sourceImage.size];
[beautyFilter useNextFrameForImageCapture];
//获取数据源
GPUImagePicture *stillImageSource = [[GPUImagePicture alloc]initWithImage:sourceImage];
//添加上滤镜
[stillImageSource addTarget:beautyFilter];
//开始渲染
[stillImageSource processImage];
//获取滤镜后的图片
UIImage *beautyImage = [beautyFilter imageFromCurrentFramebuffer];
[beautyFilter removeAllTargets];
[stillImageSource removeAllTargets];
根据以上代码,UIImage *beautyImage
存储的就是美颜后的图片。
上面写的是如何把一个图片美颜,下面说下如何使用GPUImage实现一个美颜相机 。
看如下示例代码
- (void)viewDidLoad {
[super viewDidLoad];
CGRect mainScreenFrame = [[UIScreen mainScreen] bounds];
GPUImageView *primaryView = [[GPUImageView alloc] initWithFrame:mainScreenFrame];
primaryView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.takePhotoButton = [[UIButton alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/2 - 25, [UIScreen mainScreen].bounds.size.height - 60, 50, 50)];
[self.takePhotoButton setTitle:@"拍照" forState:UIControlStateNormal];
self.takePhotoButton.backgroundColor = [UIColor clearColor];
[self.takePhotoButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[self.takePhotoButton addTarget:self action:@selector(takePhotoButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[primaryView addSubview:self.takePhotoButton];
self.view = primaryView;
self.cameraPosition = AVCaptureDevicePositionBack;
[self initCameraAndFilterWithPosition:self.cameraPosition];
}
// 初始化美颜相机
- (void)initCameraAndFilterWithPosition:(AVCaptureDevicePosition)position {
self.stillCamera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:position];
self.stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
if (AVCaptureDevicePositionFront == position) {
// 前置摄像头,镜像展示
self.stillCamera.horizontallyMirrorFrontFacingCamera = YES;
}
self.beautyFilter = [[GPUImageBeautifyFilter alloc] init];
[self.stillCamera addTarget:self.beautyFilter];
GPUImageView * filterView = (GPUImageView *)self.view;
[self.beautyFilter addTarget:filterView];
[self.stillCamera startCameraCapture];
}
// 点击了拍照按钮
- (void)takePhotoButtonClicked {
[self.stillCamera capturePhotoAsJPEGProcessedUpToFilter:self.beautyFilter withCompletionHandler:^(NSData *processedJPEG, NSError *error){
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
// 获取美颜过的相片
UIImage * beautyPhoto = [UIImage imageWithData:processedJPEG];
// ……
// ……
});
}];
}
如果要获取未美颜的原图,可以参照我上一篇笔记iOS实时美颜滤镜并获取原图里面的方法原理获取原图。即实现GPUImageVideoCameraDelegate
协议里面的方法- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
。
这里有个需要注意的点:使用GPUImage的前置摄像头与后置摄像头获取到的原图方向不是一样的,可能是因为前置摄像头的时候设置了horizontallyMirrorFrontFacingCamera = YES
的原因。
- 使用前置摄像头获取到的原图,orientation是0,但是相当于
leftMirror
了 - 使用后置摄像头获取到的原图,orientation是0,但是相当于
left
了
所以,如果使用后置摄像头拍照,获取未美颜的原图的时候,转换代码如下:
- (UIImage *)fixNotBeautyImageOrientation:(UIImage *)originImage {
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformRotate(transform, -M_PI_2);
transform = CGAffineTransformTranslate(transform, - originImage.size.width, 0);
CGContextRef ctx = CGBitmapContextCreate(NULL, originImage.size.height, originImage.size.width,
CGImageGetBitsPerComponent(originImage.CGImage), 0,
CGImageGetColorSpace(originImage.CGImage),
CGImageGetBitmapInfo(originImage.CGImage));
CGContextConcatCTM(ctx, transform);
CGContextDrawImage(ctx, CGRectMake(0,0, originImage.size.width, originImage.size.height), originImage.CGImage);
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
UIImage *img = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return img;
}