本文僅代表個(gè)人學(xué)習(xí)研究成果扮宠,如有不對(duì)的地方蚯妇,請(qǐng)?jiān)谠u(píng)論下方探討对人!
- 將Filter類(lèi)型定義為一個(gè)函數(shù),該函數(shù)接受一個(gè)圖像作為參數(shù)并返回一個(gè)新的圖像
typealias Filter = (CIImage) -> CIImage
構(gòu)建濾鏡
現(xiàn)在我們已經(jīng)定義了 Filter 類(lèi)型凛俱,接著就可以開(kāi)始定義函數(shù)來(lái)構(gòu)建特定的的濾鏡了紊馏。這些函數(shù) 在接受特定濾鏡所需要的參數(shù)之后,構(gòu)造并返回一個(gè) Filter 類(lèi)型的值蒲犬。它們的基本形態(tài)大概都 是下面這樣:
func myFilter (...) -> Filter
注意這里的返回值 Filter瘦棋,也是一個(gè)函數(shù)。稍后我們將會(huì)借助它來(lái)組合多個(gè)濾鏡以實(shí)現(xiàn)期待的 圖像效果暖哨。
模糊
定義第一個(gè)簡(jiǎn)單的濾鏡 —— 高斯模糊濾鏡赌朋。定義它只需要模糊半徑這一個(gè)參數(shù):
func blur(radius: Double) -> Filter {
return { image in
let parameters: [String: Any] = [
kCIInputRadiusKey: radius,
kCIInputImageKey: image
]
guard let filter = CIFilter (name: "CIGaussianBlur",
withInputParameters: parameters)
else { fatalError () }
guard let outputImage = filter.outputImage
else { fatalError () } return outputImage
}
}
blur 函數(shù)返回一個(gè)新函數(shù),新函數(shù)接受一個(gè) CIImage 類(lèi)型的參數(shù) image篇裁, 并返回一個(gè)新圖像 (return lter .outputImage)沛慢。因此,blur 函數(shù)的返回值滿足我們之前定義 的 (CIImage) -> CIImage达布,也就是 Filter 類(lèi)型团甲。
顏色疊層
現(xiàn)在讓我們來(lái)定義一個(gè)能夠在圖像上覆蓋純色疊層的濾鏡。Core Image 默認(rèn)不包含這樣一個(gè)濾 鏡黍聂,但是我們完全可以用已經(jīng)存在的濾鏡來(lái)組成它躺苦。
我們將使用的兩個(gè)基礎(chǔ)組件:顏色生成濾鏡 (CIConstantColorGenerator) 和圖像覆蓋合成濾鏡 (CISourceOverCompositing)。首先讓我們來(lái)定義一個(gè)生成固定顏色的濾鏡:
funcgenerate(color:UIColor)-> Filter {
return { _ in
let parameters = [kCIInputColorKey: CIColor(cgColor: color.cgColor)]
guard let filter = CIFilter (name: "CIConstantColorGenerator",
withInputParameters: parameters)
else { fatalError () }
guard let outputImage = filter.outputImage
else { fatalError () } return outputImage
}
}
這段代碼看起來(lái)和我們用來(lái)定義模糊濾鏡的代碼非常相似产还,但是有一個(gè)顯著的區(qū)別:顏色生成 濾鏡不檢查輸入圖像匹厘。因此,我們不需要給返回函數(shù)中的圖像參數(shù)命名脐区。取而代之愈诚,我們使用 一個(gè)匿名參數(shù) _ 來(lái)強(qiáng)調(diào)濾鏡的輸入圖像參數(shù)是被忽略的。
接下來(lái),我們將要定義合成濾鏡:
func compositeSourceOver(overlay: CIImage) -> Filter {
return { image in
let parameters = [ kCIInputBackgroundImageKey: image,
kCIInputImageKey: overlay
]
guard let filter = CIFilter (name: "CISourceOverCompositing",
withInputParameters: parameters)
else { fatalError () }
guard let outputImage = filter.outputImage
else { fatalError () }
return outputImage.cropped(to: image.extent)
}
在這里我們將輸出圖像剪裁為與輸入圖像一致的尺寸炕柔。嚴(yán)格來(lái)說(shuō)酌泰,這不是必須的,完全取決于
我們希望濾鏡如何工作匕累。不過(guò)陵刹,這個(gè)選擇在我們即將涉及的例子中效果很好。
最后欢嘿,我們通過(guò)結(jié)合兩個(gè)濾鏡來(lái)創(chuàng)建顏色疊層濾鏡:
func overlay(color: UIColor) -> Filter {
return { image in
let overlay = generate(color: color)(image).cropped(to: image.extent)
return compositeSourceOver(overlay: overlay)(image)
}
}
我們?cè)俅畏祷亓艘粋€(gè)接受圖像作為參數(shù)的函數(shù)衰琐。我們?cè)诙x該函數(shù)的整個(gè)過(guò)程中所做的一切可 大致概括為:首先使用先前定義的顏色生成濾鏡函數(shù) generate(color:) 來(lái)生成一個(gè)新疊層。然 后以顏色作為參數(shù)調(diào)用該函數(shù)际插,返回 Filter 類(lèi)型值。而 Filter 類(lèi)型本身就是一個(gè)從 CIImage 到 CIImage 的函數(shù)显设,因此我們還可以向 generate(color:) 函數(shù)傳遞一個(gè) image 參數(shù)框弛,最終通過(guò)計(jì) 算能夠得到一個(gè) CIImage 類(lèi)型的新疊層。
與疊層的創(chuàng)建相似捕捂,所構(gòu)建的濾鏡函數(shù)的返回值也有著相同的結(jié)構(gòu):先通過(guò)調(diào)用 compositeSourceOver(overlay:) 來(lái)創(chuàng)建一個(gè)濾鏡瑟枫。然后以輸入圖像為參數(shù)調(diào)用這個(gè)濾鏡。
復(fù)合函數(shù)組合濾鏡
ffunc compose( filter filter1: @escaping Filter, with filter2 : @escaping Filter) -> Filter
{ `` return { image in filter2 ( filter1 (image)) }
}
使用
demo
以上知識(shí)源于王巍大神的分享指攒,后期會(huì)持續(xù)更新慷妙,致敬王巍大神!