【Swift】画像の色を自由に変更してローカルに保存する方法


とりあえず、今作ってるアプリの結構メインな機能の部分なので筆者必死です。
興味があったり、いずれこんな機能ついてるアプリ作りたいなって人のためにもご参考まで。

画像の色を変更する

UIImageRenderingMode

レンダリングモードを使うことで画像の色を自由に変更できる。
NavigationBarやTabBarのItemに黒い色の画像を設定しても色が変更できますよね?あれを使います。

StoryboardにUIImageViewを配置してる体で書いていきます。

ViewController.swift
@IBOutlet weak var imageView: UIImageView!

override func viewDidLoad() { 
    imageView.image = UIImage(named:"smile.png")?.imageWithRenderingMode(.AlwaysTemplate)
}

上記の様にimageを読み込んだあとに

.imageWithRenderingMode(.AlwaysTemplate)

を書くことでテンプレート画像を描画します。

デフォルトで、このニコニコマークは、黒い画像を使用してますが

CustomColor.swift
extension UIColor {
// RGBからUIColorを返します
class func rgb(r: Int, g: Int, b: Int, alpha: CGFloat) -> UIColor{
        return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: alpha)
    }
}        

上記のような、extensionを用いてRGBをからUIColorを得る機能を追加したとして

ViewController.swift
@IBOutlet weak var imageView: UIImageView!

override func viewDidLoad() { 
    imageView.image = UIImage(named:"smile.png")?.imageWithRenderingMode(.AlwaysTemplate)
    imageView.tintColor = UIColor.rgb(255, g: 0, b: 0, alpha: 1)
}

このようにimageViewのtintColorに指定してあげると

ニコニコマークの色が指定した色に変わります。

あとは、UISliderなどを使用して画像の色を動的に変更することも可能です。

しかし、このあと問題が‥

画像を保存する

筆者は、先ほどの色に変えたニコニコマークをローカルの画像フォルダに保存したいと思いました。

通常の画像保存方法

セーブボタンなどを用意した場合下記のような処理で、保存できます。

ViewController.swift

@IBAction func saveImageButton(sender:UIButton) {
    UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, "image:didFinishSavingWithError:contextInfo:", nil)
}


//保存処理のイベント
func image(image: UIImage, didFinishSavingWithError error: NSError!, contextInfo: UnsafeMutablePointer<Void>) {
        if error != nil {
           //エラーの時
        }
}

が、しかし‥

この保存方法だと、色を変更する前の元画像が保存されちゃいました‥。

真っ黒なニコニコマークがたくさん保存されちゃいました。

ナンテコッタ/(^o^)\

どうにかして、保存できないか模索して最終的に辿り着いたのは

編集してるImageViewのところだけスクショしちゃう

ViewController.swift

var saveImage: UIImage?

var frame:CGRect?

func screenShot() -> UIImage{
        // スクリーンショットの取得開始
        UIGraphicsBeginImageContextWithOptions(imageView.frame.size, true, 1.0)

        // ImageViewの座標取得
        let x:CGFloat = self.imageView.bounds.origin.x
        let y:CGFloat = self.imageView.bounds.origin.y

        // ImageViewの幅と高さを取得
        let width:CGFloat = self.imageView.bounds.width;
        let height:CGFloat = self.imageView.bounds.height

        // 上記よりフレームを生成する
        frame = CGRect(x: x, y: y, width: width, height: height)

        // frameのサイズと場所で描画
        imageView.drawViewHierarchyInRect(frame!, afterScreenUpdates: true)

        // 描画したスクリーンショットを取得する
        saveImage = UIGraphicsGetImageFromCurrentImageContext()

        // 取得終了
        UIGraphicsEndImageContext()

        // スクショを返す
        return saveImage!
}

上記の方法でImageViewの部分だけをスクショしてUIImageで返すことが出来ました。

あとは、先ほどの保存処理の中で呼び出してあげます。

ViewController.swift

@IBAction func saveImageButton(sender:UIButton) {
    UIImageWriteToSavedPhotosAlbum(self.screenShot(), self, "image:didFinishSavingWithError:contextInfo:", nil)
}


//保存処理のイベント
func image(image: UIImage, didFinishSavingWithError error: NSError!, contextInfo: UnsafeMutablePointer<Void>) {
        if error != nil {
           //エラーの時
        }
}

これで、ローカルに赤いニコニコマークが保存できました。

この挑戦中に上手く保存できなかった、ニコニコマーク達です。