[SwiftUI][Image] イメージ処理アプリを作る(5)

SwiftUI

SwiftUI を使った イメージ処理アプリを作ってみます

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Big Sur 11.1
  • Xcode 12.3

本シリーズ内容

SwiftUI を使って、イメージ処理するアプリを作ります。

以下の理解が進むことがゴールです。

  • SwiftUI を使ったアプリ開発
  • NSImage を使った画像処理全般
  • Photos 拡張編集機能 と SwiftUI app の組み合わせ方
  • イメージ処理アプリも TDD で進めることが可能かどうか
  • その他 macOS app 開発 Tips

この記事で作る範囲

次回以降に、Photos の拡張機能としての実装をして行く前に少しアーキテクチャを見直しておきます。

  • 写真とその表示サイズ、メガネイメージその配置とサイズをモデルとして保持する
  • 合成イメージを出力

Photos の拡張機能として実装をすると、全体を合成したイメージの作成が必要になります。
そのための準備として、現在、各ビューで保持している上記の情報をモデル内に持つようにして、モデルから合成したイメージを提供できるようにします。

モデル

モデルで保持する情報は以下のものとします。

  • 表示中の写真イメージ
  • 表示している写真の(表示上の)大きさ
  • メガネのイメージ
  • メガネの配置位置
  • メガネの表示上の大きさ

モデル定義

以下のような定義になります。EditModel という名前のクラスにして、このクラスからビューのアップデートをできるように ObservableObject を継承し、必要なプロパティに @Published を付与します。

EditModel 定義

各種情報提供用プロパティ

メガネの移動やリサイズ用に、位置調整をしているので、そのための値を提供するプロパティもこのクラスに作ります。

ビューは、このクラスからの情報を(そのまま)使って、配置できるようにします。

EditModel property

ビューからクラスを参照

GlassImage ビューを、この EditModel を参照するように変更します。

GlassImage
コード解説
  1. EditModel を environmentObject で受けるようにします
  2. UI 操作用のプロパティは、ビューに残します
  3. 位置情報等は、EditModel から提供された情報を使います

モデルとして 保持しなければいけない情報と UI 操作のために一時保存している情報を整理できました。

EnvironmentObject として EditModel を受け取るようにしたので、上位ビューのコードも修正が必要です。

PhotoGlassesApp
コード解説
  1. App の初期段階で EditModel を作ります
  2. メインビューに environmentObject として設定します

MainView は、以下のようになります。

MainView

コード解説
  1. App で EnvironmentObject として EditModel を付与していますので、EnvironmentObject として受け取ることができます
  2. 以降で、EditModel を参照して表示するように修正します

合成したイメージを保存できるように

合成イメージ作成

イメージを合成するために必要な情報を EditModel に 保存していますので、EditModel から 合成したイメージを取得できるようなメソッドを作ります。

example

コード解説
  1. AppKit は、原点は、左下
  2. SwiftUI では 表示に使用しているレイアウトによる
    メガネのイメージは、ZStack をデフォルトレイアウトで使用しているため center-aligned で表示
  3. SwiftUI での座標系は、画面下に移動すると Y+
  4. AppKit での座標系は、画面下に移動すると Y-
  5. SwiftUI/AppKit 共に、X軸は同じ扱い(左移動で X-、右移動で X+)

上記の点を考慮して、イメージを合成します

合成イメージ出力ボタン

合成イメージを作成するメソッドを作りたいのですが、現時点では出力する方法がありません。

合成したイメージを出力するボタンをつけます。

アプリに出力ボタンを付与
アプリに出力ボタンを付与

ボタンを1つ追加するだけなので、非常に簡単です。

MainView
コード解説
  1. イメージ表示の右側に表示するため HStack を使います
  2. ボタンが押下された時の処理として、EditModel から合成イメージを取得し、ファイル書き出しメソッドに渡します
  3. 渡されたイメージをファイルに書き出すメソッド
  4. 注意:App Sandbox 設定で、”User Selected File” の扱いを “Read” から “Read/Write” に変更する必要があります

アプリと出力されたJPEG

アプリと出力したJPEG
アプリと出力したJPEG

この記事でできたこと

  • イメージ合成に必要な情報を集めてアーキテクチャのリファクタリング
  • ビュー表示を NSImage として合成し JPEG ファイルに出力

次回

Photos の extension としての必要な実装をすすめていきます。

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です