クリアメモリ

プログラミングやモーショングラフィックス、便利なアプリケーションなど雑多に記録するブログ

【Swift】彩度を加工できるアプリをCIFilterで作ってみた

f:id:clrmemory:20170422185717p:plain 

前回、画像の「明るさとコントラスト」を加工できるOSXアプリを作成しました。そこで紹介したCIColorControlsは「彩度」を調整することもできます。

 

そこで今回は「画像の彩度」を調整できるOSXアプリの作り方を紹介します。

 

 

はじめに

 

今回紹介する方法は「CocoaProgramming」で動作を確認しており、使用言語は「Swift」です。言語が違っていたり、ツールが違うとうまく動作しない可能性があるので注意してください。

 

ではまず、前回作成した「明るさとコントラスト」を調整できるアプリの作り方を確認しておきましょう。

 

https://clrmemory.com/swift/cocoa-contrast-brightness-filter/

 

こちらでは明るさとコントラストのみでしたが、このアプリケーションに「彩度」を加工する項目を追加しました。

今回完成したアプリがこちら

このように、前回の明るさとコントラストを調整しつつ、彩度も合わせて調整できるようになりました。

 

 

では、ストーリーボードに「彩度」を加工するオブジェクト追加していきましょう。

 

ストーリーボードを作成

 

今回のアプリケーションは「明るさとコントラスト」を調整するオブジェクトについては詳しく解説しません。

オブジェクトだけではなく作成するコードの似たようなものになるため、あらかじめ確認しておくと今回の流れがわかりやすくなると思います。

 

では、彩度を加工するオブジェクト「Saturation」を設置していきましょう。追加したオブジェクトは「Label」と「NSSlider」です。

 

 

このようになりました。

彩度のスライダーオブジェクトは「0 〜 2」の範囲で値を設定できるようにしており、デフォルト(Current)値は1です。

 

 

また、こちらのスライダーもリアルタイムで値を変化させたいので、Continuousをtrueにしておいてください。

 

Continuousについて詳しく見る

 

また、ここで設置したスライダーオブジェクトのIdentifierには「Saturation」を設定しておきました。後ほど条件分岐で操作したスライダーを判定するため必須項目です。

 

これでストーリーボードは完成です。

続いて今回のアプリケーションを動作させるコードの流れを確認しましょう。

 

コードの流れ

 

今回のアプリケーションは前回の続きになるため、一部省略して解説します。

 

・オブジェクトをOutlet Action接続する

・操作されたスライダーを判定

・フィルタを作成

・フィルタを追加

ここまでは前回解説しました。

 

今回の記事では

・彩度の変数saturationValueを作成

・Saturationスライダーを判定

・スライダーで値を変化させる

・彩度フィルタを追加

あたりを触れていこうかと思います。

 

では順番にコードを作成していきましょう。

 

彩度の変数を作成

 

彩度の値を格納する変数は「saturationValue」という名前にしました。Saturationは彩度、Valueは値です。

 

var saturationValue: Float = 1.0

 

saturationValueの初期値は「1.0」、スライダーで設定したデフォルト値に合わせています。

 

彩度スライダーを判定

 

前回作成した「switch文」の中に彩度スライダーを判定する「case “Saturation”: 」を追加します。

ここで記述した「"Saturation"」は、ストーリーボードから設定したIdentifierを元に判定しています。

 

明るさとコントラストの条件分岐に彩度の条件を追加し、スライダーの値を元にsaturationValueの値を変化させましょう。

 

@IBAction func sliderAction(_ sender: NSSlider) {

    switch sender.identifier!{
    case "Contrast":
        contrastValue = sender.floatValue
    case "Brightness":
        brightnessValue = sender.floatValue
    case "Saturation":
        saturationValue = sender.floatValue
    default: break
    }

    print("Contrast => \(contrastValue)\nBrightness => \(brightnessValue)\nSaturation => \(saturationValue)")
    print("---------------------------------------------")

    imageFilter()
}

 

このように記述することで、画像を加工する彩度の値を追加することができました。senderはNSSlider(ここではSaturation)で、floatValueはFloat型で値を受け取る記述です。

 

 

彩度フィルタを追加

 

前回は以下のようなコードでフィルタを作成しました。

 

func imageFilter(){
    let ciImage = CIImage(data: image!.tiffRepresentation!)
    let filter  = CIFilter(name: "CIColorControls")!
    filter.setValue(ciImage, forKey: kCIInputImageKey)
    filter.setValue(contrastValue, forKey: kCIInputContrastKey)
    filter.setValue(brightnessValue, forKey: kCIInputBrightnessKey)
    let ciImageFilter = filter.outputImage!
    let nsImage = NSImage(size: ciImageFilter.extent.size)

    nsImage.addRepresentation(NSCIImageRep(ciImage: ciImageFilter))
    imageView.image = nsImage
}

 

ここまでくればもう分かる方もいるかと思いますが、彩度のフィルタを追加するには「brightnessのfilter.setValue」の下に以下の一文を追加します。

 

filter.setValue(saturationValue, forKey: kCIInputSaturationKey)

 

彩度(saturation)にフィルタをかけるためのキーは「kCIInputSaturationKey」です。このkCIInputSaturationKeyの値がsaturationValueで変化させるというわけですね。

 

これで彩度も調整できるOSXアプリになりました。

 

 

他のフィルタを探す

 

ここまで紹介してきたもの以外にもCIFilterには様々なフィルタが用意されています。

このサイトでも、いくつか紹介しているので参考にしてみてください。

 

CIFilterまとめ

 

完成したコード

 

ここまで彩度フィルタを調整できるOSXアプリを作成してきましたが、最終的に完成したコードが以下になります。

 

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var imageView: NSImageView!
    let image = NSImage(named: "FilterImage.png")
    var contrastValue: Float = 1.0
    var brightnessValue: Float = 0.0
    var saturationValue: Float = 1.0

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        imageView.image = image
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    func imageFilter(){
        let ciImage = CIImage(data: image!.tiffRepresentation!)
        let filter  = CIFilter(name: "CIColorControls")!
        filter.setValue(ciImage, forKey: kCIInputImageKey)
        filter.setValue(contrastValue, forKey: kCIInputContrastKey)
        filter.setValue(brightnessValue, forKey: kCIInputBrightnessKey)
        filter.setValue(saturationValue, forKey: kCIInputSaturationKey)
        let ciImageFilter = filter.outputImage!
        let nsImage = NSImage(size: ciImageFilter.extent.size)

        nsImage.addRepresentation(NSCIImageRep(ciImage: ciImageFilter))
        imageView.image = nsImage
    }

    @IBAction func sliderAction(_ sender: NSSlider) {

        switch sender.identifier!{
        case "Contrast":
            contrastValue = sender.floatValue
        case "Brightness":
            brightnessValue = sender.floatValue
        case "Saturation":
            saturationValue = sender.floatValue
        default: break
        }

        print("Contrast => \(contrastValue)\nBrightness => \(brightnessValue)\nSaturation => \(saturationValue)")
        print("---------------------------------------------")

        imageFilter()
    }
}

 

このようなコードを使うことで、簡単に画像の明るさとコントラスト、彩度を加工できるアプリが完成しました。

 

まとめ

 

今回紹介した方法を使えば、画像の彩度を加工することができます。デフォルト値が1.0であったり、フィルタのキーがkCIInputSaturationKeyであるということさえ覚えて仕舞えば簡単に使いこなせるかと思います。

 

前回の明るさとコントラストも合わせて覚えておくと良いでしょう。ぜひ参考にしてみてください。

ではまた。