直播預(yù)覽層添加濾鏡效果
原理,在顯示之前,提前對(duì)圖片進(jìn)行濾鏡處理,把處理后的圖片展示出來(lái)就好了.
CIFiter(濾鏡類):給圖片添加特殊效果(模糊,高亮等等).
-
CIFiter濾鏡分類(一個(gè)濾鏡可能屬于多個(gè)分類)
- kCICategoryDistortionEffect 扭曲效果,比如bump、旋轉(zhuǎn)、hole
- kCICategoryGeometryAdjustment 幾何開(kāi)著調(diào)整,比如仿射變換、平切、透視轉(zhuǎn)換
- kCICategoryCompositeOperation 合并,比如源覆蓋(source over)、最小化、源在頂(source atop)、色彩混合模式
- kCICategoryHalftoneEffect Halftone效果,比如screen、line screen、hatched
- kCICategoryColorAdjustment 色彩調(diào)整,比如伽馬調(diào)整、白點(diǎn)調(diào)整、曝光
- kCICategoryColorEffect 色彩效果,比如色調(diào)調(diào)整、posterize
- kCICategoryTransition 圖像間轉(zhuǎn)換,比如dissolve、disintegrate with mask、swipe
- kCICategoryTileEffect 瓦片效果,比如parallelogram、triangle
- kCICategoryGenerator 圖像生成器,比如stripes、constant color、checkerboard
- kCICategoryGradient 漸變,比如軸向漸變、仿射漸變、高斯?jié)u變
- kCICategoryStylize 風(fēng)格化,比如像素化、水晶化
- kCICategorySharpen 銳化、發(fā)光
- kCICategoryBlur 模糊,比如高斯模糊、焦點(diǎn)模糊、運(yùn)動(dòng)模糊
- kCICategoryStillImage 能用于靜態(tài)圖像
- kCICategoryVideo 能用于視頻
- kCICategoryInterlaced 能用于交錯(cuò)圖像
- kCICategoryNonSquarePixels 能用于非矩形像素
- kCICategoryHighDynamicRange 能用于HDR
- kCICategoryBuiltIn 獲取所有濾鏡
-
常用圖片處理濾鏡:
// 懷舊 --> CIPhotoEffectInstant 單色 --> CIPhotoEffectMono // 黑白 --> CIPhotoEffectNoir 褪色 --> CIPhotoEffectFade // 色調(diào) --> CIPhotoEffectTonal 沖印 --> CIPhotoEffectProcess // 歲月 --> CIPhotoEffectTransfer 鉻黃 --> CIPhotoEffectChrome 自動(dòng)處理濾鏡,通過(guò)CIImage獲取,CIImage會(huì)自動(dòng)對(duì)圖片進(jìn)行濾鏡處理
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// 轉(zhuǎn)換為CIImage
CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
NSArray *fiters = [ciImage autoAdjustmentFilters];
NSLog(@"%@",fiters);
-
常有的自動(dòng)濾鏡
CIRedEyeCorrection:修復(fù)因相機(jī)的閃光燈導(dǎo)致的各種紅眼 CIFaceBalance:調(diào)整膚色 CIVibrance:在不影響膚色的情況下,改善圖像的飽和度 CIToneCurve:改善圖像的對(duì)比度 CIHighlightShadowAdjust:改善陰影細(xì)節(jié) 濾鏡對(duì)象創(chuàng)建(也可以使用coreImage自動(dòng)處理濾鏡,就不需要自己創(chuàng)建)
濾鏡屬性可以通過(guò)inputKeys屬性獲取
濾鏡工作原理,給濾鏡傳入一個(gè)圖片,濾鏡有個(gè)方法,可以獲取處理完成的圖片outputImage.
CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectInstant"];
[fiter setValue:ciImage forKey:@"inputImage"];
ciImage = fiter.outputImage;
直播預(yù)覽層添加濾鏡效果步驟
- 取出捕獲到的幀(CMSampleBufferRef) -> 獲取幀里面圖片信息(CVImageBufferRef) -> CIFiter濾鏡處理 ->轉(zhuǎn)換成UIImage -> 設(shè)置為UIImageView的image就能實(shí)時(shí)顯示捕獲的畫(huà)面
if (_videoConnection == connection) {
// 獲取圖片信息
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// 轉(zhuǎn)換為CIImage
CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
// 創(chuàng)建濾鏡
CIFilter *fiter = [CIFilter filterWithName:@"CIFaceBalance"];
[fiter setValue:ciImage forKey:@"inputImage"];
[fiter setValue:@100 forKey:@"inputStrength"];
ciImage = fiter.outputImage;
// 轉(zhuǎn)換UIImage
UIImage *image = [UIImage imageWithCIImage:ciImage];
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
通過(guò)GPU渲染圖片顯示
- 只有OpenGL才能操控GPU,需要用到OpenGL才行
- CIContext:通過(guò)這個(gè)上下文的方法渲染圖片(createCGImage)
- CIContext:通過(guò)OpenGL的上下文創(chuàng)建,就能用GPU渲染圖片,處理圖片效率高.(contextWithEAGLContext)
// 獲取圖片信息
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// 轉(zhuǎn)換為CIImage
CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
// 創(chuàng)建濾鏡
CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectInstant"];
[fiter setValue:ciImage forKey:@"inputImage"];
ciImage = fiter.outputImage;
EAGLContext *openglCtx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
CIContext *ctx = [CIContext contextWithEAGLContext:openglCtx];
CGImageRef imgRef = [ctx createCGImage:ciImage fromRect:ciImage.extent];
UIImage *image = [UIImage imageWithCGImage:imgRef];
// 用完了及時(shí)清空,否則內(nèi)存溢出,造成程序崩潰.使用C語(yǔ)言的時(shí)候,需要特別注意內(nèi)存管理.
CGImageRelease(imgRef);
// 轉(zhuǎn)換UIImage
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
- 注意點(diǎn):有個(gè)地方需要自己管理內(nèi)存,否則程序會(huì)閃退,報(bào)下列錯(cuò)誤

內(nèi)存溢出bug.png
CGImageRef imgRef = [ctx createCGImage:ciImage fromRect:ciImage.extent];
UIImage *image = [UIImage imageWithCGImage:imgRef];
// 用完了及時(shí)清空,否則內(nèi)存溢出,造成程序崩潰.使用C語(yǔ)言的時(shí)候,需要特別注意內(nèi)存管理.
CGImageRelease(imgRef);
- 注意點(diǎn):會(huì)報(bào)壞內(nèi)存訪問(wèn),原因有些對(duì)象銷(xiāo)毀了,沒(méi)有及時(shí)清空,再次用到就壞內(nèi)存訪問(wèn)
- 測(cè)試:不需要添加濾鏡效果,容易測(cè)試出來(lái),報(bào)下列錯(cuò)誤

壞內(nèi)存訪問(wèn).png
- 解決:把一個(gè)周期的代碼,放入一個(gè)自動(dòng)釋放池里管理,下一個(gè)運(yùn)行循環(huán),會(huì)自動(dòng)清空已經(jīng)銷(xiāo)毀的對(duì)象。
- 自動(dòng)釋放池:可以用來(lái)管理一段代碼中對(duì)象的生命周期。
@autoreleasepool {
// 獲取圖片信息
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// 轉(zhuǎn)換為CIImage
CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
// 創(chuàng)建濾鏡
CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectInstant"];
[fiter setValue:ciImage forKey:@"inputImage"];
ciImage = fiter.outputImage;
EAGLContext *openglCtx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
CIContext *ctx = [CIContext contextWithEAGLContext:openglCtx];
CGImageRef imgRef = [ctx createCGImage:ciImage fromRect:ciImage.extent];
UIImage *image = [UIImage imageWithCGImage:imgRef];
// 用完了及時(shí)清空,否則內(nèi)存溢出,造成程序崩潰.使用C語(yǔ)言的時(shí)候,需要特別注意內(nèi)存管理.
CGImageRelease(imgRef);
// 轉(zhuǎn)換UIImage
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
}