Core Image框架詳細(xì)解析(四) —— Processing Images處理圖像(一)

版本記錄

版本號 時(shí)間
V1.0 2018.01.27

前言

Core Image是IOS5中新加入的一個(gè)框架,里面提供了強(qiáng)大高效的圖像處理功能,用來對基于像素的圖像進(jìn)行操作與分析。還提供了很多強(qiáng)大的濾鏡,可以實(shí)現(xiàn)你想要的效果,下面我們就一起解析一下這個(gè)框架。感興趣的可以參考上面幾篇。
1. Core Image框架詳細(xì)解析(一) —— 基本概覽
2. Core Image框架詳細(xì)解析(二) —— Core Image濾波器參考
3. Core Image框架詳細(xì)解析(三) —— 關(guān)于Core Image

Overview

處理圖像意味著應(yīng)用濾波器 - 圖像濾波器是一個(gè)逐像素檢查輸入圖像的軟件,在算法上應(yīng)用一些效果來創(chuàng)建輸出圖像。 在Core Image中,圖像處理依賴于CIFilterCIImage類,它們描述了過濾器及其輸入和輸出。 要應(yīng)用過濾器并顯示或?qū)С鼋Y(jié)果,可以使用Core Image和其他系統(tǒng)框架之間的集成,或者使用CIContext類創(chuàng)建您自己的渲染工作流程。 本章介紹了使用這些類來應(yīng)用過濾器和渲染結(jié)果的關(guān)鍵概念。

在應(yīng)用程序中使用Core Image進(jìn)行圖像處理有很多方法。在本章中,Listing 1-1顯示了一個(gè)基本的例子,并提供了進(jìn)一步解釋的指導(dǎo)。

// Listing 1-1  The basics of applying a filter to an image

import CoreImage
 
let context = CIContext()                                           // 1
 
let filter = CIFilter(name: "CISepiaTone")!                         // 2
filter.setValue(0.8, forKey: kCIInputIntensityKey)
let image = CIImage(contentsOfURL: myURL)                           // 3
filter.setValue(image, forKey: kCIInputImageKey)
let result = filter.outputImage!                                    // 4
let cgImage = context.createCGImage(result, from: result.extent)    // 5

這里就是代碼做的事情:

    1. 創(chuàng)建一個(gè)CIContext對象(使用默認(rèn)選項(xiàng))。你并不總是需要你自己的Core Image context - 通常你可以與其他管理渲染的系統(tǒng)框架集成。創(chuàng)建自己的上下文可以更精確地控制渲染過程和渲染過程中涉及的資源。上下文是重量級的對象,所以如果你真的創(chuàng)建了一個(gè),那么盡可能早地做,并且每次需要處理圖片時(shí)都要重新使用它。 (請參閱Building Your Own Workflow with a Core Image Context。)
    1. 實(shí)例化表示要應(yīng)用的過濾器的CIFilter對象,并為其參數(shù)提供值。 (請參閱Filters Describe Image Processing Effects。)
    1. 創(chuàng)建一個(gè)表示要處理的圖像的CIImage對象,并將其作為輸入圖像參數(shù)提供給過濾器。從URL中讀取圖像數(shù)據(jù)只是創(chuàng)建圖像對象的許多方法之一。 (請參閱Images are the Input and Output of Filters。)
    1. 獲取表示過濾器輸出的CIImage對象。此時(shí)過濾器尚未執(zhí)行 - 圖像對象是一個(gè)“recipe”,指定如何使用指定的濾鏡,參數(shù)和輸入創(chuàng)建圖像。Core Image僅在請求渲染時(shí)才執(zhí)行此recipe。 (請參閱Images are the Input and Output of Filters。)
    1. 將輸出圖像渲染為可以顯示或保存到文件的Core Graphics圖像。 (請參閱Building Your Own Workflow with a Core Image Context。)

Images are the Input and Output of Filters - 圖像是過濾器的輸入和輸出

Core Image過濾器處理和生成Core Image圖像。 CIImage實(shí)例是表示圖像的不可變對象。 這些對象不直接表示圖像位圖數(shù)據(jù) - 而是一個(gè)CIImage對象是用于生成圖像的“recipe”。 一個(gè)“recipe”可能會要求從文件加載圖像; 另一個(gè)可能表示來自過濾器的輸出,或來自過濾器鏈的輸出。 Core Image只有在您要求顯示或輸出圖像時(shí)才執(zhí)行這些“recipe”。

要應(yīng)用濾鏡,請創(chuàng)建一個(gè)或多個(gè)代表要由濾鏡處理的圖像的CIImage對象,并將其分配給濾鏡的輸入?yún)?shù)(如kCIInputImageKey)。 您幾乎可以從任何圖像數(shù)據(jù)源創(chuàng)建一個(gè)Core Image圖像對象,其中包括:

  • 引用要加載的圖像文件的URL或包含圖像文件數(shù)據(jù)的NSData對象
  • Quartz2D,UIKit或AppKit圖像表示(CGImageRef,UIImageNSBitmapImageRep對象)
  • Metal,OpenGL或OpenGL ES紋理
  • CoreVideo圖像或像素緩沖區(qū)(CVImageBufferRefCVPixelBufferRef
  • 在進(jìn)程之間共享圖像數(shù)據(jù)的IOSurfaceRef對象
  • 內(nèi)存中的圖像位圖數(shù)據(jù)(指向此類數(shù)據(jù)的指針或按需提供數(shù)據(jù)的CIImageProvider對象)

有關(guān)創(chuàng)建CIImage對象的完整列表,請參閱CIImage Class Reference。

由于CIImage對象描述如何生成圖像(而不是包含圖像數(shù)據(jù)),因此它也可以表示過濾器輸出。在訪問CIFilter對象的outputImage屬性時(shí),Core Image僅會標(biāo)識并存儲執(zhí)行過濾器所需的步驟。這些步驟只有在您要求顯示或輸出圖像時(shí)才會執(zhí)行。您可以使用CIContextrenderdraw方法之一(請參閱Building Your Own Workflow with a Core Image Context)顯式地請求渲染,也可以使用與Core Image一起工作的許多系統(tǒng)框架之一顯示圖像來隱式的請求渲染(請參閱Integrating with Other Frameworks)。

推遲處理,直到渲染時(shí)間使Core Image快速高效。在渲染時(shí),Core Image可以查看是否需要將多個(gè)過濾器應(yīng)用于圖像。如果是這樣,它自動(dòng)連接多個(gè)“recipes”,并組織它們以消除冗余操作,使每個(gè)像素只處理一次,而不是多次。


Filters Describe Image Processing Effects - 過濾器描述圖像處理效果

CIFilter類的一個(gè)實(shí)例是一個(gè)表示圖像處理效果的可變對象以及控制該效果行為的任何參數(shù)。要使用過濾器,您可以創(chuàng)建CIFilter對象,設(shè)置其輸入?yún)?shù),然后訪問其輸出圖像(請參閱 Images are the Input and Output of Filters)。調(diào)用filterWithName:初始化器來使用系統(tǒng)已知的過濾器的名稱實(shí)例化一個(gè)過濾器對象(請參閱Querying the System for FiltersCore Image Filter Reference)。

大多數(shù)過濾器都有一個(gè)或多個(gè)輸入?yún)?shù),可以控制處理過程的方式。每個(gè)輸入?yún)?shù)都有一個(gè)屬性類,用于指定其數(shù)據(jù)類型,如NSNumber。輸入?yún)?shù)可以選擇性地包含其他屬性,例如默認(rèn)值,允許的最小值和最大值,參數(shù)的顯示名稱以及CIFilter Class Reference中描述的其他屬性。例如,CIColorMonochrome濾鏡具有三個(gè)輸入?yún)?shù) - 要處理的圖像,單色和顏色強(qiáng)度。

過濾器參數(shù)被定義為鍵值對,要使用參數(shù),通常使用valueForKey:setValue:forKey:方法或基于鍵值編碼(如Core Animation)的其他功能。key是標(biāo)識屬性的常數(shù),值是與key相關(guān)的設(shè)置。Core Image屬性值通常使用下面Attribute value data types表中列出的數(shù)據(jù)類型之一

重要:CIFilter objects are mutable, so you cannot safely share them between different threads. Each thread must create its own CIFilter objects. However, a filter’s input and output CIImage objects are immutable, and thus safe to pass between threads. CIFilter對象是可變的,所以你不能在不同的線程之間安全地共享它們。 每個(gè)線程都必須創(chuàng)建自己的CIFilter對象。 但是,過濾器的輸入和輸出CIImage對象是不可變的,因此在線程之間傳遞是安全的。

1. Chaining Filters for Complex Effects - 復(fù)雜效果的鏈?zhǔn)綖V波器

每個(gè)Core Image過濾器都會生成一個(gè)輸出CIImage對象,因此您可以將此對象用作另一個(gè)過濾器的輸入。 例如,圖1-1中所示的過濾器序列將顏色效果應(yīng)用于圖像,然后添加發(fā)光效果,最后從結(jié)果中裁剪出一部分。

Figure 1-1 Construct a filter chain by connecting filter inputs and outputs

Core Image優(yōu)化過濾器鏈的應(yīng)用,如這一個(gè),以快速和高效地呈現(xiàn)結(jié)果。 鏈中的每個(gè)CIImage對象都不是完全渲染的圖像,而僅僅是渲染的“recipe”。 Core Image不需要單獨(dú)執(zhí)行每個(gè)濾鏡,浪費(fèi)時(shí)間和內(nèi)存渲染永遠(yuǎn)不會看到的中間像素緩沖區(qū)。 相反,Core Image將過濾器組合成一個(gè)單一的操作,甚至可以重新組織過濾器,當(dāng)以不同的順序應(yīng)用它們時(shí)會更有效地產(chǎn)生相同的結(jié)果。 圖1-2顯示了從圖1-1中示例過濾器鏈的更準(zhǔn)確的解釋。

Figure 1-2 Core Image optimizes a filter chain to a single operation

請注意,在圖1-2中,裁剪操作已從最后一個(gè)移到第一個(gè)。 該過濾器會導(dǎo)致原始圖像的大部分區(qū)域被從最終輸出中剪切掉。 因此,不需要應(yīng)用顏色并將銳化濾鏡添加到這些像素。 通過首先執(zhí)行裁剪,Core Image可以確保昂貴的圖像處理操作僅適用于在最終輸出中可見的像素。

Listing 1-2顯示了如何設(shè)置如上所示的過濾器鏈

// Listing 1-2  Creating a filter chain

func applyFilterChain(to image: CIImage) -> CIImage {
    // The CIPhotoEffectInstant filter takes only an input image
    let colorFilter = CIFilter(name: "CIPhotoEffectProcess", withInputParameters:
        [kCIInputImageKey: image])!
    
    // Pass the result of the color filter into the Bloom filter
    // and set its parameters for a glowy effect.
    let bloomImage = colorFilter.outputImage!.applyingFilter("CIBloom",
                                                             withInputParameters: [
                                                                kCIInputRadiusKey: 10.0,
                                                                kCIInputIntensityKey: 1.0
        ])
    
    // imageByCroppingToRect is a convenience method for
    // creating the CICrop filter and accessing its outputImage.
    let cropRect = CGRect(x: 350, y: 350, width: 150, height: 150)
    let croppedImage = bloomImage.cropping(to: cropRect)
    
    return croppedImage
}

Listing 1-2還顯示了一些用于配置過濾器和訪問結(jié)果的便利方法??傊梢允褂眠@些方法中的任何一種來單獨(dú)或作為過濾器鏈的一部分應(yīng)用過濾器:

  • 使用filterWithName:初始化器創(chuàng)建CIFilter實(shí)例,使用·setValue:forKey:·方法(包括要處理圖像的·kCIInputImageKey·)設(shè)置參數(shù),并使用·outputImage·屬性訪問輸出圖像。 (請參閱Listing 1-1。)

  • 一次調(diào)用filterWithName:withInputParameters: 初始化器創(chuàng)建一個(gè)CIFilter實(shí)例并設(shè)置其參數(shù)(包括輸入圖像),然后使用outputImage屬性訪問輸出。 (請參閱Listing 1-2中的colorFilter示例。)

  • 通過使用imageByApplyingFilter:withInputParameters:方法應(yīng)用于CIImage對象,而不創(chuàng)建CIFilter實(shí)例來應(yīng)用過濾器。 (請參閱Listing 1-2中的bloomImage示例。)

  • 對于某些常用的濾鏡操作(例如cropping, clamping, 和 applying coordinate transforms),請使用Creating an Image by Modifying an Existing Image中列出的其他CIImage實(shí)例方法。 (請參閱Listing 1-2中的croppedImage示例。)

2. Using Special Filter Types for More Options - 使用特殊的過濾器類型獲得更多的選擇

大多數(shù)內(nèi)置的Core Image過濾器在主要輸入圖像上運(yùn)行(也可能有會影響處理的附加輸入圖像)并創(chuàng)建單個(gè)輸出圖像。 但還有其他幾種可用于創(chuàng)建有趣效果的類型,或者與其他過濾器結(jié)合使用以生成更復(fù)雜的工作流程。

  • 合成(或混合)濾鏡根據(jù)預(yù)設(shè)的公式組合兩個(gè)圖像。 例如:
    • CISourceInCompositing過濾器組合圖像,使得只有輸入圖像中不透明的區(qū)域在輸出圖像中才可見。
    • CIMultiplyBlendMode濾鏡將兩個(gè)圖像的像素顏色相乘,產(chǎn)生一個(gè)黑暗的輸出圖像。

有關(guān)合成過濾器的完整列表,請查詢CICategoryCompositeOperation類別。

Note: You can arrange input images before compositing them by applying geometry adjustments to each. See the CICategoryGeometryAdjustment filter category or the imageByApplyingTransform: method. 注意:您可以在合成之前安排輸入圖像,方法是對每個(gè)圖像應(yīng)用幾何調(diào)整。 請參閱CICategoryGeometryAdjustment篩選器類別或imageByApplyingTransform:方法。

  • generator濾波器不輸入任何輸入圖像。相反,這些過濾器使用其他輸入?yún)?shù)從頭創(chuàng)建一個(gè)新的圖像。一些generator產(chǎn)生的輸出可以獨(dú)立使用,另一些發(fā)生器可以組合在濾波器鏈中產(chǎn)生更有趣的圖像。內(nèi)置Core Image過濾器中的一些示例包括:

要查找生成器過濾器,請查詢CICategoryGeneratorCICategoryGradient類別。

  • reduction過濾器對輸入圖像進(jìn)行操作,但是不是以傳統(tǒng)意義來創(chuàng)建輸出圖像,而是其輸出描述關(guān)于輸入圖像的信息。 例如:
    • CIAreaMaximum濾鏡輸出表示圖像指定區(qū)域中所有像素顏色中最亮的單個(gè)顏色值。
    • CIAreaHistogram過濾器輸出關(guān)于圖像的指定區(qū)域中的每個(gè)強(qiáng)度值的像素?cái)?shù)目的信息。

所有Core Image過濾器都必須生成一個(gè)CIImage對象作為輸出,所以由reduction生成的信息仍然是一個(gè)圖像。 但是,通常不顯示這些圖像,而是從單像素或單行圖像中讀取顏色值,或?qū)⑵溆米髌渌麨V鏡的輸入。

有關(guān)reduction過濾器的完整列表,請查詢CICategoryReduction類別。

  • 一個(gè)transition過濾器需要兩個(gè)輸入圖像,并根據(jù)一個(gè)獨(dú)立的變量來改變它們之間的輸出 - 通常這個(gè)變量是時(shí)間,所以你可以使用transition過濾器來創(chuàng)建一個(gè)動(dòng)畫,從一個(gè)圖像開始,在另一個(gè)圖像上結(jié)束, 從一個(gè)到另一個(gè)使用有趣的視覺效果。 Core Image提供了幾個(gè)內(nèi)置的transition過濾器,包括:
    • CIDissolveTransition過濾器產(chǎn)生一個(gè)簡單的交叉消解,從一個(gè)圖像漸變到另一個(gè)。
    • CICopyMachineTransition過濾器模擬復(fù)印機(jī),在一幅圖像上劃過一道明亮的光線,以顯示另一幅圖像。

有關(guān)transition過濾器的完整列表,請查詢CICategoryTransition類別。

后記

本篇已結(jié)束,后面更精彩~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容