ImageMagick 改造入門 (その四)

こんにちは。マルチメディアエンジニアリングチームのよやです。最近は ImageMagick の ストーキング(アップデートの差分追跡)に余念のない日々を送っています。

尚、本エントリは GREE Advent Calendar 2013 の 7日目です。よろしくお願いいたします!

ImageMagick をサービスに適用している皆様におかれましては、バージョンアップに大変な慎重さをもって臨まれていると思いますが、自分なりの薀蓄を共有出来ればと、バージョンアップに絡んだ最近の闘いの記録を公開します。(長文です)

初めに logo

  • ImageMagick 公式サイト > http://www.imagemagick.org/
  • ImageMagick は開発の大変活発なプロジェクトです。提案されたコードを取り込むのも素早いです。その代わりといってか、バージョンによって画質が大きく変わったり、細かいデグレードも結構入ります。
  • ImageMagick は x.y.z-p のバージョン形式を取りますが、major version miner version, patch 番号といった区別は無しに、xyzp という4桁の1つのバージョンであると捉えるのが正しいです。(但し p は 0~10なので、そこだけ11進数)
  • リーダーの Cristy さんは svn commit コメントを殆ど書きません。でも、ソースコード自体は読み易いので差分を追うのは怖くないです。コワくない、コワくない。。

色んなバージョンで試す

弊社の画像担当者は複数のバージョンの実行ファイルを手元に用意して、調査に備えています。

この環境を作るのは簡単で、探せるだけのバージョンの tar.gz を集めて、以下のようなスクリプトでまとめて build 出来ます。尚、zlib が 1.2.6 だと ImageMagick-6.7.5-0 以降しかコンパイル出来ません。(*1) 参考 > http://www.imagemagick.org/discourse-server/viewtopic.php?t=20267&p=80457

実行ファイルが用意出来れば、以下のようなスクリプトで各バージョンでの convert コマンドをまとめて実行出来ます。

  • convert_allver.sh

  • 実行例

バージョン比較

上記のスクリプトで作った画像ファイルをテーブル表示して比較します。


ImageMagick_version

通常、古いバージョンを見る必要は無いのですが、古い不具合がずっと放置され、後の方で入った他のコミットとの相性で問題が顕在化する事もあり、デグレードの根本原因を調べるのに網羅的な確認は欠かせません。

この一覧を拡大してよく見ていくと、いくつかのバージョンで画質が大幅に変わる所があります。

  • 顔だけ拡大した比較画像。


アバター比較4つx2倍

(*2)

画像にブツブツが入る問題は当時の最新バージョンでも残っていました。
その為、弊社で使っている ImageMagick は 6.3.x 系からなかなかバージョンアップ出来なかったのですが、脆弱性の対応で是が非でもバージョンを上げる必要が出てきました。
脆弱性パッチだけバックポートする手もありますが、我々は後ろに倒れるのをよしとせず前のめりで行きます。本体の改造です!

改造

顔にブツブツ問題

  • 6.4.1-7 では問題なしで、6.4.1-8 から画質が悪化しています。
ImageMagick-6.4.1-7 ImageMagick-6.4.1-8
6.4.1-7-test 6.4.1-8-test
  • 同僚との会話。


quantize_error

つまり、quantize_error に色空間内の色と中央との距離を計算してトータルを出す時、ビットマップ画像内に複数の場所で同じ色が使われる場合は、その分を足しこむアルゴリズムですが、その色数を count 変数で数えておく事で、同じ色の距離は一度しか計算しない。という高速化を施したけれど、count を sqrt の中にしてしまったので計算結果が変わってしまったという事です。

好ましくない画質の変わり方をしていたので、count を sqrt の外に出して元のアルゴリズムと同じ結果になるよう修正しました。

白が混ざる問題

  • 稀に白いピクセルが混ざる事があります。

ImageMagick-6.6.7-6 以前 ImageMagick-6.6.7-7 以降
アバターで白いのが混ざらない アバターで白いのが混ざる

  • 6.6.7-6 までは大丈夫で、6.6.7-7 から問題が発生するのを確認。
  • 関連するコード。

  • 色空間ツリーのイメージ図

rgb-octree

コメントによると、色空間ツリーで自分の色が含まれるnodeの親兄弟までの範囲で似た色を探すのに、一つ親を余計に辿ってるので、叔父叔母の所を見ちゃってます。余計に親を辿る処理を消すと症状が収まりました。(*3)

コメント大切ですね!

ImageMagick 本家へフィードバック

不具合修正

まずは軽いジャブとして、軽い不具合修正2点を報告。

RiemersmaDither でツリーを辿る処理が間違ってたのを正した

(訳)

なんと、話の早い。

量子化エラーの計算処理を正した

(訳)

6.8.6-5, 6.8.6-6

どちらも 6.8.6-5 で取り込まれました。

ですが、これには問題があって、マージされたコードの量子化エラーの計算を勝手にレビューした所、

というコードを確認。これはアカン。。(red から count* を移動してるけど、green, blue, opacity がそのままや。。)

(訳)

すぐに直して貰えました。

レビューは大切。

高速化の提案

幸い、エンジニアブログに解説記事があったので、それを単純に英訳して渡しました。

英訳は Google 翻訳、Nifty 翻訳、Excite翻訳で生成した英語のいいとこ取りをし、それでも残る不自然な文章を手で治すやり方です。(*4)

(訳)

遠慮がちに configure で明示的に enable 指定しないとデフォルトでは無効になる方式で提案したのですが、切り替えなしで僕のコードが取り入れられました。これは嬉しい。 リリースされた11月1日は自分の誕生日だったので更に嬉しい\(^o^)/

尚、このバージョンは YoyaMagick の高速化と別に、OpenCL のガチな対応が入っていて、ImageMagick にとって高速化のエポックメイキング的な更新になっていると思います。
あ、ボクの更新というより OpenCL の方がです。

最後に

俺達の戦いはまだ始まったばかりだ!というノリで今後も ImageMagick を追いかけて行こうと思います。

以上です。最後までお読み頂き、ありがとうございました。

明日は JavaScript で色々とマニアックなライブラリを公開してる imaya さんです。お楽しみに!

*1: Debian 6 squeeze は zlib 1.2.3 で都合が良いですが、Debian 7 wheezy は zlib 1.2.7 なので困ったりします

*2: 6.4.0-11 は一見綺麗ですが、デフォルトでディザが無効になる不具合があって、グラデを真面目に扱ってないだけです。ただの階調表示です。

*3: 黒は色空間ツリーの頂点なので、その更に上のノードを漁ったつもりで処理するのは結構怖い事が起こってそうです。

*4: 英語ネイティブの同僚から、機械翻訳のように見えて何故か普通に読める不思議な文章という評価を頂きました。^^;