iOS—使用GPUImage对照片和相机添加滤镜

#1GPUImage 的下载与安装git

GPUImage 是一个开源的图像处理库,提供了很是多的滤镜效果来加工图片。GPUImage 并不像通常的第三方库能够直接拖入到工程中使用,而是须要先在本地编译,而后将编译后的文件拖入到工程中使用。配置步骤以下:github

  1. :首先下载GPUImage https://github.com/BradLarson/GPUImagexcode

  2. :解压后,在framework 目录下,打开 GPUImage.xcodeproj 工程ide

输入图片说明

  1. 把Headers文件夹下 Project中的头文件,所有拖到 Public文件夹下面 输入图片说明
  2. 运行该工程
  3. 点击Products下的 libGPUImage.a,右键, show in finder 输入图片说明
  4. 把该目录下的libGpuImage.a 和 User文件夹拖到咱们新建的工程下面 输入图片说明 输入图片说明
  5. .m中导入头文件 #import "GPUImage.h",就可使用GPUImage了

#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;
    }
}

输入图片说明

相关文章
相关标签/搜索