はじめに

まずはLT枠5分というはずだったのに15分ほど話してしまい、会場の皆様すみませんでした。

最近 SWF の Lossless, Lossless2, Jpeg3 あたりのデコード実装を JavaScript で行ったので、Lossless 系について話しました。 SWF の話と見せかけて、PNG の仕様の話と JavaScript のパフォーマンスチューニングが大半で、あとは少しだけ zlib.js の宣伝です。

スライドについて

GitHub Pages です。

JSPerfView のグラフを埋め込みたかったので、ブラウザで実行できるスライドツールを探しました。 その中で html5slides が良さそうだったので採用しました。 JSPerfView の使い方には以前書いたものがあるのでご参照ください。

また、JavaScript で画像を扱う話しだったので、実際にブラウザでデコードして表示というのがそのままスライドに埋め込めるのは便利でした。

Android Browser の putImageData のバグについて

現象と対策

@fchiba さんに教えていただいた内容そのままなので、自分が説明するというのも恐縮なんですが備忘録として書いておきます。

Android Browser (確認した限りでは 2.3, 4.0) では CanvasRenderingContext2D#putImageData で描画する際に、描画する ImageData の RGB 値を premultiplied alpha として扱うバグがあるようです。 Android Browser でこのバグがある場合には、CanvasPixelArray に RGBA をセットする際に以下のように alpha 値を掛けてやれば良いようです。

red   = red   * alpha / 255 | 0;
green = green * alpha / 255 | 0;
blue  = blue  * alpha / 255 | 0;
alpha = alpha;

比較

対策前対策後のページを用意しましたので、Android Browser で確認してください。

なお、ここでは上記の対策だけを入れたコードになっていますので、正常なブラウザで見た際も premultiplied alpha になっています。

バグの有無を判定

このバグを持っているかどうか判別するのをどうするか考えてみたのですが、実際に putImageData して判別するのが分かりやすいかと思いました。 他にもっと良い方法があればください。

Lossless2 のデコードへの影響

Lossless2 では RGB 値を premultiplied alpha で持っているため、Android Browser の場合はそのまま使えば良いことになります。 そのため、Android Browser で Canvas を使用する場合はさらに(特に Direct で)速度を向上させることができます。

お礼

発表の機会を与えていただいた @yoya さんと @tkihira さん、 Android Browser の putImageData バグの解決方法を教えていただいた @fchiba さん、 前日に iPhone5 でベンチマークを実行していただいた @constellation さん、 どうもありがとうございました!