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