こんにちは、アプリケーション基盤チームの青木(@a_o_k_i_n_g)です。
一般的な Web アプリケーションがそうであるように、サイボウズのグループウェアにも画像をサムネイルで表示する機能があります。サイボウズでは日々数万件やそれ以上のサムネイルを生成しており、それらは全て ImageMagick によって生成されていました。
そこで得た知見はこちらの記事で公開されています。
blog.cybozu.io
しかし現在、サイボウズから ImageMagick は消え去りました。その理由と、我々が取った代替手段について紹介します。
![f:id:cybozuinsideout:20180817180448p:plain f:id:cybozuinsideout:20180817180448p:plain](https://cdn-ak.f.st-hatena.com/images/fotolife/c/cybozuinsideout/20180817/20180817180448.png)
ImageMagick で変換した画像
![f:id:cybozuinsideout:20180817180534p:plain f:id:cybozuinsideout:20180817180534p:plain](https://cdn-ak.f.st-hatena.com/images/fotolife/c/cybozuinsideout/20180817/20180817180534.png)
Go版で変換した画像
・・・というわけで、肉眼ではわかりませんね。ImageMagick の compare コマンドで画像の差分を出力すると差分が浮かび上がります。
稀に肉眼でわかる程度の差が出る画像もあるにはありますが、実用では問題無いと判断しました。
ImageMagick を外した理由
言うまでもなく ImageMagick は優秀なツールで、画像変換に関する何らかのサービスやツールを作る場合には採用の第一候補になることでしょう。あらゆる画像フォーマットに対応し、出力画像をきめ細かに制御できる膨大なオプションがあるからです。 しかし一方で、 ImageMagick には脆弱性が大量に存在します。2017 年に報告された ImageMagick の脆弱性は 236 件 でした。大量にある上にリモートコード実行級の脆弱性もあり、安全性という観点ではかなり厳しい評価をしなければなりません。こちらに ImageMagick の脆弱性情報があり、その多さが伺えると思います。 Imagemagick : Security Vulnerabilities もちろん、我々は AppArmor による厳重なアクセス制御やサムネイル作成専用の環境を使うなどの策は施しています。しかしそれでもこれだけ多数の脆弱性があるとなると、 ユーザーに安心安全なクラウドサービスを提供できているか? という点で疑問がありました。 また、脆弱性報告が来るたびにサイボウズに影響が無いか調査しており、そのコストが無視できないほど大きくなりました。脆弱性報告が来た際は否応無しに調査に時間を取られますし、意図しないタイミングでバージョンアップを迫られることもあります。スムーズな運用のためにも ImageMagick を採用し続けるのは得策ではないだろうという意見が出ていました。 検討を重ねた結果、我々は ImageMagick を捨てる決意をしました。ImageMagick の代わりに
代替として使えそうなツールがいくつかありましたが、サイボウズのサムネイル事情は少々仕様が凝っている部分があり、自作することにしました。そして調査の結果、Go言語と imaging パッケージが良さそうということでこれを用いて実装することにしました。 結論から言えば、ImageMagick に依存しないサムネイル作成ツールを実装し、移行も終えています。いくつか判明した点について記します。PNG の変換画像が僅かに暗くなるケースがある
Go版サムネイル生成ツールと ImageMagick では、PNG を変換した際にGo版の方がわずかに色が暗くなるケースがあることが判明しました。 Wikipedia の PNG のページ にある PNG 画像を例に取って説明します。一枚目が ImageMagick で変換した画像、二枚目がGo版サムネイル生成ツールで変換した画像です。![f:id:cybozuinsideout:20180817180448p:plain f:id:cybozuinsideout:20180817180448p:plain](https://cdn-ak.f.st-hatena.com/images/fotolife/c/cybozuinsideout/20180817/20180817180448.png)
![f:id:cybozuinsideout:20180817180534p:plain f:id:cybozuinsideout:20180817180534p:plain](https://cdn-ak.f.st-hatena.com/images/fotolife/c/cybozuinsideout/20180817/20180817180534.png)
![f:id:cybozuinsideout:20180817175457p:plain f:id:cybozuinsideout:20180817175457p:plain](https://cdn-ak.f.st-hatena.com/images/fotolife/c/cybozuinsideout/20180817/20180817175457.png)
変換できない画像がある
ImageMagick で変換出来てもGo版サムネイル生成ツールでは変換出来ない画像があります。 まず、Go版では BMP の一部は変換出来ません。BMP にはいくつか種類があり、その種類を表す値はBitmap Informa
tion Header
というヘッダ部分で指定されます。ここで指定される値と種類は下記の通りです。
値 | 意味 |
---|---|
40 | Windows V3 |
108 | Windows V4 |
124 | Windows V5 |
12 | OS/2 V1 |
64 | OS/2 V2 |
しかしGoの image パッケージの当該部分を見ると40という値が来ることを前提としており、
Windows V3
以外の BMP のバージョンは未サポートでした。
https://github.com/golang/image/blob/c73c2afc3b812cdd6385de5a50616511c4a3d458/bmp/reader.go#L151
ImageMagick では Windows V3
以外の BMP も変換可能で、この点ではGo化して劣化した部分と言えます。とはいえ近年は BMP ファイルがアップロードされる回数はさほど多くなく、大きな問題には至ってません。
他にも、ImageMagick は壊れた画像も変換できる という謎機能があり、もちろん壊れ方にも依るのですが、Go版では変換に失敗する画像でも ImageMagick だと変換できることがあります。なおそういったケースは全体から見れば極僅かなのでこのケースも実用では問題無いでしょう。