iOS8 Core Image In Swift:更復雜的濾鏡

   

       iOS8 Core Image In Swift:更復雜的濾鏡            

       分類:            iOS開發            Swift開發            2014-09-12 00:52    3549人閱讀    評論(8)    收藏    舉報    html

SwiftiOS8Core Image濾鏡CIFiltergit

目錄(?)[+]github

iOS8 Core Image In Swift:自動改善圖像以及內置濾鏡的使用xcode

iOS8 Core Image In Swift:更復雜的濾鏡
app

iOS8 Core Image In Swift:人臉檢測以及馬賽克dom

iOS8 Core Image In Swift:視頻實時濾鏡
ide


上 面那篇文章主要是Core Image的基礎,只是爲了說明CIImage、CIFilter、CIContext,以及基礎濾鏡的簡單使用。在上一篇中幾乎沒有對濾鏡進行更復雜的 操做,都是直接把inputImage扔給CIFilter而已,而Core Image實際上還能對濾鏡進行更加細粒度的控制,咱們在新的工程中對其進行探索。爲此,我從新創建了一個空的workspace,並把以前所使用的工程 添加到這個workspace中,編譯、運行,沒問題的話咱們就開始建立新的工程。post

經過workspace左下角的Add Files to添加已有的工程文件(xx.xcodeproj):測試



當添加工程到workspace的時候,記得要把被添加的工程關掉,否則workspacce不能識別。
另外,在流程上這篇也會與上一篇不一樣,上一篇一開始我就給出了代碼,而後先看效果再步步爲營,這篇不會在一開始給出代碼。



動態改變濾鏡參數的值

用Single View Application的工程模板創建一個新的工程,在View上放一個UIImageView,仍是一樣的frame,一樣的ContentMode設置爲Aspect Fit,一樣的關閉Auto Layout以及Size Classes,最後把上個工程中使用的圖片複製過來,在這個工程中一樣使用這張圖。
網站

作完上面這些基礎工做後,咱們回到VC中,把showFiltersInConsole方法從上個工程中複製過來,而後在viewDidLoad裏調用,在運行以前咱們先看看Core Image有哪些類別,畢竟所有的濾鏡有127種,不可能一一用到的。

類別有不少,並且咱們從上一篇中知道了濾鏡能夠同時屬於不一樣的類別,除此以外,類別還分爲兩大類:

按效果分類:

  • kCICategoryDistortionEffect 扭曲效果,好比bump、旋轉、hole

  • kCICategoryGeometryAdjustment 幾何開着調整,好比仿射變換、平切、透視轉換

  • kCICategoryCompositeOperation 合併,好比源覆蓋(source over)、最小化、源在頂(source atop)、色彩混合模式

  • kCICategoryHalftoneEffect Halftone效果,好比screen、line screen、hatched

  • kCICategoryColorAdjustment 色彩調整,好比伽馬調整、白點調整、曝光

  • kCICategoryColorEffect 色彩效果,好比色調調整、posterize

  • kCICategoryTransition 圖像間轉換,好比dissolve、disintegrate with mask、swipe

  • kCICategoryTileEffect 瓦片效果,好比parallelogram、triangle

  • kCICategoryGenerator 圖像生成器,好比stripes、constant color、checkerboard

  • kCICategoryGradient 漸變,好比軸向漸變、仿射漸變、高斯漸變

  • kCICategoryStylize 風格化,好比像素化、水晶化

  • kCICategorySharpen 銳化、發光

  • kCICategoryBlur 模糊,好比高斯模糊、焦點模糊、運動模糊

按使用場景分類:

  • kCICategoryStillImage 能用於靜態圖像

  • kCICategoryVideo 能用於視頻

  • kCICategoryInterlaced 能用於交錯圖像

  • kCICategoryNonSquarePixels 能用於非矩形像素

  • kCICategoryHighDynamicRange 能用於HDR

這些專業詞太難翻譯了,有不許確的地方還望告知


此外還有咱們以前用到的kCICategoryBuiltIn

咱們把kCICategoryColorAdjustment這個類別下的濾鏡打印出來看看:



有11個濾鏡,其中有一個CIHueAdjust,這個看名字應該是修改圖像色調的,效果應該會比較明顯,看看它有哪些參數:



它的詳細信息裏除了咱們以前瞭解的inputImage和所屬分類信息之外,多了個inputAngle,顯然這是一個輸入參數,並且這個參數也打印的很是清晰,其中包括了:

  • 參數類型:NSNumber

  • 默認值:0

  • kCIAttributeIdentity:雖然這個值大部分狀況下與默認值是同樣的,可是它們的含義不同,kCIAttributeIdentity表示的含義是這個值被應用到參數上的時候,就表示被應用的參數不會對inputImage形成任何影響

  • 最大值:Ԉ

  • 最小值:

  • 屬性類型:角度

上面的這些參數以及取值對不一樣的CIFilter來講都不同,要具體狀況具體分析。

瞭解了以上狀況後,咱們就能夠開始編碼了。首先在VC裏添加上個工程中的經常使用屬性:

class ViewController: UIViewController {

    @IBOutlet var imageView: UIImageView!

    @IBOutlet var slider: UISlider!

    lazy var originalImage: UIImage = {

        return UIImage(named: "Image")

    }()

    

    lazy var context: CIContext = {

        return CIContext(options: nil)

    }()

    

    var filter: CIFilter!

......

與以前工程中不一樣的是,我多加了一個UISlider,Main.storyboard中VC的view像這樣:


把UIImageView及UISlider的連線與VC中的鏈接起來,而後咱們在viewDidLoad方法裏寫上: 

override func viewDidLoad() {

    super.viewDidLoad()

    

    imageView.layer.shadowOpacity = 0.8

    imageView.layer.shadowColor = UIColor.blackColor().CGColor

    imageView.layer.shadowOffset = CGSize(width: 1, height: 1)

    

    slider.maximumValue = Float(M_PI)

    slider.minimumValue = Float(-M_PI)

    slider.value = 0

    slider.addTarget(self, action: "valueChanged", forControlEvents: UIControlEvents.ValueChanged)


    let inputImage = CIImage(image: originalImage)

    filter = CIFilter(name: "CIHueAdjust")

    filter.setValue(inputImage, forKey: kCIInputImageKey)

    slider.sendActionsForControlEvents(UIControlEvents.ValueChanged)

    

    showFiltersInConsole()

}

imageView的設置同之前同樣,增長點陰影顯得好看多了。

接着對slider初始化,在以前咱們瞭解到CIHueAdjust濾鏡的inputAngle參數最大值是Ԉ,最小值是負Ԉ,默認值是0,就用這些值來初始化,而後添加一個當值發生改變時觸發的事件。

初始化filter,因爲只有一個濾鏡,filter對象也能夠重用,設置完inputImage後,觸發slider的事件就能夠了。

valueChanged方法實現:

@IBAction  func valueChanged() {

    filter.setValue(slider.value, forKey: kCIInputAngleKey)

    let outputImage = filter.outputImage

    let cgImage = context.createCGImage(outputImage, fromRect: outputImage.extent())

    imageView.image = UIImage(CGImage: cgImage)

} 

filter會在每次觸發這個事件的時候更新inputAngle屬性,同時輸出到imageView上。

雖然我並非在Storyboard裏把slider的valueChanged事件鏈接到VC的方法上,可是在這裏使用@IBAction 也是適當的,這樣能夠代表這個方法不是業務邏輯方法,而是一個UI控件觸發的方法。

編譯、運行,應該能夠看到效果了。




複合濾鏡--老電影效果

在此以前,不管是使用簡單濾鏡,仍是能動態修改參數值的濾鏡,都不算複雜,由於咱們最多也只是對一個濾鏡設置點參數而已。但是若是現有的濾鏡沒有想要的效果,或者說單個濾鏡實現不了本身想要的效果,就只能本身處理了,其中,最簡單的作法是把多個濾鏡組合起來

Core Image並無內置相似於老電影的效果,就是那種影像有點發黃,同時還會帶點黑條、白條之類的,而咱們若是要實現這種效果,整體上就像這樣:



大體過程以下:

  • 須要使用CISepiaTone濾鏡,CISepiaTone能使總體顏色偏棕褐色,又有點像復古

  • 須要建立隨機噪點圖,很像之前電視機沒信號時顯示的圖像,再經過它生成一張白斑圖濾鏡

  • 須要建立另外一個隨機噪點圖,而後經過它生成一張黑色磨砂圖濾鏡,就像是一張使用過的黑色砂紙同樣

  • 把它們組合起來

在開始以前首先要知道一件事,咱們已經知道了一些簡單的濾鏡,它們只須要設置inputImage就好了;還有一些除了inputImage參數外有其餘參數的濾鏡,除此以外,還有一些濾鏡不須要任何參數,就是上面提到的隨機噪點圖,另外,有些Core Image濾鏡會生成無限大小的圖,好比CICategoryTileEffect類別下的濾鏡,在渲染它們生成的圖以前,必須先把這些無限大小的圖裁剪一番,你能夠經過CICrop濾鏡來完成這一步,也能夠經過在一個有限的矩形範圍之類渲染這張圖來達到一樣的效果。

而後咱們就動手吧。

在 VC裏添加一個IBAction方法:oldFilmEffect,而後在Storyboard的VC上增長一個按鈕,就叫「老電影」,而後鏈接到 oldFilmEffect方法上,oldFilmEffect方法實現的代碼稍後給出,這裏先描述下詳細步驟,其實經過這些詳細步驟,已經能夠本身先實 現出來了:


應用CISepiaTone濾鏡到原圖上

  • 設置inputImage爲原圖

  • 設置inputIntensity爲1.0


建立白斑圖濾鏡

用CIRandomGenerator生成隨機噪點濾鏡,而後經過imageByCroppingToRect方法對其進行裁剪,在imageByCroppingToRect方法內Core Image隱式的使用了CICrop濾鏡

接下來使用CIColorMatrix濾鏡,該濾鏡能夠很方便的調整圖片中RGBA各份量的值,其參數設置以下:

  • 設置inputImage爲CIRandomGenerator生成的隨機噪點圖

  • 設置inputRVector、inputGVector和inputBVector爲(0,1,0,0)

  • 設置inputBiasVector爲(0,0,0,0)

CISourceOverCompositing(源覆蓋)濾鏡把前景圖(inputImage)覆蓋在背景圖(inputBackgroundImage)上:

  • 設置inputImage爲CISepiaTone濾鏡生成的圖

  • 設置inputBackgroundImage爲白斑圖濾鏡


建立黑色磨砂圖濾鏡

仍是先用CIRandomGenerator生成隨機噪點圖,而後用CIAffineTransform濾鏡對其進行處理,其實就是把生成的點放大。參數設置以下:

  • 設置inputImage爲CIRandomGenerator生成的隨機噪點圖

  • 設置inputTransform爲x放大1.5倍、y放大25倍,把點拉長、拉厚,可是它們仍然是有顏色的

在這裏除了使用CIAffineTransform濾鏡外,還有一種替代方法能夠達到一樣的效果,同時不用顯式建立CIAffineTransform濾鏡,就是使用CIImage的imageByApplyingTransform:方法。

再次用CIColorMatrix濾鏡對顏色進行處理:

  • 設置inputImage爲CIAffineTransform生成的圖

  • 設置inputRVector爲(4,0,0,0)

  • 設置inputGVector、inputBVector和inputAVector爲(0,0,0,0)

  • 設置inputBiasVector爲(0,1,1,1)

如今產生的是一個藍綠色磨砂圖濾鏡,再把CIMinimumComponent濾鏡應用到這個藍綠色磨砂圖濾鏡產生的圖上。CIMinimumComponent濾鏡會使用r、g、b的最小值生成一張灰度圖像。


把全部的濾鏡組合起來

使用CIMultiplyCompositing作最後的組合,參數設置以下:

  • 設置inputImage爲CISourceOverCompositing濾鏡生成的圖(內含CISepiaTone、白斑圖濾鏡的效果)

  • 設置inputBackgroundImage爲CIMinimumComponent濾鏡生成的圖(內含黑色磨砂圖濾鏡效果)

最後把CIMultiplyCompositing生成出的圖輸出到imageView上,仍是之前的方式,先轉成CGImage,再把CGImage轉成UIImage。

有點小長,並且同時用到了多個濾鏡,其實想表達的意思並無那麼複雜,可使用kCICategoryBuiltIn把全部的濾鏡打印出來,而後對照着看它們的參數。

這裏是oldFilmEffect方法實現:

@IBAction  func oldFilmEffect() {

    let inputImage = CIImage(image: originalImage)

    // 1.建立CISepiaTone濾鏡

    let sepiaToneFilter = CIFilter(name: "CISepiaTone")

    sepiaToneFilter.setValue(inputImage, forKey: kCIInputImageKey)

    sepiaToneFilter.setValue(1, forKey: kCIInputIntensityKey)

    // 2.建立白斑圖濾鏡

    let whiteSpecksFilter = CIFilter(name: "CIColorMatrix")

    whiteSpecksFilter.setValue(CIFilter(name: "CIRandomGenerator").outputImage.imageByCroppingToRect(inputImage.extent()), forKey: kCIInputImageKey)

    whiteSpecksFilter.setValue(CIVector(x: 0, y: 1, z: 0, w: 0), forKey: "inputRVector")

    whiteSpecksFilter.setValue(CIVector(x: 0, y: 1, z: 0, w: 0), forKey: "inputGVector")

    whiteSpecksFilter.setValue(CIVector(x: 0, y: 1, z: 0, w: 0), forKey: "inputBVector")

    whiteSpecksFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputBiasVector")

    // 3.CISepiaTone濾鏡和白斑圖濾鏡以源覆蓋(source over)的方式先組合起來

    let sourceOverCompositingFilter = CIFilter(name: "CISourceOverCompositing")

    sourceOverCompositingFilter.setValue(whiteSpecksFilter.outputImage, forKey: kCIInputBackgroundImageKey)

    sourceOverCompositingFilter.setValue(sepiaToneFilter.outputImage, forKey: kCIInputImageKey)

    // ---------上面算是完成了一半

    // 4.CIAffineTransform濾鏡先對隨機噪點圖進行處理

    let affineTransformFilter = CIFilter(name: "CIAffineTransform")

    affineTransformFilter.setValue(CIFilter(name: "CIRandomGenerator").outputImage.imageByCroppingToRect(inputImage.extent()), forKey: kCIInputImageKey

    affineTransformFilter.setValue(NSValue(CGAffineTransform: CGAffineTransformMakeScale(1.525)), forKey: kCIInputTransformKey)

    // 5.建立藍綠色磨砂圖濾鏡

    let darkScratchesFilter = CIFilter(name: "CIColorMatrix")

    darkScratchesFilter.setValue(affineTransformFilter.outputImage, forKey: kCIInputImageKey)

    darkScratchesFilter.setValue(CIVector(x: 4, y: 0, z: 0, w: 0), forKey: "inputRVector")

    darkScratchesFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputGVector")

    darkScratchesFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputBVector")

    darkScratchesFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputAVector")

    darkScratchesFilter.setValue(CIVector(x: 0, y: 1, z: 1, w: 1), forKey: "inputBiasVector")

    // 6.CIMinimumComponent濾鏡把藍綠色磨砂圖濾鏡處理成黑色磨砂圖濾鏡

    let minimumComponentFilter = CIFilter(name: "CIMinimumComponent")

    minimumComponentFilter.setValue(darkScratchesFilter.outputImage, forKey: kCIInputImageKey)

    // ---------上面算是基本完成了

    // 7.最終組合在一塊兒

    let multiplyCompositingFilter = CIFilter(name: "CIMultiplyCompositing")

    multiplyCompositingFilter.setValue(minimumComponentFilter.outputImage, forKey: kCIInputBackgroundImageKey)

    multiplyCompositingFilter.setValue(sourceOverCompositingFilter.outputImage, forKey: kCIInputImageKey)

    // 8.最後輸出

    let outputImage = multiplyCompositingFilter.outputImage

    let cgImage = context.createCGImage(outputImage, fromRect: outputImage.extent())

    imageView.image = UIImage(CGImage: cgImage)

}

以上就是一個老電影濾鏡的「配方」了。

編譯、運行,顯示效果以下:






子類化CIFilter

有時可能會對一些圖片應用一樣的濾鏡,咱們可能會像上面那樣把一連串的濾鏡組合起來,以達到本身想要的效果,那麼咱們就能夠把這些操做封裝到一個CIFilter的子類中,而後在多個地方反覆使用,就像使用Core Image預置的濾鏡那樣。

CICategoryColorEffect類別中有個CIColorInvert濾 鏡,這個濾鏡提供反色功能,實現起來並不複雜,由於咱們並非作一個真正的自定義濾鏡,而是在裏面對Core Image已有濾鏡的封裝,咱們能夠爲子類定義一些輸入參數,參照蘋果對CIFilter子類的命名約定,輸入參數必須用input做前綴,如 inputImage,而後再重寫outputImage方法就好了。

如今咱們回到Xcode中,作如下幾件事:

  1. 新建一個Cocoa Touch Class,類名就叫CIColorInvert,繼承自CIFilter

  2. 添加一個inputImage參數,類型天然是CIImage,由外界賦值。

  3. 重 寫outputImage屬性的getter。若是你以前寫過Objective-C,應該對屬性有這樣一個印象:子類要重寫父類的屬性,只須要單獨寫個 getter或setter方法就好了,但在Swift裏,不能經過這種方式重寫屬性,必須連getter、setter(若是父類的屬性支持 setter的話)一塊兒重寫。在咱們的例子中outputImage在CIFilter中只是一個getter屬性,

  4. 在outputImage裏經過CIColorMatrix濾鏡對圖像的各向量進行調整。

CIColorInvert類實現:

class CIColorInvert: CIFilter {

    var inputImage: CIImage!

    

    override var outputImage: CIImage! {

        get {

            return CIFilter(name: "CIColorMatrix", withInputParameters: [

                kCIInputImageKey : inputImage,

                "inputRVector" : CIVector(x: -1, y: 0, z: 0),

                "inputGVector" : CIVector(x: 0, y: -1, z: 0),

                "inputBVector" : CIVector(x: 0, y: 0, z: -1),

                "inputBiasVector" : CIVector(x: 1, y: 1, z: 1),

            ]).outputImage

        }

    }

}

而後在Storyboard的VC上增長一個按鈕「反色」,鏈接到VC的colorInvert方法上,colorInvert方法實現以下:

@IBAction func colorInvert() {

    let colorInvertFilter = CIColorInvert()

    colorInvertFilter.inputImage = CIImage(image: imageView.image)

    let outputImage = colorInvertFilter.outputImage

    let cgImage = context.createCGImage(outputImage, fromRect: outputImage.extent())

    imageView.image = UIImage(CGImage: cgImage)

} 

這 樣一下,一個對Core Image預置濾鏡的簡單封裝就完成了,每個濾鏡的效果就像是一張配方,CIFilter就是裝有配方的瓶子,因此子類化CIFilter並不算自定義 濾鏡,可是從iOS 8開始,Core Image是支持真正的自定義濾鏡的,自定義的濾鏡被稱之爲內核(CIKernel),在WWDC視頻裏對其有50分鐘的介紹:https://developer.apple.com/videos/wwdc/2014/#515

運行後反色的效果,再次點擊反色按鈕後顯示原圖:




簡單摳圖並更換背景

利用Core Image預置的濾鏡能知足大部分使用場景,咱們作一個簡單的替換背景的功能。

爲了方便測試,加入兩張新的圖:


點擊圖片能夠打開原圖。

將兩張圖添加到當前工程中,而後把ViewController的屬性originalImage改成返回左邊的圖:

......

lazy var originalImage: UIImage = {

    return UIImage(named: "Image2")

}()

......

而後在Storyboard的VC上增長兩個按鈕:一個用於顯示原圖:

@IBAction func showOriginalImage() {

    self.imageView.image = originalImage

}

另外一個按鈕就叫「更換背景」,鏈接到VC的IBAction方法replaceBackground上。

咱們先看要作的事情:

  • 消除深綠色

  • 組合圖片

消除深綠色

就像Photoshop的魔法棒同樣,Core Image也有相似的濾鏡,可是沒有那麼簡單粗暴,使用起來很麻煩。

在Core Image裏,咱們爲了消除某種顏色,須要使用CIColorCube濾鏡,而CIColorCube濾鏡須要一張cube映射表,這張表其實就是張顏色表(3D顏色查找表),把你想消除的顏色的alpha值設置爲0,其餘的顏色不變,Core Image將會把圖像數據上的顏色映射爲表中的顏色,以此來達到消除某種顏色的目的。

CIColorCube的這張表默認不會對inputImage做任何處理,但在咱們這裏要將全部的深綠色幹掉,因此須要本身來創建這張表。

咱們要消除的「深綠色」並不僅是視覺上的一種顏色,而是顏色的範圍,最直接的方法是將RGBA轉成HSV(Hue,Saturation,Value), 在HSV的格式下,顏色是圍繞圓柱體中軸的角度來表現的,在這種表現方法下,你能把顏色的範圍想象成連在一塊兒的扇形,而後直接把該塊區域幹掉(alpha 設爲0),這就表示咱們實際上須要指定顏色區域的範圍------圍繞圓柱體中軸線的最小角度以及最大角度,此範圍內的顏色alpha設爲0。最 後,Cube Map表中的數據必須乘以alpha,因此建立Cube Map的最後一步是把RGB值乘以你剛剛計算出來的alpha值:若是是想要消除的顏色,乘出來就是0,反之則不變。這是一張表明顏色值區域的HSV(Hue值)圖:


能夠看到若是是純綠色,其取值是120度,藍色是240度,咱們這種狀況取值大概在60到90左右(偏綠一點),在這個網站上能夠看到更詳細的RGB顏色對應的HSV值。

那麼接下來咱們就準備建立Cube Map表,建立Cube Map表的方法在蘋果官方示例中能夠找到,是C語言實現的,爲了方便起見,咱們就直接建立一個C文件來包含這些代碼。

在工程裏選擇新建一個.c文件,我取名爲CubeMap.c,在建立這個.c文件的時候,不出意外的話Xcode會問你是否須要建立一個橋接頭文件(xxxx.Bridging-Header.H),選擇是,Xcode會建立該文件,並自動把其路徑放到編譯選項的Objective-C Bridging Header中。若是你要本身添加這個文件,而且須要手動修改Objective-C Bridging Header的編譯選項,能夠看這裏

.c文件搞完之後,即把蘋果官方示例中的代碼(如下代碼)添加進去:

struct CubeMap {

    int length;

    float dimension;

    float *data;

};


struct CubeMap createCubeMap(float minHueAngle, float maxHueAngle) {

    const unsigned int size = 64;

    struct CubeMap map;

    map.length = size * size * size * sizeof (float) * 4;

    map.dimension = size;

    float *cubeData = (float *)malloc (map.length);

    float rgb[3], hsv[3], *c = cubeData;

    

    for (int z = 0; z < size; z++){

        rgb[2] = ((double)z)/(size-1); // Blue value

        for (int y = 0; y < size; y++){

            rgb[1] = ((double)y)/(size-1); // Green value

            for (int x = 0; x < size; x ++){

                rgb[0] = ((double)x)/(size-1); // Red value

                rgbToHSV(rgb,hsv);

                // Use the hue value to determine which to make transparent

                // The minimum and maximum hue angle depends on

                // the color you want to remove

                float alpha = (hsv[0] > minHueAngle && hsv[0] < maxHueAngle) ? 0.0f1.0f;

                // Calculate premultiplied alpha values for the cube

                c[0] = rgb[0] * alpha;

                c[1] = rgb[1] * alpha;

                c[2] = rgb[2] * alpha;

                c[3] = alpha;

                c += 4// advance our pointer into memory for the next color value

            }

        }

    }

    map.data = cubeData;

    return map;

}

我將這個方法稍微改造了一下,選回一個結構體,由於外面要用到length和dimension。蘋果沒有提供rgbToHSV方法的實現,能夠用我找到的這個:

void rgbToHSV(float *rgb, float *hsv) {

    float min, max, delta;

    float r = rgb[0], g = rgb[1], b = rgb[2];

    float *h = hsv, *s = hsv + 1, *v = hsv + 2;

    

    min = fmin(fmin(r, g), b );

    max = fmax(fmax(r, g), b );

    *v = max;

    delta = max - min;

    if( max != 0 )

        *s = delta / max;

    else {

        *s = 0;

        *h = -1;

        return;

    }

    if( r == max )

        *h = ( g - b ) / delta;

    else if( g == max )

        *h = 2 + ( b - r ) / delta;

    else

        *h = 4 + ( r - g ) / delta;

    *h *= 60;

    if( *h < 0 )

        *h += 360;

}

我在.c文件中導入的庫:

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

對了,若是那個橋接文件裏沒有導入這個.c文件的話是不行的,Swift的類會找不到這裏面的方法。

//  ComplexFilters-Bridging-Header.h

//  Use this file to import your target's public headers that you would like to expose to Swift.

//


#import "CubeMap.c" 


組合圖片

VC中的replaceBackground方法只須要作三件事:

  • 建立Cube Map表

  • 建立CIColorCube濾鏡並使用Cube Map

  • 用CISourceOverCompositing濾鏡將處理過的人物圖像和未處理過的背景圖粘合起來

方法實現以下:

@IBAction func replaceBackground() {

    let cubeMap = createCubeMap(60,90)

    let data = NSData(bytesNoCopy: cubeMap.data, length: Int(cubeMap.length), freeWhenDone: true)

    let colorCubeFilter = CIFilter(name: "CIColorCube")

    

    colorCubeFilter.setValue(cubeMap.dimension, forKey: "inputCubeDimension")

    colorCubeFilter.setValue(data, forKey: "inputCubeData")

    colorCubeFilter.setValue(CIImage(image: imageView.image), forKey: kCIInputImageKey)

    var outputImage = colorCubeFilter.outputImage

    

    let sourceOverCompositingFilter = CIFilter(name: "CISourceOverCompositing")

    sourceOverCompositingFilter.setValue(outputImage, forKey: kCIInputImageKey)

    sourceOverCompositingFilter.setValue(CIImage(image: UIImage(named: "background")), forKey: kCIInputBackgroundImageKey)


    outputImage = sourceOverCompositingFilter.outputImage

    let cgImage = context.createCGImage(outputImage, fromRect: outputImage.extent())

    imageView.image = UIImage(CGImage: cgImage)

}

參數設置都還比較簡單,CISourceOverCompositing濾鏡目前已經使用過屢次了,並無什麼複雜的。

編譯、運行,能夠分兩次執行,先看消除深綠色的效果,再看最後使用CISourceOverCompositing濾鏡組合圖片以後的效果:




GitHub下載地址

我在GitHub上會保持更新。


UPDATED:

我在更換背景的右側,新加入了一個顯示圖2的button,已在GitHub上更新。



參考資料:

http://www.docin.com/p-387777241.html

https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/CoreImaging/ci_intro/ci_intro.html

相關文章
相關標籤/搜索