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

輸入圖片說明

相關文章
相關標籤/搜索