水印相機-gpuimage

[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)鍵算法就好了。


gpuimage 詳解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末味咳,一起剝皮案震驚了整個濱河市庇勃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莺葫,老刑警劉巖匪凉,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捺檬,居然都是意外死亡再层,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門堡纬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聂受,“玉大人,你說我怎么就攤上這事烤镐〉凹茫” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵炮叶,是天一觀的道長碗旅。 經(jīng)常有香客問我渡处,道長,這世上最難降的妖魔是什么祟辟? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任医瘫,我火速辦了婚禮,結(jié)果婚禮上旧困,老公的妹妹穿的比我還像新娘醇份。我一直安慰自己,他們只是感情好吼具,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布僚纷。 她就那樣靜靜地躺著,像睡著了一般拗盒。 火紅的嫁衣襯著肌膚如雪怖竭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天陡蝇,我揣著相機與錄音侵状,去河邊找鬼。 笑死毅整,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的绽左。 我是一名探鬼主播悼嫉,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拼窥!你這毒婦竟也來了戏蔑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤鲁纠,失蹤者是張志新(化名)和其女友劉穎总棵,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體改含,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡情龄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捍壤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骤视。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鹃觉,靈堂內(nèi)的尸體忽然破棺而出专酗,到底是詐尸還是另有隱情,我是刑警寧澤盗扇,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布祷肯,位于F島的核電站沉填,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏佑笋。R本人自食惡果不足惜翼闹,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望允青。 院中可真熱鬧橄碾,春花似錦、人聲如沸颠锉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琼掠。三九已至拒垃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓷蛙,已是汗流浹背悼瓮。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艰猬,地道東北人横堡。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像冠桃,于是被迫代替她去往敵國和親命贴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容