#74 利用 CIFilter 實現美麗的圖片濾鏡
iOS 上照片類的 App 十分受歡迎,尤其是 App 裡幫我們做出漂亮照片的濾鏡功能。其實基本的濾鏡功能不難做到,因為 iOS SDK 早已為我們提供實現濾鏡功能的 CIFilter。
接下來就讓我們試試在小王子的可愛杯墊照片加上流行的單色(Monochrome)濾鏡效果吧。
ps: 模擬器的濾鏡效能較差,而且可能無法顯示濾鏡效果,因此建議在實機測試。
程式範例
1 Storyboard 畫面設計。
加入 image view & 控制濾鏡效果強度的 slider。
2 連結 image view 的 outlet & slider 的 action。
@IBOutlet weak var imageView: UIImageView!
@IBAction func filterSliderChange(_ sender: UISlider) {
}
3 為了使用內建的濾鏡,我們必須 import 以下套件。
import CoreImage.CIFilterBuiltins
4 在 function filterSliderChange 加入濾鏡功能的程式碼。
@IBAction func filterSliderChange(_ sender: UISlider) {
let image = UIImage(named: "little prince")
let ciImage = CIImage(image: image!)
let filter = CIFilter.colorMonochrome()
filter.inputImage = ciImage
filter.intensity = sender.value
if let outputCIImage = filter.outputImage {
let filterImage = UIImage(ciImage: outputCIImage)
imageView.image = filterImage
}
}
還不會 if let (optional binding) 的同學可參考以下連結的說明。
說明
我們的目標是產生加了濾鏡效果的 UIImage,然後顯示在 UIImageView 上,不過 CIFilter 產生濾鏡圖片時卻是搭配 CIImage,因此我們必須經過以下兩個階段:
- 將 UIImage 變成 CIImage,然後利用 CIFilter 搭配 CIImage 產生添加濾鏡效果的圖片。
- CIFilter 產生的添加濾鏡效果圖片是 CIImage,因此我們要再將 CIImage 變成 UIImage 才能顯示在 UIImageView 上。
產生 CIImage 物件。
let image = UIImage(named: "little prince")
let ciImage = CIImage(image: image!)
CIFilter 只能作用在 CIImage 物件,而不是我們一般常見的 UIImage,因此我們要先產生小王子圖片的 CIImage 物件。
產生製造濾鏡效果的 CIFilter 物件。
let filter = CIFilter.colorMonochrome()
如下圖所示,CIFilter 定義了產生各種濾鏡效果的 function,因此我們直接呼叫 colorMonochrome() 產生單色濾鏡效果的 CIFilter。
設定 CIFilter 物件。
filter.inputImage = ciImage
filter.intensity = sender.value
每種 CIFilter 有不同的 property 可設定,比方從下圖的自動完成選單,我們看到它可以設定圖片(inputImage),強度(intensity) & 顏色(color)。
我們也可以從程式裡一層層查詢 colorMonochrome,最後從 CIColorMonochrome 發現它有三種可設定的欄位,inputImage,color & intensity。
產生加了濾鏡效果的圖片。
if let outputCIImage = filter.outputImage {
let filterImage = UIImage(ciImage: outputCIImage)
imageView.image = filterImage
}
從 filter.outputImage 取得加了濾鏡效果的圖片,不過它的型別是 CIImage?,我們必須將它變成 UIImage,才能設定到顯示圖片的 image view。
執行 App
特別要注意的閃退問題
當我們使用 CIFilter 將濾鏡效果作用在圖片時,必須透過它的 property inputImage 告訴它原始的圖片是什麼,不過這部分 Apple 還有些 bug,所以有些濾鏡效果在設定 inputImage 時會讓 App 閃退,比方以下的 comicEffect。
let filter = CIFilter.comicEffect()
filter.inputImage = ciImage
閃退的錯誤訊息
2019-12-30 16:14:09.898356+0800 CIFilterDemo[7887:8234207] -[CIComicEffect setInputImage:]: unrecognized selector sent to instance 0x6000036daf40
此問題其實有解決的方法,只是要用比較麻煩的寫法,要利用 function setValue(_:forKey:) 設定,然後在參數 forKey 傳入 kCIInputImageKey 表示我們要設定濾鏡作用的圖片。
filter.setValue(ciImage, forKey: kCIInputImageKey)
iOS SDK 已為我們定義好濾鏡可設定的相關 key,比方 kCIInputImageKey & kCIInputIntensityKey,因此我們可方便地用自動完成輸入,減少直接輸入字串打錯字的機率。
完整範例
參考連結
作業
基本功能
1 利用 CIFilter 將濾鏡套用到圖片上。
2 利用 slider 調整濾鏡的效果,比方濾鏡的強度。
3 選擇不同的濾鏡。
利用 segmented control 或點選 scroll view 裡代表不同濾鏡效果的圖片。
進階功能
1 可將濾鏡效果套用到拍照或手機相簿選擇的照片。
2 結合多個 CIFilter。
CIImage 變 UIImage 的轉向問題
套用濾鏡效果後,若遇到圖片轉向問題,可參考以下連結。