読者です 読者をやめる 読者になる 読者になる

blog.syfm

徒然なるままに考えていることなどを書いていくブログ

イラストを Git で管理したかったのでツールをつくった

イラストの管理

自分はたまにイラストを描いたりするのですが、以前からその管理方法に苦労していました。
苦労していた点は主に次の 2 点です。

  • バックアップ
  • 制作過程 Gif をつくるのが面倒くさい

強い人は、短時間でもさらっとイラストを描いてしまいますが、自分は時間をものすごく掛けないとまともなものが描けないので、バックアップは結構頻繁に取ります。
手動でバックアップしようとした場合は、ふつうにファイルを複製する感じになると思います。
ただ、普段からコードを書いていて VCS を利用している身だと、どうしても原始時代かと錯覚してしまいます。
さらに、PhotoShop の psd 形式や CLIP STUDIO PAINT の標準である clip 形式はいろんなデータが詰め込んであるので 1 ファイル当たり平気で 50 MB くらい持って行かれます。これも結構厳しいところです。

VCS を使う場合の不便な点

そこで 1 年くらい前から Git などの VCS で管理できないかなぁと思うようになりました。
Git を使うことでイラストファイルの差分は管理できるようになります。
ただ、コミット時点でのイラストがどんなものだったか確認することはできません(できるけど面倒くさい)。
あくまで Git でバイナリの差分を管理しているだけです。

Clip

そこでこんなものを作りました。 今回は自分がイラストを描くときに使っている CLIP STUDIO PAINT の clip 形式ファイルを管理しようと思ったので、clip 形式に絞っています。

github.com

Git の hook にちょっと設定を追加して、コミットの度にその時点のイラストを自動エクスポートする。
差分を見たいときにはコミットハッシュに紐付いたイラストを表示させる感じ。

仕組み

clip ファイルは何かしらのメタデータ(ちゃんとは確認していない)と SQLite データベースがくっついているので、まず SQLite データベースのマジックナンバーを探して、そこから末端までを取り出しています。
データベースには CanvasPreview なるテーブルがあり、そのうちの ImageData カラムに画像データが blob で格納されているので、取り出すことで画像を生成しています。
最初は Python3 で書いたのですが、あまりにも動作が遅すぎたので、Go で書くことにしました。
Go を書くのは初めてだったのですが、ものすごく書きやすくてすごい(KONAMI)と思いました。
以下が同じ処理の Python3 と Go による比較です。

Python3
f:id:ktr_0731:20161025000126p:plain

Go
f:id:ktr_0731:20161025000135p:plain

Python3 より 132 倍高速になりました。ハンパねぇ…。さすがコンパイラ言語…。

デモ

ちょっと分かりづらいですが、以下のような感じで使えます。
コミットハッシュ値を引数に与えてやることでそれに対応するイラストを表示します。
Demo

思ったこと

.clip 以下にコミット毎の画像が入るので、ImageMagick なんかを使うことでいちいち画像形式でエクスポートしなくても簡単に制作過程 Gif を作ることができます。
ただ、いくつか欲しい機能を実装していないので追々やっていきます〜。
リポジトリの容量については 1 ファイルあたり 1 GB が GitHub での限界だったと思うので 1 リポジトリ 1 イラストを意識していれば特に問題はないかと思います。

追記(2016年10月26日)

思ってもいない反響があって驚いています…。ありがとうございます。
ただ、ちょっと重要なことを忘れていました。
Git は差分を管理するわけではなくて実際にはファイルをまるごと保存するような形で管理しているので、コミットする度に容量は増加します。
とはいえ、 git gc コマンドによって容量の削減ができるはずです。
LFS を利用することでいい感じにできそうなので機能追加を行いたいと思います!ご意見ありがとうございました!

追記(2016年10月27日)

clip ファイルの管理には Git LFS を利用することでリポジトリの肥大化を抑えることができるので、LFS の利用を推奨します。
詳しくはこちら↓

git-lfs.github.com