綜述
CoreImage是什么?
Core Image 是 iOS 5 加入到 iOS 平臺(tái)的一個(gè)圖像處理框架,它基于OpenGL頂層創(chuàng)建,底層則用著色器來(lái)處理圖像,這意味著它利用了GPU基于硬件加速來(lái)處理圖像,提供了強(qiáng)大高效的圖像處理功能, 內(nèi)置了很多功能強(qiáng)大的濾鏡(Filter) , 這些Filter 提供了各種各樣的效果, 并且還可以通過 "濾鏡鏈" 將各種效果的 Filter疊加起來(lái),來(lái)形成強(qiáng)大的自定義效果。
現(xiàn)階段CoreImage引入 CIDetector,提供一些常用的圖片識(shí)別功能:人臉識(shí)別、條形碼識(shí)別、文本識(shí)別等,并且與越來(lái)越多的框架結(jié)合:OpenGL ES . Metal . SceneKit . SpriteKit等。
如何使用CoreImage濾鏡
我們先來(lái)看一下效果圖

下面是實(shí)現(xiàn)該效果的代碼
//后臺(tái)線程渲染,防止阻塞主線程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^(void){
//獲取圖片資源,imageview.image是原圖
CIImage *Ciimage = [[CIImage alloc]initWithImage:imageview.image];
//根據(jù)濾鏡名稱創(chuàng)建濾鏡
CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectMono" keysAndValues:kCIInputImageKey,Ciimage, nil];
//這里使用的是默認(rèn)參數(shù),也可自己設(shè)置
[fiter setDefaults];
//創(chuàng)建繪制上下文,默認(rèn)使用GPU繪制
//創(chuàng)建基于 GPU 的 CIContext 對(duì)象
CIContext *context = [CIContext contextWithOptions:nil];
//或者使用這種方法創(chuàng)建基于 GPU 的 CIContext 對(duì)象
// EAGLContext *gpucontext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
// CIContext *context = [CIContext contextWithEAGLContext: gpucontext];
//創(chuàng)建基于 CPU 的 CIContext 對(duì)象
// CIContext *context = [CIContext contextWithOptions: [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];
// 渲染并輸出CIImage
CIImage *outputImage = [fiter outputImage];
// 創(chuàng)建CGImage句柄
CGImageRef Cgimage = [context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *showimage = [UIImage imageWithCGImage:Cgimage];
// 釋放CGImage句柄
CGImageRelease(Cgimage);
dispatch_async(dispatch_get_main_queue(), ^(void){
//回到主線程給控件賦值(渲染之后的圖片)
imageview.image = showimage;
});
});
注意事項(xiàng)
小知識(shí)點(diǎn)
獲取CIFilter-Names : [CIFilter filterNamesInCategory:nil]
獲取當(dāng)前Filter的輸入?yún)?: [filter inputKeys]
獲取當(dāng)前Filter的輸出參數(shù) : [filter outputKeys]
輸入?yún)?shù)的attributes : [filter attributes]
UIImage 屬性.CIImage 可能為nil。只有UIImage基于CIImage創(chuàng)建的,才能通過.CIImage得到 <CIImage>
使用filter生成的圖片并不是總能使用UIImage進(jìn)行渲染
生成的圖片.extent 可能會(huì)是 "infinite(無(wú)窮大)".這樣的圖片不會(huì)被渲染, 需要進(jìn)行CICrop進(jìn)行裁切。
如果filter對(duì)圖片進(jìn)行放大等操作而且需要裁切的,那么他是通過"Center向四周放大的" 那么或許圖片的時(shí)候應(yīng)該考慮到裁切的范圍補(bǔ)償。
注意事項(xiàng)
1.為了防止阻塞主線程,用GCD異步執(zhí)行濾鏡與渲染操作,在獲取渲染后的照片以后,返回主線程進(jìn)行界面的更新。
2 不要重復(fù)應(yīng)用濾鏡,即使是同一個(gè)濾鏡也不要應(yīng)用兩次,因?yàn)闉V鏡后輸出照片包含濾鏡鏈,在進(jìn)行照片渲染是會(huì)將濾鏡鏈效果疊加到原始數(shù)據(jù)上,這時(shí)會(huì)造成問題。比如,有一個(gè)CIImage,上面配置了強(qiáng)度為0.5的棕色濾鏡,現(xiàn)在通過滑塊將強(qiáng)度改為0.6,這個(gè)濾鏡應(yīng)該用在原始的CIImage上,如果不是原始的CIImage上,那么新的CIImage中將包含強(qiáng)度為0.5和0.6的棕色濾鏡,而我們只想0.6的棕色濾鏡,這樣就造成錯(cuò)誤,這一點(diǎn)在編寫程序的時(shí)候一定要切忌。
3 app中應(yīng)用的濾鏡太多,改變速率太快,如果是根據(jù)滑塊來(lái)產(chǎn)生事件的話,一定要注意在使用滑條值前要首先判斷更改的濾鏡當(dāng)前是否正在起作用,如果該濾鏡正在生成新的渲染圖片,則應(yīng)該使用這次滑塊的更新。這一點(diǎn)也是很重要的,弄的不好常常導(dǎo)致程序崩潰,出現(xiàn)內(nèi)存泄露問題。
4 建一個(gè)全局的變量CIContext去維護(hù)每一次濾鏡參數(shù)的改變,你需要重新用新的值進(jìn)行圖像過濾。因?yàn)槊總€(gè)上下文中都是有緩存的,頻繁創(chuàng)建就用不到上下文中的緩存,既浪費(fèi)資源又浪費(fèi)內(nèi)存的消耗,使程序非常地慢。另一步優(yōu)化是你可以保存CIFilter和存有初始圖像的CIImage。對(duì)每一個(gè)輸出你都需要生成一個(gè)新的CIFilter,但是每次初始用到的圖像始終是同一個(gè)。