【Swift】CIImageからUIImageに変換すると画像が表示されない


CIImage->UIImageへの変換がうまくいかなかった話。

環境

MacOS Big Sur version 11.4
Swift 5.4.2
Xcode 12.5.1

CoreImageを使って画像加工をしていた

Swiftの勉強でCoreImageを使った画像にフィルターをかけるアプリを制作していました。

CoreImageを使うにはUIImageからCIImageを作る必要があるらしい。
そして、CIFilterなどで加工したCIImageをSwiftUIのView内で表示するにはUIImageに変換する必要がある。

いろいろ記事を漁ったところ、UIImageからCIImageへの変換は次の2種類があることがわかった。

example1.swift
let uiImage: UIImage = UIImage(ciImage: ciImage!)
example2.swift
let ciContext = CIContext(options: nil)
let outputCGImage: CGImage = ciContext.createCGImage((ciImage)!,
            from: (newCiImage?.extent)!)!
let uiImage = UIImage(cgImage: outputCGImage, scale: 0, orientation: uiImage.imageOrientation)

参考:Core Imageを使ったiOS上での画像フィルタの実装( https://qiita.com/makoto-nagai/items/21cb119d036b7db346af

CIImage->UIImageの変換がうまくいかない

とりあえず、上側のUIImage→CIImageにダイレクトに変換しているコードがシンプルなので書いて実行してみたら、画像がまったく表示されなくなった。なぜ?

printでデータが入っているか確認したがデータはちゃんと入っていそう。なぜ、、、?(ここで1時間ぐらい格闘した)

下側のCIContextでCGImageを経由してUIImageに変換しているコードだとちゃんと画像が表示されました。なぜ、、、?

CIImageは画像そのものではなく、「レシピ」

こういう時は公式ドキュメントだ!

Apple Developerの公式ドキュメントのCIImageに書かれていた文章(を日本語訳したもの)は以下の通り。

CIImageオブジェクトは、画像データが関連付けられていますが、画像ではありません。CIImageオブジェクトは、画像の "レシピ "と考えることができます。CIImageオブジェクトには、画像を生成するために必要な情報がすべて含まれていますが、Core Imageは、指示されるまで実際に画像をレンダリングしません。このような遅延評価により、Core Imageは可能な限り効率的に動作します。
CIImage | Apple Developer Documentation: https://developer.apple.com/documentation/coreimage/ciimage

つまり、、、?
料理で例えると、CIImageは料理そのものではなく料理を行う手順を記載しているクックパッドのような役割で、CIContextからCGImageへの変換の段階は手順に従って料理を行っているということでしょうか。
そして、CGImage->UIImageは料理を見せるためにお皿に盛り付けを行うといったイメージ?

つまり、UIImage(ciImage: ciImage!)で画像が表示されなかったのは、クックパッドをそのままお皿に盛り付けようとしたためにうまくいかなかったということなのでしょうね。

しかし、なぜCIImage->UIImageにダイレクトに変換できるメソッドが用意されているのかはわかりませんでした。この方法でも正しく動く例があるのでしょうか、、、。

おわりに

そもそもうまくいかなかった時点でCIContextでの方法にさっさと切り替えればよかったのですが、結果的にUIImageとCIImage、CGImageの理解を深めることができたのでいい経験になりました。

また、著者はSwiftでのプログラミングの経験も浅く、Qiitaでの記事執筆も初めてなので、至らぬ点があるかもしれません。何か問題があればコメントをお願いします。
自分のアウトプットと備忘録のために執筆しましたが、この記事が誰かの役に立てば幸いです。