綜述
CoreImage是什么?
Core Image 是 iOS 5 加入到 iOS 平臺的一個圖像處理框架,它基于OpenGL頂層創建,底層則用著色器來處理圖像,這意味著它利用了GPU基于硬件加速來處理圖像,提供了強大高效的圖像處理功能, 內置了很多功能強大的濾鏡(Filter) , 這些Filter 提供了各種各樣的效果, 并且還可以通過 "濾鏡鏈" 將各種效果的 Filter疊加起來,來形成強大的自定義效果。
現階段CoreImage引入 CIDetector,提供一些常用的圖片識別功能:人臉識別、條形碼識別、文本識別等,并且與越來越多的框架結合:OpenGL ES . Metal . SceneKit . SpriteKit等。
如何使用CoreImage濾鏡
我們先來看一下效果圖
下面是實現該效果的代碼
//后臺線程渲染,防止阻塞主線程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^(void){
//獲取圖片資源,imageview.image是原圖
CIImage *Ciimage = [[CIImage alloc]initWithImage:imageview.image];
//根據濾鏡名稱創建濾鏡
CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectMono" keysAndValues:kCIInputImageKey,Ciimage, nil];
//這里使用的是默認參數,也可自己設置
[fiter setDefaults];
//創建繪制上下文,默認使用GPU繪制
//創建基于 GPU 的 CIContext 對象
CIContext *context = [CIContext contextWithOptions:nil];
//或者使用這種方法創建基于 GPU 的 CIContext 對象
// EAGLContext *gpucontext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
// CIContext *context = [CIContext contextWithEAGLContext: gpucontext];
//創建基于 CPU 的 CIContext 對象
// CIContext *context = [CIContext contextWithOptions: [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];
// 渲染并輸出CIImage
CIImage *outputImage = [fiter outputImage];
// 創建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;
});
});
注意事項
小知識點
獲取CIFilter-Names : [CIFilter filterNamesInCategory:nil]
獲取當前Filter的輸入參 : [filter inputKeys]
獲取當前Filter的輸出參數 : [filter outputKeys]
輸入參數的attributes : [filter attributes]
UIImage 屬性.CIImage 可能為nil。只有UIImage基于CIImage創建的,才能通過.CIImage得到 <CIImage>
使用filter生成的圖片并不是總能使用UIImage進行渲染
生成的圖片.extent 可能會是 "infinite(無窮大)".這樣的圖片不會被渲染, 需要進行CICrop進行裁切。
如果filter對圖片進行放大等操作而且需要裁切的,那么他是通過"Center向四周放大的" 那么或許圖片的時候應該考慮到裁切的范圍補償。
注意事項
1.為了防止阻塞主線程,用GCD異步執行濾鏡與渲染操作,在獲取渲染后的照片以后,返回主線程進行界面的更新。
2 不要重復應用濾鏡,即使是同一個濾鏡也不要應用兩次,因為濾鏡后輸出照片包含濾鏡鏈,在進行照片渲染是會將濾鏡鏈效果疊加到原始數據上,這時會造成問題。比如,有一個CIImage,上面配置了強度為0.5的棕色濾鏡,現在通過滑塊將強度改為0.6,這個濾鏡應該用在原始的CIImage上,如果不是原始的CIImage上,那么新的CIImage中將包含強度為0.5和0.6的棕色濾鏡,而我們只想0.6的棕色濾鏡,這樣就造成錯誤,這一點在編寫程序的時候一定要切忌。
3 app中應用的濾鏡太多,改變速率太快,如果是根據滑塊來產生事件的話,一定要注意在使用滑條值前要首先判斷更改的濾鏡當前是否正在起作用,如果該濾鏡正在生成新的渲染圖片,則應該使用這次滑塊的更新。這一點也是很重要的,弄的不好常常導致程序崩潰,出現內存泄露問題。
4 建一個全局的變量CIContext去維護每一次濾鏡參數的改變,你需要重新用新的值進行圖像過濾。因為每個上下文中都是有緩存的,頻繁創建就用不到上下文中的緩存,既浪費資源又浪費內存的消耗,使程序非常地慢。另一步優化是你可以保存CIFilter和存有初始圖像的CIImage。對每一個輸出你都需要生成一個新的CIFilter,但是每次初始用到的圖像始終是同一個。