【iOS】SwiftUIとCoreImageを使って、EXIF情報を表示した画像をシェアする

iOS, Swift

はじめに

こんにちは、最近NewJeans沼にどっぷりハマっている永田です。

Cool With You, Cookieが特にお気に入りで、Coke STUDIO SUPERPOP JAPAN 2023も参戦予定でとても楽しみです。

さて、今回はLiitというアプリをコピーしてみた中で学んだことを書き記そうと思います。

開発環境

本記事で扱うコードは以下の環境で動作することを想定しています。

  • Xcode 14.3.1
  • Swift 5.8.1
  • iOS 16.0+

Liit とは

Liitとは写真編集アプリの一種です。

さまざまなフィルターやフレームなどが用意されており、簡単に写真を編集できます。

その中でも写真のメタデータ(EXIF)を表示できるフレームがX(ex-Twitter)の写真家たちの間で流行っていました。

Liit で編集した画像

普段画像データをこねくり回すようなコードを書くことがないので、写真からEXIF情報を取得する方法を知らずかなり興味を惹かれました。

その方法さえわかれば自作できるのではと考え、勉強がてらLiitをコピーしてみることにしました。

実装する機能

まずは実装する機能の洗い出しを行いました。
ざっくり以下の5つに分けて実装を行います。

  • 写真ライブラリから写真を選択する
  • 写真からEXIFをパースする
  • 写真とEXIFをフレームに入れて表示する
  • フレームを画像化する
  • 画像をシェアする

これらのそれぞれについて、簡単なサンプルコードと共に実装方法をご紹介します。

実装の流れ

写真ライブラリから写真を選択する

ここでは PhotosPickerを使用しました。

iOS 16以降で使えるSwiftUIの Viewで、UIKitにある PHPickerViewControllerUIImagePickerControllerと同等の機能を持っています。

以下のように Viewbody内に配置することで、写真ピッカーを表示させるボタンを表示できます。

写真からEXIFをパースする

ここでは CIImage.properties を使用しました。

これは写真のメタデータを格納する [String: Any]のディクショナリで、使用できるキーはImageIOのEXIF Dictionary Keysに定義されています。

以下は、 PhotosPickerで取得した画像から「焦点距離」を取得する例です。
特定のキーを用いて propertiesから値を取り出しています。

ただし、このメタデータをパースする処理にはしんどいポイントが何箇所もあります。たとえば、

  • キーごとに取得できる値の型がドキュメントに書かれていない
  • キーによってはディクショナリが入れ子になっている場合がある
  • 入れ子になっているディクショナリに対してしか使えないキーも多く存在する
  • ↑のようなキーたちが、どのキーから取得したディクショナリに対して使うものなのかがドキュメントに書かれていない

などなど、自力で色々調査しながら実装する必要があり、かなりめんどくさいです。
楽曲のメタデータもそうですが、このあたりのドキュメントが適当すぎるのはどうにかならないものか。。。

自分は、パースのロジックを ImageMetadataParserというクラスに集約させ使用することにしました(具体的な実装は本記事の末尾に記載しています)。

写真とEXIFをフレームに入れて表示する

ここではCombineを使用したMVVMパターンで実装をしています。

ObservableObjectなViewModelを作成し、 pickedPhotoが変わるたびにEXIFをパースしています。
パースした結果のEXIFデータを @Publishedで定義しておき、その変更をViewで監視しています。

フレームを画像化する

ここでは ImageRendererを使用しました。

iOS 16以降で使えるSwiftUIのAPIで、SwiftUIの Viewを画像化できます。

このような extensionを定義しておくことで、任意の Viewsnapshot()メソッドを呼ぶことで簡単に画像を取得できます。

画像をシェアする

ここでは ShareLinkを使用しました。

iOS 16以降で使えるSwiftUIの Viewで、UIKitにあった UIActivityViewControllerと同等の機能を持っています。

以下のように Viewbody内に配置することで、シェアシートを表示するボタンを表示できます。

完成

これらの技術を組み合わせて、LiitのようにEXIF情報を表示した画像をシェアできるアプリが完成しました。

完成したアプリのキャプチャ
書き出した画像

完成品のコードは以下に記載しておきます。
UIKitと比べてかなり少ないコード量で実装できている印象を受けました。

ContentViewModel.swift

ContentView.swift

ExifImage.swift

ImageMetadataParser.swift

Data.swift

終わりに

今回は以下の技術を用いてLiitのコピーアプリを作ってみました。

  • SwiftUI
    • PhotosPicker
    • ImageRenderer
    • ShareLink
  • Combine
  • CoreImage
    • CIImage
  • ImageIO
    • EXIF Dictionary Keys

画像データをこねくりまわすなど、普段の業務では関わりの少ない分野に触れられたのが新鮮で楽しかったです。

SwiftUIの新しいAPIにもいくつか触れることができ、SwiftUIもここ数年でかなり便利になってきていることを実感できました。
OSのサポートラインの問題はどうしてもついてまわりますが、新規のアプリ等では積極的に導入していきたいと思います。

また気になるアプリが出てきたらコピーしながら勉強しようかと思います。

参考文献

iOS, Swift