#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 的轉向問題

套用濾鏡效果後,若遇到圖片轉向問題,可參考以下連結。

作品集

--

--

彼得潘的 iOS App Neverland
彼得潘的 100 道 Swift iOS App 謎題

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com