[self.myCamera setCaptureSessionPreset:AVCaptureSessionPreset640x480];//設(shè)置相機尺寸
[self.videoCamera rotateCamera];// 切換攝像頭前后翻轉(zhuǎn)
// 切換濾鏡
-(void)change1:(UIButton*)sender{
? ? [self.myCamera removeAllTargets];相機去除濾鏡組和GPUImageView
? ? [self.myFilterGroup removeAllTargets];//去除容器內(nèi)的所有濾鏡 (這種方式有問題實際上并沒有去處數(shù)組里面的濾鏡多次切換會內(nèi)存溢出導(dǎo)致奔潰)
應(yīng)該改為一下子2行代碼:
? ?self.myFilterGroup =nil;
? ? self.myFilterGroup = [[GPUImageFilterGroup alloc]init];
? ? GPUImageStretchDistortionFilter *stretchDistortionFilter0 = [[GPUImageStretchDistortionFilter alloc] init];
? ? [selfaddGPUImageFilter:stretchDistortionFilter0];//重新添加濾鏡
//? ? GPUImageColorInvertFilter *stretchDistortionFilter = [[GPUImageColorInvertFilter alloc] init];
//? ? [self addGPUImageFilter:stretchDistortionFilter];
? ? [self.myCamera addTarget:self.myFilterGroup];//相機上添加濾鏡組
? ? [self.myFilterGroup addTarget:self.myGPUImageView];//相機上添加GPUImageView
}
#pragma mark 將濾鏡加在FilterGroup中并且設(shè)置初始濾鏡和末尾濾鏡
- (void)addGPUImageFilter:(GPUImageFilter *)filter{
? ? [self.myFilterGroup addFilter:filter];
? ? GPUImageOutput *newTerminalFilter = filter;
? ? NSInteger count = self.myFilterGroup.filterCount;
? ? if(count ==1)
? ? {
? ? ? ? //設(shè)置初始濾鏡
? ? ? ? self.myFilterGroup.initialFilters=@[newTerminalFilter];
? ? ? ? //設(shè)置末尾濾鏡
? ? ? ? self.myFilterGroup.terminalFilter= newTerminalFilter;
? ? }else
? ? {
? ? ? ? GPUImageOutput *terminalFilter? ? =self.myFilterGroup.terminalFilter;
? ? ? ? NSArray*initialFilters? ? ? ? ? ? ? ? ? ? ? ? ? =self.myFilterGroup.initialFilters;
? ? ? ? [terminalFilteraddTarget:newTerminalFilter];
? ? ? ? //設(shè)置初始濾鏡
? ? ? ? self.myFilterGroup.initialFilters=@[initialFilters[0]];
? ? ? ? //設(shè)置末尾濾鏡
? ? ? ? self.myFilterGroup.terminalFilter= newTerminalFilter;
? ? }
}
照片的水印帆离,我是采用得到了帶濾鏡的uiimage和水印層獲得uiimage 合成一張照片
一邊錄制一邊加水印。其實是用了混合模式里的一些混合方式屠尊。選擇2個數(shù)據(jù)源 1是所需要的濾鏡組 另一就是水印層創(chuàng)建的GPUImageUIElement喜鼓,可選擇如果不需要不透明拔妥,直接貼上去建議使用GPUImageScreenBlendFilter屏幕混合方式 或者GPUImageDivideBlendFilter?分割混合婴氮。效果會好一些纵苛。不過還是會有一點模糊。
#pragma mark混合
-(void)Starwatervideo{
? ? [_videoCamera removeAllTargets];
? ? self.VideFilterGroup =nil;
? ? self.VideFilterGroup = [[GPUImageFilterGroup alloc]init];
? ? [self addVideoGPUImageFilter:self.BrightnessFilter];
? ? [self addVideoGPUImageFilter:self.BeautifyFilter];
? ? GPUImageUIElement *uiElement = [[GPUImageUIElement alloc] initWithView:self.tempview];
//? ? _filter1 = [[GPUImageScreenBlendFilter alloc] init];
? ? _filter1 = [[GPUImageDivideBlendFilter alloc] init];
//? ? _filter1.mix = 0.5f;
? ? [_videoCamera addTarget:self.VideFilterGroup];
? ? [uiElementaddTarget:_filter1];
? ? [self.VideFilterGroup addTarget:_filter1];
? ? [_filter1 addTarget:self.filterView];
//? ? [self addVideoGPUImageFilter:_filter1];
//? ? [self.VideFilterGroup addTarget:_filterView];
? ? [_videoCamera startCameraCapture];
//刷新
? ? [self.VideFilterGroup setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
? ? ? ? [uiElementupdate];
? ? }];
}
#pragma mark開始錄制和結(jié)束錄制
-(void)takeVideIsStop:(BOOL)isstop{
? ? NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie4.m4v"];
? ? NSURL*movieURL = [NSURLfileURLWithPath:pathToMovie];
? ? if(!isstop) {//開始拍攝
? ? ? ? [self Starwatervideo];
? ? ? ? unlink([pathToMovie UTF8String]); // 如果已經(jīng)存在文件照弥,AVAssetWriter會有異常腻异,刪除舊文件
//? ? ? ? self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(SCREEN_WIDTH, SCREEN_HEIGHT-STATUS_BAR_HIGHT)];
? ? ? ? self.movieWriter= [[GPUImageMovieWriteralloc]initWithMovieURL:movieURLsize:CGSizeMake(SCREEN_WIDTH,SCREEN_HEIGHT)];
? ? ? ? self.movieWriter.encodingLiveVideo = YES;
//? ? ? ? [_VideFilterGroup addTarget:_movieWriter];
? ? ? ? [_filter1 addTarget:_movieWriter];
? ? ? ? _videoCamera.audioEncodingTarget = _movieWriter;
? ? ? ? [self.movieWriter startRecording];
? ? }else{//結(jié)束拍攝
//? ? ? ? [_VideFilterGroup removeTarget:_movieWriter];
? ? ? ? [_filter1 removeTarget:_movieWriter];
? ? ? ? _videoCamera.audioEncodingTarget = nil;
? ? ? ? [_movieWriter finishRecording];
? ? ? ? ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
? ? ? ? if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(pathToMovie))
? ? ? ? {
? ? ? ? ? ? [librarywriteVideoAtPathToSavedPhotosAlbum:movieURLcompletionBlock:^(NSURL*assetURL,NSError*error)
?? ? ? ? ? ? {
?? ? ? ? ? ? ? ? dispatch_async(dispatch_get_main_queue(), ^{
?? ? ? ? ? ? ? ? ? ? if(error) {
?? ? ? ? ? ? ? ? ? ? ? ? UIAlertView*alert = [[UIAlertViewalloc]initWithTitle:@"視頻保存失敗"message:nil
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:nil];
?? ? ? ? ? ? ? ? ? ? ? ? [alertshow];
?? ? ? ? ? ? ? ? ? ? }else{
?? ? ? ? ? ? ? ? ? ? ? ? UIAlertView*alert = [[UIAlertViewalloc]initWithTitle:@"視頻保存成功"message:nil
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:selfcancelButtonTitle:@"OK"otherButtonTitles:nil];
?? ? ? ? ? ? ? ? ? ? ? ? [alertshow];
?? ? ? ? ? ? ? ? ? ? }
?? ? ? ? ? ? ? ? });
?? ? ? ? ? ? }];
? ? ? ? }else{
? ? ? ? }
? ? }
}
防止鏈接失效,下面一些內(nèi)容來自上述鏈接
? //? ? 如果錄像的額時候这揣,圖像高亮下悔常,可以在初始化GPUImageVideoCamera的時候,加上
? ? [_videoCamera addAudioInputsAndOutputs];
? ? //? ? //如果是調(diào)用前置攝像頭就發(fā)現(xiàn)成的像是左右相反了给赞,就看下是不是開啟了鏡像
? ? //? ? self.videoCamera.horizontallyMirrorFrontFacingCamera = YES;
? ? //? ? self.videoCamera.horizontallyMirrorRearFacingCamera = NO;
?//? 如果僅僅是暫停錄制机打,不暫停攝像頭畫面
? ? //錄制暫停
? ? [self.movieWriter setPaused:true];
? ? //錄制繼續(xù)
? ? [self.movieWriter setPaused:false];
//? ? 如果是暫停錄制,并且也要暫停攝像頭畫面
? ? //錄制暫停
? ? [self.movieWriter setPaused:true];
? ? //攝像頭暫停
? ? [_videoCamera pauseCameraCapture];
? ? //錄制繼續(xù)
? ? [self.movieWriter setPaused:false];
? ? //攝像頭繼續(xù)
? ? [_videoCamera resumeCameraCapture];
視頻防抖
AVCaptureDevice *device = self.videoCamera.inputCamera;
? ? ? ? AVCaptureConnection *connection = self.videoCamera.videoCaptureConnection;
? ? ? ? AVCaptureVideoStabilizationMode stabilizationMode = AVCaptureVideoStabilizationModeCinematic;//強制開啟視頻防抖
? ? ? ? if ([device.activeFormat isVideoStabilizationModeSupported:stabilizationMode]) {
? ? ? ? ? ? [connectionsetPreferredVideoStabilizationMode:stabilizationMode];
? ? ? ? }
利用lut文件映射出濾鏡,用lut文件去ps生成一個64X64X64 的圖如果是圖片詳細做法柑蛇,網(wǎng)上有很多資料:比如這個
- (UIImage*)generateImage:(UIImage*)inputImage
{
? ? UIImage*outputImage;
? ? GPUImagePicture*stillImageSource = [[GPUImagePicturealloc]initWithImage:self.Image];
? ? //添加濾鏡
? ? GPUImageLookupFilter *lookUpFilter = [[GPUImageLookupFilter alloc] init];
? ? GPUImagePicture*lookupImg = [[GPUImagePicture alloc]initWithImage:inputImage];
? ? [lookupImgaddTarget:lookUpFilteratTextureLocation:1];
? ? [stillImageSourceaddTarget:lookUpFilteratTextureLocation:0];
? ? [lookUpFilteruseNextFrameForImageCapture];
? ? if([lookupImg processImageWithCompletionHandler:nil] && [stillImageSource processImageWithCompletionHandler:nil]) {
? ? ? ? outputImage = [lookUpFilterimageFromCurrentFramebuffer];
? ? }
? ? returnoutputImage;
}
但是要在錄制視頻時候添加進去就需要生成對應(yīng)的gpuimagefiter的濾鏡芥挣。所以需要自定義一個GPUImageFilterGroup濾鏡,然后把.m實現(xiàn)方法里的圖片換成我們需要的耻台,就生成了一個通用的我們想要的濾鏡了
一遍錄制一遍添加水印空免,網(wǎng)上也有資料比如這個?但是實際上會遇到2個問題,第一是清晰度第二個是色差
在添加水印時候是需要編輯更改等操作導(dǎo)致粘我,水印并非一開始就和視頻混合鼓蜒,先在一個圖層說添加水印在這個圖層可以進行編輯拖動更改甚至更換水印痹换。直到開始錄制才去和相機錄制混合,這樣就會有原版的水印圖層和混合好的視頻展示圖層都弹。兩個地方都會有水印娇豫,這樣如果兩個位置不一樣就會出現(xiàn)重復(fù)。所以需要計算好水印圖層和視頻添加水印時候的坐標畅厢。有2種解決方案
方案一:把整個水印層(水印的父是圖)作為GPUImageUIElement 的目標圖層冯痢。這樣就不會出現(xiàn)位置問題,但是會出現(xiàn)水印模糊問題
推薦方案二:重新創(chuàng)建一個圖層框杜,寬高(像素點)和你所選擇相機的質(zhì)量的像素保持一致
比如:相機初始化選擇了AVCaptureSessionPresetiFrame1280x720 那么圖層的寬*高=720 *1280
然后水印生成圖片浦楣,再用uiimageview添加到新圖層上,位置和大小都要按照新圖層的寬和原來的寬的比例去計算現(xiàn)在水印在新圖層的X咪辱,Y,寬振劳,高。這樣做就是為了水印和視頻源被同比例的拉伸達到不影響清晰的的效果油狂。
如果有對視頻做裁剪历恐,那新圖層的寬高是裁剪之后的。
網(wǎng)上的那些方法對于不透明的為1的水印沒影響专筷,但是對有帶不透明的水印會造成色差弱贼,色彩或重或淡,原因是GPUImageAlphaBlendFilter 的像素點混合算法就是按照色彩疊加生成新色值的算法磷蛹,所以需要改變計算方式自定義過一個混合濾鏡吮旅。算法是這個
修改GPUImageAlphaBlendFilter 里面的關(guān)鍵算法就好了。