生活随笔
收集整理的這篇文章主要介紹了
iOS框架介绍之coreImage
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.coreImage的介紹
???????? coreImage是IOS5中新加入的一個Objective-c的框架,提供了強大高效的圖像處理功能,用來對基于像素的圖像進行操作與分析。IOS提供了很多強大的濾鏡(Filter),其中IOS5中有48種,而到了最新的IOS6 Filter已經增加到了93種之多,并且這一數字會繼續增加。這些Filter提供了各種各樣的效果,并且還可以通過濾鏡鏈將各種效果的Filter疊加起來,形成強大的自定義效果,如果你對該效果很滿意,還可以子類化濾鏡。
????????
2.coreImage框架中的對象
?
2.1 CIImage
???????? CIImage是CoreImage框架中最基本代表圖像的對象,他不僅包含元圖像數據,還包含作用在原圖像上的濾鏡鏈。這里我想特別強調的是CIImage和其他圖像是不同的,在CIImage被CIContext渲染出來之前,他是依賴于濾鏡鏈的,濾鏡是不會更改CIImage中的圖像數據。這個需要正確理解,不然會給你的程序造成錯誤。說到了CIImage的不同,就必須得提一下如何創建CIImage了,CIImage是不能直接有UIImage轉化而來的,有以下幾種創建CIImage的類方法:
[cpp] view plaincopy
1.CIImage*image=[CIImage?imageWithContentsOfURL:myURL];??2.CIImage*image=[CIImage?imageWithData:myData];??3.CIImage*image=[CIImage?imageWithCGImage:myCgimage];??4.CIImage*image=[CIImage?imageWithCVPixelBuffer:CVBuffer];??
2.2 CIFilter
???????? CIFilter用來表示CoreImage提供的各種濾鏡。濾鏡使用鍵-值來設置輸入值,一旦這些值設置好,CIFilter就可以用來生成新的CIImage輸出圖像了。記住,這里的輸出的圖像不會進行實際的圖像渲染,他只包含一個對輸入圖像的引用以及需要應用與數據上的濾鏡鏈。IOS永遠在最佳的時間選擇渲染圖像。
???????? CIFilter提供了一個簡單的方法查詢可用的濾鏡種類:[CIFilterfilterNamesInCategory:kCICategoryBuiltIn];//搜索屬于 kCICategoryBuiltIn類別的所有濾鏡名字,返回一個數組;
[CIFilterfilterNamesInCategories];//搜索所有可用的濾鏡名稱;
調用[CIFilter attributes]會返回filter詳細信息,下面我們以一個具體列子來看看他返回的信息。
????? 下面是我程序返回的一個叫做CISepiaTone濾鏡返回的詳細信息:
[cpp] view plaincopy
2012-09-18?16:17:09.155?SZFYKJHomeWorkVersion1[2836:f803]?{??????CIAttributeFilterCategories?=?????(??????????CICategoryColorEffect,?????????????????CICategoryVideo,???????????????????????CICategoryInterlaced,??????????CICategoryNonSquarePixels,??????????CICategoryStillImage,??????????CICategoryBuiltIn??????);??????CIAttributeFilterDisplayName?=?"Sepia?Tone";??????CIAttributeFilterName?=?CISepiaTone;???????????????????????????????????????????????????inputImage?=?????{???????????????????????????CIAttributeClass?=?CIImage;???????????????CIAttributeType?=?CIAttributeTypeImage;??????};??????inputIntensity?=?????{????????????????????????CIAttributeClass?=?NSNumber;??????????????????CIAttributeDefault?=?1;???????????????????CIAttributeIdentity?=?0;??????????????????????CIAttributeMax?=?1;???????????????????????CIAttributeMin?=?0;???????????????????????CIAttributeSliderMax?=?1;??????????CIAttributeSliderMin?=?0;??????????CIAttributeType?=?CIAttributeTypeScalar;??????};??}??程序中使用CISepiaTone的代碼為:CIFilter?*filter?=?[CIFilter?filterWithName:@"CISepiaTone"];???[filter?setValue:inputImage?forKey:@"inputImage"];??[filter?setValue:[NSNumber?numberWithFloat:0.8]?forKey:@"inputIntensity"];??
大家可以 [CIFilterfilterNamesInCategories]返回所有的濾鏡,并查看他們的參數來熟悉各個濾鏡的使用方法。
?
2.3 CIContext
????? CIContext用來渲染CIImage,將作用在CIImage上的濾鏡鏈應用到原始的圖片數據中。CIContext可以是基于CPU的,也可以是基于GPU的,這兩種渲染的區別是:使用CPU渲染的IOS會采用GCD來對圖像進行渲染,這保證了CPU渲染在大部分情況下更可靠,比CPU渲染更容易使用,他可以在后臺實現渲染過程;而GPU渲染方式使用OpenGL ES2.0來渲染圖像,這種方式CPU完全沒有負擔,應用程序的運行循環不會受到圖像渲染的影響,而且他渲染比CPU渲染更快但是GPU渲染無法在后臺運行。
?????
對于如何選擇更好的渲染方式,我認為應該視具體情況而定:對于復雜的圖像濾鏡使用
GPU
更好,但是如果在處理視頻并保存文件,或保存照片到照片庫中時為避免程序退出對圖片保存造成影響,這時應該使用
CPU
進行渲染。默認情況是用
CPU
渲染的。
[cpp] view plaincopy
CIContext?*context?=?[CIContext?contextWithOptions:[NSDictionary?dictionaryWithObject:[NSNumber?numberWithBool:YES]?forKey:kCIContextUseSoftwareRenderer]];??
渲染后的圖片使用:
1.在imageView中使用:
[cpp] view plaincopy
????CIContext?*context?=?[CIContext?context];????????CIImage?*ciimage?=?[filter?outputImage];????????CGImageRef?cgimg?=?[context?createCGImage:ciimage?fromRect:[ciimage?extent]];??????UIImage?*uiimage?=?[UIImage?imageWithCGImage:cgimg?scale:1.0f??orientation:ui_orientation([ciimage?properties])];??CGImageRelease(cgimg);????imageView.image?=?uiimage;??
2.將圖片保存到photoLibrary
[cpp] view plaincopy
???CIImage?*outputImage?=?[filter?outputImage];???CGImageRef?cgimage?=?[cpu_context?createCGImage:outputImage???????????????????????????????fromRect:[outputImage?extent]];??????ALAssetsLibrary?*library?=?[ALAssetsLibrary?new];???[library?writeImageToSavedPhotosAlbum:cgimage????????????????????????????????metadata:[outputImage?properties]????????completionBlock:^(NSURL?*assetURL?NSError?*error)?{??????????CGImageRelease(cgimg);??}];??
2.4 CIDetector和CIFeature
???????? CIDetector用來分析CIImage,得到CIFeature。每個CIDetector都要用一個探測器來初始化,這個類型高數探測器要在圖像中尋找什么特征。
???????? 當一個CIDetector分析一張圖片時,返回一個探測到的CIFeature的數組,如果CIDetector 被初始化為尋找面孔,那么返回的數組會被填上CIFaceFeature對象,每個CIFaceFeature都包含一個面部的CGrect引用(按照圖像的坐標系),以及檢測到的面孔的左眼,右眼,嘴部位置的CGPoint;
[cpp] view plaincopy
CIDetector?*faceDetector?=?[CIDetector???????????????????????????????????????detectorOfType:CIDetectorTypeFace??????????????????????????????????????context:self.imageContext???????????????????????????????????????options:options];????????????????NSArray?*faces?=?[faceDetector?featuresInImage:coreImage?????????????????????????????????????????????????options:nil];??for(CIFaceFeature?*face?in?faces){??????????????coreImage?=?[CIFilter?filterWithName:@"CISourceOverCompositing"?????????????????????????????????????keysAndValues:kCIInputImageKey,?[self?makeBoxForFace:face],???????????????????????????kCIInputBackgroundImageKey,?coreImage,?nil].outputImage;??????????}??
3 注意事項
?
1 CoreImage在IOS上有很高的效率,但是濾鏡和渲染操作也會對主線程造成影響。應該將CoreImage濾鏡渲染操作放在后臺線程執行,當這些操作介紹后在返回主線程進行界面的更新。
[cpp] view plaincopy
dispatch_async(?????????dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,?0),?????????^(void){???????????????????????????????????????NSArray?*filters;??????????????????????????CGImageRef?cgImg?=?self.imageView.image.CGImage;?????????????CIImage?*coreImage?=?[CIImage?imageWithCGImage:cgImg];????????????????????????????????????????????????????for(CIFilter?*filter?in?filters){?????????????????[filter?setValue:coreImage?forKey:kCIInputImageKey];?????????????????coreImage?=?filter.outputImage;?????????????}?????????????????????????????????????????????????????????????????CGImageRef?newImg?=?[self.imageContext?createCGImage:coreImage??????????????????????????????????????????????????????????fromRect:[coreImage?extent]];??????????????????????????dispatch_async(dispatch_get_main_queue(),?^(void){????????????????????????????????????????????????????????????????????self.imageView.image?=?[UIImage?imageWithCGImage:newImg];?????????????????[self.adjustSpinner?stopAnimating];?????????????????[sender?setEnabled:YES];?????????????});?????????});??
上面這段代碼,就是為了防止阻塞主線程,用GCD異步執行濾鏡與渲染操作,在獲取渲染后的照片以后,返回主線程進行界面的更新。(完整的程序見本文末連接)
?
2 不要重復應用濾鏡,即使是同一個濾鏡也不要應用兩次,因為濾鏡后輸出照片包含濾鏡鏈,在進行照片渲染是會將濾鏡鏈效果疊加到原始數據上,這時會造成問題。比如,有一個CIImage,上面配置了強度為0.5的棕色濾鏡,現在通過滑塊將強度改為0.6,這個濾鏡應該用在新的CIImage上,如果不是新的CIImage上,那么原來的CIImage中將包含強度為0.5和0.6的棕色濾鏡,而我們只想0.6的棕色濾鏡,這樣就造成錯誤,這一點在編寫程序的時候一定要切忌。
?
3 app中應用的濾鏡太多,改變速率太快,如果是根據滑塊來產生事件的話,一定要注意在使用滑條值前要首先判斷更改的濾鏡當前是否正在起作用,如果該濾鏡正在生成新的渲染圖片,則應該這次滑塊的更新。這一點也是很重要的,弄的不好常常導致程序崩潰,出現內存泄露問題。
?
這些問題常常會導致程序的崩潰.
?
4 總結
CoreImage處理圖像的流程:
1:創建一個新的CIImage;
2:創建一個行的CIFIlter,并通過鍵-值設置各種輸入值,這些值有些是有默認值的,有些沒有默認值,需要編程者的設置;
3:沖CIFilter中生成輸出圖像,如果存在濾鏡鏈則將輸出圖像作為輸入參數傳入到下一個濾鏡,跳回步驟2繼續進行,如果到達濾鏡末,則調用CIContext渲染CIImage對象。這個context可以是基于CPU或GPU的,基于CPU的產出CGImageRef對象,基于GPU的調用OpenGL ES在屏幕上畫出結果,默認是基于CPU的。
?
在使用CoreImage時,一定要記住CIImage對象在開始時不會操作圖像數據,知道使用CIContext渲染圖片是才會這么做。還要記住最好在后臺執行圖像處理的操作,然后在主線程中修改界面。
大家有機會可以參考一下IOS5核心框架中的CoreImage章節和AVFoundation章節,下面在貼一個書本中的列子的連接,我認為很有助理解。http://ioscoreframeworks.com/download/。
另外也可以參考下wwdc上面的視頻Session510-Getting Started with Core Image和Session 511 -? Core Image Techniques.mov。
總結
以上是生活随笔為你收集整理的iOS框架介绍之coreImage的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。