CIFilter_看了這個,你就可以打造自己的美圖秀秀

上篇文章iOS_最全的二維碼篇說要給大家簡紹一下強大而好玩工具CIFilter,所以這今天晚上給大家分享一個demo夯尽。我保證你看了這篇文章之后瞧壮,肯定能做出自己的美圖工具,我發(fā)誓(雖然并沒卵用)匙握。

CIFilter,其實就是一個濾鏡咆槽。喜歡攝影的小伙伴,可能接觸過PS圈纺,而接觸過PS的小伙伴秦忿,對濾鏡肯定不陌生。而且有了解相關知識的小伙伴蛾娶,對于顏色和圖片處理的認知也一定信手捏來灯谣。什么RGB,什么CMYK蛔琅,什么灰度圖片胎许,什么高斯模糊,什么銳化罗售,什么對比度辜窑,什么飽和度,什么顏色通道寨躁,為什么值在255之間等等穆碎。我為什么知道這些,其實小Jorn我大一的時候朽缎,剛上大學惨远,課不是很多谜悟,時間充足话肖,那時候,都還不知道LOL(呵呵葡幸,現(xiàn)在最筒,此處省略1W字),還帶著高中的稚氣和志氣蔚叨。想想要學點啥一技之長床蜘。記得高中時候,有次去拍一寸照蔑水,看那sb老板邢锯,不懂PS,硬是給我照片亂修搀别。結(jié)果照片老丑丹擎,還硬坑我20塊錢。所以大學就想到自己學學PS,在處理照片的時候可以自己修蒂培。而且再愈,PS還可以做很多平面設計。說不定以后可以去做設計的工作护戳。一個好的設計師翎冲,薪資還是很高的(_)。所以自己學了一年多的PS(堪稱大神了媳荒,然并卵)抗悍,后來學的差不多了。海報設計钳枕,網(wǎng)頁設計檐春,UI設計,還有其他各種設計么伯,圖文排版疟暖,圖片處理,婚紗處理田柔,P圖等什么滴都自己做過(厲害吧)俐巴。大二的時候又學了一年的AI,后來還想學AE來著(因為大學嘛硬爆,越到后來欣舵,你懂得。游戲也開始玩起來了)缀磕。學了PS和AI缘圈,其實我還是覺得很不錯的,不只在一個地方看到袜蚕,PS和AI就像左右手糟把,這也是做平面設計的工作者必備的兩技能。一個負責位圖牲剃,一個負責矢量圖遣疯,功能都超強大。現(xiàn)在iOS上用的icon基本都是用這兩工具設計的凿傅。雖然現(xiàn)在不慎混到了程序猿的大流缠犀。不過想想懂這也不是無可用武之地,至少在圖片處理聪舒,顏色的認知上還有挺有幫助的(呵呵辨液,安慰一下自己)。(扯遠了箱残。滔迈。。)

言歸正傳,你學會使用CIFilter亡鼠,你就可以隨意處理你想要的效果赏殃。系統(tǒng)給我們提供的濾鏡種類是非常的多,不是十幾個间涵,是幾十個仁热。沒錯!

CoreImage是個非常強大框架勾哩,集圖片的幾乎所有操作編輯于一身抗蠢,CIFilter只是其中的一個工具,主要作用是給圖片渲染不同的效果
CIFilter的種類很多思劳,所以蘋果的官方文檔也只能給出部分常用的種類的說明迅矛。
官方文檔給出的部分說明:點擊這里
雖然官方文檔很簡潔,但國外的大神們已經(jīng)證明這是個相當強悍的框架潜叛,
不僅功能強大秽褒,而且可以直接使用GPU,效率奇高威兜,甚至可以實時的對視頻進行渲染销斟。

下面讓我們來看看,如何具體使用它:
首先你需要導入CoreImage.framework框架椒舵;進行Mac(不是iOS)開發(fā)的同學請導入QuartzCore.framework框架蚂踊,包含在其中了。
然后我們先來看看3個主要的類:
CIContext:它與CoreGraphicsOpenGL context類似笔宿,所有CoreImage的處理流程都通過它來進行犁钟;
CIImage:它用來存放圖片數(shù)據(jù),可以通過UIImage泼橘,圖片文件或像素數(shù)據(jù)創(chuàng)建涝动;
CIFilter:通過它來定義過濾器的詳細屬性。
CIContext有兩種初始化方法侥加,分別對應GPUCPU

創(chuàng)建基于GPU的CIContext對象
context = [CIContext contextWithOptions: nil];
創(chuàng)建基于CPU的CIContext對象

context = [CIContext contextWithOptions: [NSDictionarydictionaryWithObject:[NSNumber numberWithBool:YES]
    forKey:kCIContextUseSoftwareRenderer]];

一般采用第一種基于GPU的捧存,因為效率要比CPU高很多,但是要注意的是基于GPU的CIContext對象無法跨應用訪問担败。 比如你打開UIImagePickerController要選張照片進行美化,如果你直接在UIImagePickerControllerDelegate的委托方法里調(diào)用CIContext對象進行處理镰官,那么系統(tǒng)會自動將其降為基于CPU的提前,速度會變慢,所以正確的方法應該是在委托方法里先把照片保存下來泳唠,回到主類里再來處理狈网。

CIFilter的強大之處在于,可以疊加來得到多種效果⊥夭福看過iOS_最全的二維碼篇這篇文章的小伙伴肯定知道了什么叫疊加勇垛,其實如果你按那篇文章我說的練習一下,你就會發(fā)現(xiàn)士鸥,得到的圖片也還是不過清晰闲孤。因為,二維碼生成的原圖太小烤礁,放大就很模糊讼积。其實我在用PS處理手機拍的圖片時,一開始少不了這三步脚仔,補點光勤众,太暗;增加的對比度鲤脏,不夠鮮明们颜;銳化一下,細節(jié)不過清晰猎醇。對掌桩,就是銳化一下。等下會讓你獲得一副清晰的二維碼圖姑食。

首先讓你知道波岛,怎么查看到底有哪些濾鏡:

        /* Categories */
//        public let kCICategoryDistortionEffect: String ///失真效果
//        public let kCICategoryGeometryAdjustment: String ///幾何調(diào)整
//        public let kCICategoryCompositeOperation: String ///復合操作
//        public let kCICategoryHalftoneEffect: String ///半色調(diào)效果
//        public let kCICategoryColorAdjustment: String ///顏色調(diào)整
//        public let kCICategoryColorEffect: String ///顏色效果
//        public let kCICategoryTransition: String ///翻轉(zhuǎn)
//        public let kCICategoryTileEffect: String ///瓦片效果
//        public let kCICategoryGenerator: String ///生成器
//        @available(iOS 5.0, *)
//        public let kCICategoryReduction: String ///削減
//        public let kCICategoryGradient: String ///梯度
//        public let kCICategoryStylize: String ///風格
//        public let kCICategorySharpen: String ///銳化
//        public let kCICategoryBlur: String ///模糊
//        public let kCICategoryVideo: String ///視頻
//        public let kCICategoryStillImage: String ///靜態(tài)圖片
//        public let kCICategoryInterlaced: String ///交叉
//        public let kCICategoryNonSquarePixels: String ///非方形像素
//        public let kCICategoryHighDynamicRange: String ///高動態(tài)范圍
//        public let kCICategoryBuiltIn: String ///內(nèi)建
//        @available(iOS 9.0, *)
//        public let kCICategoryFilterGenerator: String ///濾鏡生成器

這是系統(tǒng)含有的所有大類。
想知道有哪些filter類型或想查找想要的filter類型音半,可以通過先查找大的分類(如上)则拷,然后在查找子項。

        let names = CIFilter.filterNames(inCategory: kCICategoryGenerator) ///kCICategoryGenerator大類
        print(names)

這樣就會輸出該大類包含的所有濾鏡曹鸠。如上會輸出所有的生成器類型CIFilter種類:

 ///生成器大類所包含的所有生成器子類煌茬,如:"`CICode128BarcodeGenerator`"(條形碼生成器),"CIQRCodeGenerator"(二維碼生成器)
//        ["CIAztecCodeGenerator",
//         "CICheckerboardGenerator",
//         "CICode128BarcodeGenerator", ///條形碼生成器
//         "CIConstantColorGenerator",
//         "CILenticularHaloGenerator",
//         "CIPDF417BarcodeGenerator",
//         "CIQRCodeGenerator", ///二維碼生成器
//         "CIRandomGenerator",
//         "CIStarShineGenerator",
//         "CIStripesGenerator",
//         "CISunbeamsGenerator"]

然后就可以創(chuàng)建濾鏡對象了,有兩方法彻桃,含參數(shù)的僅iOS8之后可用坛善,iOS上不設輸入?yún)?shù),系統(tǒng)會使用默認值邻眷,但是mac是會報錯眠屎,輸入?yún)?shù)不明確:

/** Creates a new filter of type 'name'.
         On OSX, all input values will be undefined.
         On iOS, all input values will be set to default values. */
        /// 要是是mac開發(fā),創(chuàng)建filter對象必須提供輸入?yún)?shù)肆饶,iOS可以忽略改衩,系統(tǒng)會使用默認值。
        //init?(name: String)
        //@available(iOS 8.0, *) ///iOS 8.0 之后
        //init?(name: String, withInputParameters params: [String : Any]?)

看看該濾鏡需要設置那些輸入?yún)?shù)驯镊,如此:

        let filter = CIFilter(name: "CIQRCodeGenerator")
        let inpoutkeys = filter?.inputKeys ///查看這個filter的所有輸入?yún)?shù)
        let outputKeys = filter?.outputKeys ///查看這個filter的所有輸出參數(shù)
        
        print("inpoutkeys:",inpoutkeys)
        print("outputKeys:",outputKeys)

設置參數(shù)用KVC來設置葫督,常用的key竭鞍,系統(tǒng)已經(jīng)作為常量給出,可以cmd加鼠標左鍵點擊CIFilter類名進去查看橄镜。
如上偎快,二維碼生成器濾鏡需要量輸入?yún)?shù):

///eg.1 ///示例代碼KVO
        /// 1. 實例化二維碼濾鏡
        let filter = CIFilter(name: "CIQRCodeGenerator")///二維碼
        
        /// 2. 恢復濾鏡的默認屬性 ///值得注意
        filter?.setDefaults()
        
        /// 3. 將字符串轉(zhuǎn)換成二進制數(shù)據(jù),(生成二維碼所需的數(shù)據(jù))
        let string = "hello word"
        let data = string.data(using: String.Encoding.utf8)///Swift 3.0
        
        /// 4. 通過KVO把二進制數(shù)據(jù)添加到濾鏡inputMessage中
        filter?.setValue(data, forKey: "inputMessage")
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        
        /// 5. 獲得濾鏡輸出的圖像
        let outputImage = filter?.outputImage ///CIImage
        
        /// 6. 將CIImage轉(zhuǎn)換成UIImage洽胶,并放大顯示
        //let originQRCodeImage = UIImage(ciImage: outputImage!, scale: 0.07, orientation: UIImageOrientation.up) ///原生二維碼圖片 ///這樣將圖片放大會變得模糊

這樣得到的originQRCodeImage是模糊的晒夹,把scale設為一時得到實際大小,但太小妖异。在上篇文章我提過惋戏,需要進行重繪(效果80分)。這里我們可以使用縮放濾鏡來縮放他膳。生產(chǎn)高質(zhì)量的响逢、按比例縮放的源圖像的版本(這是文檔說明,然我并沒發(fā)現(xiàn)有啥牛掰棕孙,還是模糊)舔亭。
CIFilter為"CILanczosScaleTransform"(蘭索斯縮放變化濾鏡),但為了達到彩色的效果我們先把顏色濾鏡加上蟀俊,CIFliter為"CIFalseColor"(偽色濾鏡):

let colorFilter = CIFilter(name: "CIFalseColor")///顏色濾鏡
        colorFilter!.setDefaults()
        colorFilter!.setValue(outputImage
            , forKey:kCIInputImageKey)
        
        colorFilter!.setValue(CIColor(red: 33.0 / 225.0, green: 192.0 / 225.0, blue: 174.0 / 225.0, alpha: 1.0), forKey:"inputColor0")///二維碼元素(像素)
        colorFilter!.setValue(CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1), forKey:"inputColor1")///背景
        
        let colorImgae = colorFilter!.outputImage
 let scaleFilter = CIFilter(name: "CILanczosScaleTransform") ///蘭索斯縮放變化濾鏡
        scaleFilter?.setDefaults()
        scaleFilter?.setValue(colorImgae, forKey: kCIInputImageKey)
        scaleFilter?.setValue(1.0, forKey: kCIInputScaleKey)
        scaleFilter?.setValue(1.0, forKey: kCIInputAspectRatioKey)
        let scaleImage = scaleFilter?.outputImage

所以通過添加銳化濾鏡來銳化一下钦铺,CIFilter為"CISharpenLuminance"(亮度銳化,對光度有作用肢预,度色度沒影響):

 let sharpenFilter = CIFilter(name: "CISharpenLuminance") ///細節(jié)銳化濾鏡
        ///It operates on the luminance of the image; the chrominance of the pixels remains unaffected.
        sharpenFilter?.setDefaults()
        sharpenFilter?.setValue(scaleImage, forKey: kCIInputImageKey)
        sharpenFilter?.setValue(10.0, forKey: kCIInputSharpnessKey)
        let sharpenImage = sharpenFilter?.outputImage

最后得到圖片:

let newQRCodeImage = UIImage(ciImage: sharpenImage!)
        let imgBtn = UIButton(type: .custom)
        imgBtn.frame = self.view.frame
        imgBtn.setImage(newQRCodeImage, for: .normal)
        self.view.addSubview(imgBtn)

通過參數(shù)的設置矛洞,得到的圖片效果70分;

而在進行重繪后烫映,再進行銳化處理的話沼本,你就會發(fā)現(xiàn)效果是真的不錯(95分)。

因為升為了Switft3.0代碼锭沟,所以代碼需要少量修改抽兆。主要就是Swift3.0把CoreGraphics的全局方法改為了實例方法,


func createUIimageWithCGImage(ciImage image: CIImage, widthAndHeightValue wh: CGFloat) -> CIImage {
        let ciRect = image.extent.integral///根據(jù)容器得到適合的尺寸
        let scale = min(wh / ciRect.width, wh / ciRect.height)
        
        ///獲取bitmap
        let width  = size_t(ciRect.width * scale)

        let height  = size_t(ciRect.height * scale)
        let cs = CGColorSpaceCreateDeviceGray()///灰度顏色通道 ///CGColorSpaceRef
        
        let info_UInt32 = CGImageAlphaInfo.none.rawValue
        let bitmapRef = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 0, space: cs, bitmapInfo: info_UInt32)
        
        let contex = CIContext(options: nil) ///  創(chuàng)建基于GPU的CIContext對象,性能和效果更好
        let bitmapImageRef = contex.createCGImage(image, from: CGRect(x: ciRect.origin.x, y: ciRect.origin.y, width: ciRect.size.width, height: ciRect.size.height)) ///CGImageRef
        
        ///swift 3.0, 把全局方法改為了實例方法
        bitmapRef!.interpolationQuality = CGInterpolationQuality.high///寫入質(zhì)量高族淮,時間長
        bitmapRef!.scaleBy(x: scale, y: scale) ///調(diào)整“畫布”的縮放
        bitmapRef?.draw(bitmapImageRef!, in: ciRect, byTiling: true)///繪制圖片
        
        ///保存
        let scaledImage = bitmapRef!.makeImage() ///cgimage
        
        ///bitmapRef和bitmapImageRef不用主動釋放辫红,Core Foundation自動管理
        //let originImage = UIImage(CGImage: scaledImage!) ///原生灰度圖片(灰色)
        
        let ciImage = CIImage(cgImage: scaledImage!) ///ciimage
        //let newQRCodeImage = UIImage(cgImage: scaledImage!) ///uiimage
        
        return ciImage
    }

附錄:

///附:你要是細心,或者有點好奇心祝辣,你可能會問贴妻,為什么我們看到的二維碼中間都有一個小圖片,
///確實現(xiàn)在的大多二維碼生成工具都喜歡中間貼上一個小圖较幌,但是上述生成的二維碼并沒有揍瑟,
///其實這很簡單,這也是我沒有在這個小問題給出示例的原因乍炉。其實二維碼在缺少小部分的情況下绢片,并不影響存儲信息的完整性
///所以小圖片是另外加上去的,只是遮掉了一小塊二維碼內(nèi)容岛琼,這并不影響什么底循。
///然而在一張圖上添加另一張圖,相信你也覺得這并不是什么問題槐瑞。自己試試吧熙涤。
///如:用quartz2D 、drawImga的方法即可困檩。

下圖:1.銳化祠挫;2.重繪;3.重繪+銳化


1.銳化悼沿;2.重繪等舔;3.重繪+銳化.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市糟趾,隨后出現(xiàn)的幾起案子慌植,更是在濱河造成了極大的恐慌,老刑警劉巖义郑,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝶柿,死亡現(xiàn)場離奇詭異,居然都是意外死亡非驮,警方通過查閱死者的電腦和手機交汤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來劫笙,“玉大人芙扎,你說我怎么就攤上這事⊙冢” “怎么了纵顾?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栋盹。 經(jīng)常有香客問我施逾,道長,這世上最難降的妖魔是什么例获? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任汉额,我火速辦了婚禮,結(jié)果婚禮上榨汤,老公的妹妹穿的比我還像新娘蠕搜。我一直安慰自己,他們只是感情好收壕,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布妓灌。 她就那樣靜靜地躺著轨蛤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虫埂。 梳的紋絲不亂的頭發(fā)上祥山,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音掉伏,去河邊找鬼缝呕。 笑死,一個胖子當著我的面吹牛斧散,可吹牛的內(nèi)容都是我干的供常。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼鸡捐,長吁一口氣:“原來是場噩夢啊……” “哼栈暇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起闯参,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤瞻鹏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鹿寨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體新博,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年脚草,在試婚紗的時候發(fā)現(xiàn)自己被綠了赫悄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡馏慨,死狀恐怖埂淮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情写隶,我是刑警寧澤倔撞,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站慕趴,受9級特大地震影響痪蝇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冕房,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一躏啰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耙册,春花似錦给僵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔓同。三九已至,卻和暖如春胡本,著一層夾襖步出監(jiān)牢的瞬間牌柄,已是汗流浹背畸悬。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工侧甫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹋宦。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓披粟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冷冗。 傳聞我的和親對象是個殘疾皇子守屉,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

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