UIImage と CIImage の変換(nil 回避方法)


はじめに

Swift で画像を扱うと、色々な型を使うことになります

  • UIImage
  • CGImage
  • CIImage

通常、画像を画面に表示したいだけなら UIImage だけで問題ありません

画像処理をしようと思うと CGImage を使ってみることになり、

更に複雑さや高速さを求められるようになると CIImage を使うことになります

特にリアルタイム処理では CIImage を使わないと追いつきません

それぞれの違いについては以下の記事が参考になります

さて、では相互に変換するにはどうするか

以下の記事にまとめられていますが、情報が古いのと、場合によって結果が nil になることがあるため、補足します

実装環境

  • macOS Big Sur 11.4
  • XCode 12.5.1
  • Swift 5.4.2

nil 回避方法

stack overflow にも出ていますが、 UIImage から CIImage を取り出そうとしたとき、 nil になることがあります

CIImage を元に作られた UIImage であれば問題ないのですが、そうではない(画像ファイルから読み込んだ場合など)は nil が返ります

というわけで、変換は以下のようにする必要があります

Extension にしておきました

UIImage -> CIImage

import UIKit

public extension UIImage {
    func toCIImage() -> CIImage? {
        if let ciImage = self.ciImage {
            return ciImage
        }
        if let cgImage = self.cgImage {
            return CIImage(cgImage: cgImage)
        }
        return nil
    }
}

CIImage -> UIImage

import UIKit

extension CIImage {
    func toCGImage() -> CGImage? {
        let context = { CIContext(options: nil) }()
        return context.createCGImage(self, from: self.extent)
    }

    func toUIImage(orientation: UIImage.Orientation) -> UIImage? {
        guard let cgImage = self.toCGImage() else { return nil }
        return UIImage(cgImage: cgImage, scale: 1.0, orientation: orientation)
    }
}

CIImage は画像の向き、という概念を持っていませんが、 UIImage は向きの概念があるため、引数にしています

色々やっていると、この画像の向きの概念がややこしくなってくるわけですが、、、