先日書いたXCTestのUIテストの結果をイイ感じで見たいという記事ではXCTest
で撮影したスクリーンショットをHTMLにまとて表示する様にしてみました。
ただ、HTMLではチームのメンバーにそのまま共有するのは大変だったので、画像かPDF化してみたいなと考えていました。
今回はSwift Package Manager上で画像を作成する事で、生成した画像を手軽にチームメンバーに共有出来る様にしてみました。
本題
普段iOSやmacOSのアプリを書いていると画像生成はCore Graphic等を利用して簡単に画像を作成する事が出来ますね。ただ、Swift Package ManagerなどのPure Swiftな環境では簡単な画像すら作成する環境が整っていません。簡単な画像合成プログラムをPure Swiftな環境で書いてみたので共有したいと思います。
前提
- macOS High Sierra
- Xcode 9.3
検討したツール
今回検討したツールはImagemagick
とGD Graphics Library
です。最初に使おうと思ったのがImagemagick
です。サーバーで画像生成するには最近では定番の画像作成ツールですね。但し、今回は利用しませんでした。 理由としては誰でもインストール出来るCLIツールを作りたかったのですが、インストールだけでかなりの時間を取られてしまった為です。
今回は GD
を利用
次に検討したのがGDと呼ばれるPHPではお馴染みの昔からある画像生成ライブラリです。こちらはインストールが比較的さくっと出来たので今回はこちらを利用する事にしました。
何故AppKit使わないのか
GDならLinuxからでも利用出来る為今回はAppKitを利用しませんでした。将来的に利用シーンを広げる事を視野に入れるとLinuxで利用出来る事は価値があるかなと思います。
GDのインストール
brew install gd
最初にGDをインストールします。GDはHomebrewでインストール可能です。
SwiftからC言語のライブラリを利用する
これで画像を生成する準備ができました。次にSwiftからC言語のライブラリを利用出来る様にしましょう。
module.modulemap
を作成
mkdir ./GD && cd $_
touch module.modulemap
今回作成するプロジェクトと並列の階層にGDという名前のディレクトリを作成して、module.modulemap
ファイルを作成します。
module.modulemap
内容
module GD [system] {
header "/usr/local/include/gd.h"
header "/usr/local/include/gdfontt.h"
header "/usr/local/include/gdfonts.h"
header "/usr/local/include/gdfontl.h"
header "/usr/local/include/gdfontg.h"
header "/usr/local/include/gdfontmb.h"
link "gd"
export *
}
module.mobulemapの内容はこんな感じです。名前の定義とヘッダーファイルへのパスを示します。
同じ階層に Package.swift
を作成
import PackageDescription
let package = Package(
name: "GD",
pkgConfig: "gdlib",
providers: [
.brew(["gd"])
]
)
module.modulemap
ファイルと同じ階層にPackage.swift
ファイルを作成します。Homebrew経由のGDを利用する様な記述がある事が分かります。
Gitでタグ付け
git init .
git add .
git commit -m "Initial commit"
git tag 0.0.1 -m "Initial commit"
これでGitをコミットしてタグ付けしておきます。プロジェクト側からはこのタグを参照する様です。
プロジェクトを作成
cd ../ && mkdir ./MyProject && cd $_
swift package init --type executable
ようやくプロジェクトの作成です。GDと同階層にMyProjectという名前のディレクトリを作成して、SPMを実行可能形式で初期化しておきます。
Package.swift
を編集
import PackageDescription
let package = Package(
name: "MyProject",
dependencies: [
.package(url: "../GD", from: "0.0.1"),
],
targets: [
.target(
name: "MyProject",
dependencies: []),
]
)
Package.swiftファイルのdependenciesにGDをリンクします。
一度ビルドする
swift build
↓
Fetching /PATH/TO/GD
Cloning /PATH/TO/GD
Resolving /PATH/TO/GD at 0.0.1
Compile Swift Module 'MyProject' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/MyProject
GD
がフェッチされてちゃんとビルドされている事を確認します。
Xcodeprojを作成
swift package generate-xcodeproj
ここでXcodeプロジェクトを作成して、ガシガシコードが書ける様になりました。
フォルダ構成
tree .
.
├── GD
│ ├── Package.swift
│ └── module.modulemap
└── MyProject
├── MyProject.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ └── fromkk.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ ├── xcshareddata
│ │ └── xcschemes
│ │ ├── MyProject-Package.xcscheme
│ │ └── xcschememanagement.plist
│ └── xcuserdata
│ └── fromkk.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── Package.resolved
├── Package.swift
├── README.md
├── Sources
│ └── MyProject
│ └── main.swift
└── Tests
現時点でのフォルダ構成はこの様な感じです。最初に作ったGDと並列でMyProjectを作成しました。
GDの基礎
画像新規作成
import GD
let width: Int32 = 640
let height: Int32 = 480
let image = gdImageCreateTrueColor(width, height)
画像を新規作成するにはgdImageCreateXXXXX
を利用します。画像から読み込む事も可能です。
画像保存
import GD
let handler = fopen("path/to/image.png", "wb")
defer { fclose(handler) }
gdImagePng(image, handler)
画像を保存する時はgdImageXXXX
を利用します。保存したい形式によっていくつか関数があるのでその時々で選んでください。
画像合成
import GD
let file = fopen("copy/image/path.png", "rb")
defer { fclose(file) }
let copyImage = gdImageCreateFromPng(file)
gdImageCopy(image, copyImage, dstX, dstY, srcX, srcY, width, height)
画像同士を合成するには別の画像を読み込んで、gdImageCopy
関数で貼り付けます。
文字列を書き込む
import GD
let blackColor = gdImageColorAllocate(image, 0, 0, 0)
defer { gdImageColorDeallocate(image, blackColor) }
let text = UnsafeMutablePointer<UInt8>(mutating: "hogehoge")
gdImageString(image, gdFontGetSmall(), x, y, text, blackColor)
文字列を書き込む為にはgdImageString
関数にフォントサイズ、位置、テキスト、色を指定します。デフォルトのフォントではAscii以外は文字化けします。
※日本語が利用したい場合は別でフォントを指定する必要がありますが今回は割愛します。
作ってみたツール
https://github.com/fromkk/TestSummaries
インストール方法
brew install fromkk/TestSummaries/testsummaries
結果
まとめ
XCTestで撮ったスクショを画像にまとめてチームに共有出来る様にしてみました。Homebrewから誰でもインストール出来ますので手軽に試せるかと思います。まだまだ過去の資産を活用する事で便利なツールは作れるなと思うのでこれを機にCLIでツールの作成に挑戦してみてはいかがでしょうか?