#1GPUImage 的下载与安装git
GPUImage 是一个开源的图像处理库,提供了很是多的滤镜效果来加工图片。GPUImage 并不像通常的第三方库能够直接拖入到工程中使用,而是须要先在本地编译,而后将编译后的文件拖入到工程中使用。配置步骤以下:github
:首先下载GPUImage https://github.com/BradLarson/GPUImagexcode
:解压后,在framework 目录下,打开 GPUImage.xcodeproj 工程ide
#2使用GPUImage处理静态图片 直接上代码讲解。atom
@interface ViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate> { // 相机 CameraViewController *camera; //相册 UIImagePickerController *_photos; UIImage *inputImage; UIImageView *_imageView; } @end
在处理静态图片的时候我加入了从相册中选取图片,故导入UINavigationControllerDelegate,UIImagePickerControllerDelegate这个两个协议。spa
/懒加载 UIImagePickerController -(UIImagePickerController *)getPhotos{ if (!_photos) { _photos = [[UIImagePickerController alloc]init]; _photos.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; _photos.delegate = self; } return _photos; }
使用懒加载的方法把UIImagePickerController加载出来。code
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //进去时候的默认图片; inputImage = [UIImage imageNamed:@"u=884032455,526519386&fm=21&gp=0"]; UIImageView *imageView = [[UIImageView alloc] initWithImage:inputImage]; imageView.frame = CGRectMake(50,50, 400,400); [self.view addSubview:imageView]; _imageView = imageView;
在 viewDidLoad 中设置放置图片的UIImageView的大小以及默认图片,而后再赋值给 _imageView(最开始咱们设置的全局变量)。orm
// 效果一 控件 -(void)buttonOne{ UIButton *buttonOne = [UIButton buttonWithType:UIButtonTypeCustom]; buttonOne.frame = CGRectMake(10, HEIGHT - 200, 80, 30); [buttonOne setTitle:@"效果一" forState:UIControlStateNormal]; buttonOne.backgroundColor = [UIColor blackColor]; [self.view addSubview:buttonOne]; [buttonOne addTarget:self action:@selector(buttonOneAction) forControlEvents:UIControlEventTouchUpInside]; }
这里就是咱们建立效果的button了,很简单的代码。事件
-(void)buttonOneAction{ //设置滤镜的效果 GPUImageToonFilter *passthroughFilter = [[GPUImageToonFilter alloc] init]; //设置要渲染的区域 [passthroughFilter forceProcessingAtSize:inputImage.size]; [passthroughFilter useNextFrameForImageCapture]; //获取数据源 GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:inputImage]; //加上滤镜 [stillImageSource addTarget:passthroughFilter]; //开始渲染 [stillImageSource processImage]; //获取渲染后的图片 UIImage *newImage = [passthroughFilter imageFromCurrentFramebuffer]; _imageView.image = newImage; }
这一步是实现咱们点击效果一按钮出发的事件。 其中咱们设置的滤镜效果有不少。 在这里我就给你们列出来,不要嫌多图片
##2.1依照以上的方法就能够设置多个效果button,设设置完Button后不要忘了在 viewDidLoad 中加载出来。
// 删除效果控件 -(void)buttonOriginal{ UIButton *buttonOriginal = [UIButton buttonWithType:UIButtonTypeCustom]; buttonOriginal.frame = CGRectMake(120, HEIGHT - 100, 120, 30); [buttonOriginal setTitle:@"删除效果" forState:UIControlStateNormal]; buttonOriginal.backgroundColor = [UIColor blueColor]; [self.view addSubview:buttonOriginal]; [buttonOriginal addTarget:self action:@selector(buttonOriginalAction) forControlEvents:UIControlEventTouchUpInside]; }
为了完整,我添加了一个删除效果的Button,以到达还原图片的效果
- (void)buttonOriginalAction { _imageView.image = inputImage; }
就是把选中的原图再次赋给图片,就达到了还原的效果。
// 进入相册 控件 -(void)buttonPhoto{ UIButton *buttonPhoto = [UIButton buttonWithType:UIButtonTypeCustom]; buttonPhoto.frame = CGRectMake(280, HEIGHT - 100, 120, 30); [buttonPhoto setTitle:@"相册" forState:UIControlStateNormal]; buttonPhoto.backgroundColor = [UIColor blueColor]; [self.view addSubview:buttonPhoto]; [buttonPhoto addTarget:self action:@selector(buttonPhotoAction) forControlEvents:UIControlEventTouchUpInside]; }
##2.2添加一个进入相册的控件
- (void)buttonPhotoAction{ [self presentViewController:_photos animated:YES completion:nil]; }
经过这个方法就能够进如到相册中去。
#pragma mark -<UINavigationControllerDelegate,UIImagePickerControllerDelegate> // 协议方法 UIImagePickerControllerDelegate -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ //相册返回(销毁控制器) [picker dismissViewControllerAnimated:YES completion:nil]; //把相册的照片赋给控件页面上的 UIImageView → UIImage _imageView.image = info[UIImagePickerControllerOriginalImage]; inputImage = _imageView.image; }
以上代码就是在进入相册的时候出来的时候要销毁控制器。否则会出错。最后再把照片赋给全局变量的 UIImageView → UIImage。
#3使用GPUImage制做实时滤镜
制做实时滤镜就是在相机或者摄影的时候把滤镜添加上去,这里我就只作了相机的实时滤镜
// 进入照相机 控件 -(void)buttonCamera{ UIButton *buttonCamera = [UIButton buttonWithType:UIButtonTypeCustom]; buttonCamera.frame = CGRectMake(180, HEIGHT - 300, 180, 50); [buttonCamera setTitle:@"相机 咔!咔!咔!" forState:UIControlStateNormal]; buttonCamera.backgroundColor = [UIColor blueColor]; [self.view addSubview:buttonCamera]; [buttonCamera addTarget:self action:@selector(buttonCameraAction) forControlEvents:UIControlEventTouchUpInside]; }
##3.1建立一个相机的button,以及实现他的点击功能,这些方法都要写在 处理静态图片的的.m文件中。
-(void)buttonCameraAction{ [self presentViewController:camera animated:YES completion:nil]; }
这个点击方法就是进入到相机中拍照。
建立 CameraViewController 这个类,在这个类里面写相机的一些功能。 首先导入 #import AssetsLibrary/AssetsLibrary.h>这是用来拍照的时候将图片保存到相册中的头文件
@interface CameraViewController () { //建立一个全局的效果的button UIButton *buttonEffect; // UIButton *_tempBtn; } //全局变量的相机 @property (strong, nonatomic) GPUImageStillCamera *mCamera; //滤镜 @property (strong, nonatomic) GPUImageFilter *mFilter; //视图 @property (strong, nonatomic) GPUImageView *mGPUImageView; @property (strong, nonatomic) UIView *btnBgView; //摄像头的位置 @property(nonatomic, readonly) AVCaptureDevicePosition position; @end
代码中有注释,建立这些全局变量 { } 中的内容必定要记得初始化,由于没有生成 set 和 get 方法。
// 初始化 btnBgView(懒加载) - (UIView *)btnBgView{ if (!_btnBgView) { _btnBgView = [[UIView alloc] initWithFrame:CGRectMake(80,HEIGHT - 250,WIDTH - 80, 80)]; _btnBgView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.1]; [self.view addSubview:_btnBgView]; } return _btnBgView; }
初始化 btnBgView。
##3.2步骤 1 第一个参数表示相片的尺寸,第二个参数表示前、后摄像头
- (void)viewDidLoad { [super viewDidLoad]; //摄像头方向 _position = AVCaptureDevicePositionFront; _mCamera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:_position];
竖屏方向
_mCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
步骤2 滤镜
_mFilter = [[GPUImageVignetteFilter alloc] init];
步骤3 建立GPUImageView及 尺寸
_mGPUImageView = [[GPUImageView alloc]initWithFrame:self.view.bounds];
步骤4 添加滤镜到相机上
[_mCamera addTarget:_mFilter]; [_mFilter addTarget:_mGPUImageView];
步骤5 添加视图到VIEW上
[self.view addSubview:_mGPUImageView]; //步骤6 启动相机 [_mCamera startCameraCapture];
将按键视图放置顶层
[self.view bringSubviewToFront:buttonEffect]; self.btnBgView.hidden = YES; self.btnBgView.frame = CGRectMake(WIDTH,HEIGHT - 250,WIDTH - 80, 80);
##3.3按键建立
[self creatSetectBtn]; [self buttonRt ]; [self crateBtn]; [self buttonEffect]; [self Camare]; // 将按钮的的初始值设为 nil; _tempBtn = nil; }
接下来咱们就开始建立一个个的控件,
建立拍照按钮
-(void)crateBtn{ //添加一个按钮触发拍照 UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake((self.view.bounds.size.width-80)*0.5, self.view.bounds.size.height-100, 80, 80)]; btn.backgroundColor = [UIColor redColor]; [btn setTitle:@"拍照" forState:UIControlStateNormal]; [self.view addSubview:btn]; [btn addTarget:self action:@selector(takePhoto) forControlEvents:UIControlEventTouchUpInside]; }
实现点击拍照按钮将照片保存到相册中
-(void)takePhoto{ //步骤7 [_mCamera capturePhotoAsJPEGProcessedUpToFilter:_mFilter withCompletionHandler:^(NSData *processedJPEG, NSError *error){ //将相片保存到手机相册(iOS8及以上,该方法过时可是能够用,不想用请搜索PhotoKit) ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeImageDataToSavedPhotosAlbum:processedJPEG metadata:_mCamera.currentCaptureMetadata completionBlock:^(NSURL *assetURL, NSError *error2) { if (error2) { NSLog(@"保存失败"); } else { NSLog(@"保存成功 - assetURL: %@", assetURL); } }]; }]; }
返回按钮
-(void)buttonRt{ UIButton *rt = [UIButton buttonWithType:UIButtonTypeCustom]; rt.frame = CGRectMake(0, 0, 80, 80); rt.backgroundColor = [UIColor redColor]; [rt setTitle:@"返回" forState:UIControlStateNormal]; [self.view addSubview:rt]; [rt addTarget:self action:@selector(rtAction) forControlEvents:UIControlEventTouchUpInside]; }
从相机页面返回处处理静态图片的页面
-(void)rtAction{ [self dismissViewControllerAnimated:YES completion:nil]; }
设置btnBgView的位置,设置 其 为隐藏状态
-(void)resumeState{ [UIView animateWithDuration:1.0 animations:^{ self.btnBgView.transform = CGAffineTransformMakeTranslation(WIDTH, 0); }]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.btnBgView.hidden = YES; }); }
##3.4建立滤镜按钮,这里的滤镜按钮是总按钮,弹出不少个滤镜选项的按钮
-(void)buttonEffect{ buttonEffect = [UIButton buttonWithType:UIButtonTypeCustom]; buttonEffect.frame = CGRectMake(WIDTH - 80, HEIGHT - 250, 80, 80); buttonEffect.backgroundColor = [UIColor redColor]; [buttonEffect setTitle:@"滤镜" forState:UIControlStateNormal]; [self.view addSubview: buttonEffect]; [buttonEffect addTarget:self action:@selector(effectAction) forControlEvents:UIControlEventTouchUpInside]; }
点击滤镜按钮 弹出一个btnBgView,根据判断这个视图是否显示,来进行 弹出 仍是 隐藏。 在工程的最开始的位置,咱们已经提早对btnBgView进行了初始化。且在上一步的操做中将其默认状态设置为了 隐藏。
-(void)effectAction{ if (self.btnBgView.hidden) { [UIView animateWithDuration:1 animations:^{ self.btnBgView.transform = CGAffineTransformMakeTranslation(-WIDTH, 0); }]; self.btnBgView.hidden = NO; }else{ [self resumeState]; } }
设置一个Button 不设置其颜色,至关于看不见,可是仍是存在的,将这个button 添加到咱们刚才建立的 btnBgView 上。
- (UIButton *)addSetBtn:(NSString *)btnTitle withBtnTag:(NSInteger)btnTag withBtnX:(CGFloat)btnX{ UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.frame = CGRectMake(btnX, 0, (self.btnBgView.frame.size.width - 8) / 5, 80); btn.tag = btnTag; [btn setTitle:btnTitle forState:UIControlStateNormal]; [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside]; [self.btnBgView addSubview:btn]; return btn; }
将上面的button 经过循环建立5个滤镜效果 按钮
- (void)creatSetectBtn{ for (NSInteger i = 0; i<5; i ++) { CGFloat x = (self.btnBgView.frame.size.width - 8) / 5 * i + 2 *i; [self addSetBtn:[NSString stringWithFormat:@"效果%ld",i + 1] withBtnTag:i withBtnX:x]; } }
滤镜按钮点击状态,初始化最开始咱们建立的 UIButton *_tempBtn
- (void)btnState:(UIButton *)btn{ if (!_tempBtn.enabled && _tempBtn != nil) { _tempBtn.enabled = YES; _tempBtn.selected = !_tempBtn.selected; _tempBtn.backgroundColor = [UIColor clearColor]; } btn.selected = !btn.selected; if (btn.selected) { btn.backgroundColor = [UIColor redColor]; btn.enabled = NO; _tempBtn = btn; } }
##3.5滤镜切换
-(void)changeEffct:(GPUImageFilter *)mFilter withBtn:(UIButton *)btn{ //移除上一个效果 [_mCamera removeTarget:_mFilter]; _mFilter = mFilter; // 添加滤镜到相机上 [_mCamera addTarget:_mFilter]; [_mFilter addTarget:_mGPUImageView]; //调用收缩滤镜方法的方法 [self resumeState]; [self btnState:btn]; }
切换滤镜的方法
- (void)btnAction:(UIButton *)btn{ switch (btn.tag) { case (EffctTypeOne):{ //建立一个新的滤镜 GPUImageBulgeDistortionFilter *mfilter = [[GPUImageBulgeDistortionFilter alloc]init]; //调用切换滤镜方法 [self changeEffct:mfilter withBtn:btn]; } break; case (EffctTypeTwo):{ GPUImagePinchDistortionFilter *mfilter = [[GPUImagePinchDistortionFilter alloc]init]; [self changeEffct:mfilter withBtn:btn]; } break; case (EffctTypeThree):{ GPUImageStretchDistortionFilter *mfilter = [[GPUImageStretchDistortionFilter alloc]init]; [self changeEffct:mfilter withBtn:btn]; } break; case (EffctTypeFour):{ GPUImageGlassSphereFilter *mfilter = [[GPUImageGlassSphereFilter alloc]init]; [self changeEffct:mfilter withBtn:btn]; } break; case (EffctTypeFive):{ GPUImageVignetteFilter *mfilter = [[GPUImageVignetteFilter alloc]init]; [self changeEffct:mfilter withBtn:btn]; } break; default: break; } }