document

HTML5 & JavaScript side
twitter: @y_imaya

「改行削除の代わりにGZIP」を実践してみた

はじめに

この記事の内容は「改行削除するくらいなら gzip したらいいじゃない」という記事の内容を受けて書いたものですので、まずはそちらをご覧になると良いかと思います。

記事を読んで、なんとなく呼ばれたんじゃないかという気になったので間違った方向でこれに取り組んでいこうと思います。

GZIP の展開を JavaScript で行う

まずは、GZIP ファイルを JavaScript で展開します。 いくつか実装はあると思いますが、ここは自作で使い慣れてる zlib.js を使ってやります。 そして、展開したらそれを Object URL にして適用します。 簡単ですね。

大体こんな感じです。

で、できたものはこちらになります。

http://imaya.github.com/demo/gunzip/

こちらのデモでは割と最近の機能(Blob, TypedArray, createObjectURL などなど)をつかっていますので Google Chrome などで見ると良いかと思います。( polyfill などを使えばそこそこ古いブラウザでも動かす事はできます)

問題点など

一応動作するのですが、gzip ファイルを XHR で取得しなくてはいけないことから、ページの読み込みからスタイルの適用まで、素のページが表示されてしまいます。

また、複雑な構成のサイトではレイアウトの再計算が発生して体感速度の低下ということも考えられます。

CSS ではあまり効果的な使い方は思い浮かびませんが、遅延しても良いようなリソースを取得するのには良いかもしれません。

宣伝

zlib.js 0.1.1 をひっそりリリースしました。 圧縮サイズが小さくなるようにハフマン符号の処理を置き換えましたので、よろしくお願いします。

SWF 研究会 #2 で LT してきました

はじめに

まずは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 さん、 どうもありがとうございました!

zlib.js 0.1.0 をリリースしました

はじめに

最近はいろいろなところで使っていただいているのに、いまだに develop ブランチが安定版というのも申し訳ないので zlib.js としては初のリリースとなる 0.1.0 をリリースしました。

使い方など

GitHub のプロジェクトページをご覧ください。

以前の master ブランチからの変更点など

  • パフォーマンス改善
  • BusterJS ユニットテスト(一部)の追加
  • Node.js 対応
  • GZIP圧縮・伸張対応
  • ZLIB Inflate のストリーム実装の追加
  • 圧縮時不正な出力が行われることがあるバグを修正

JavaScript で PSD Parser を作り始めました

はじめに

JavaScript で PSD ファイル (Photoshop Document) をパースする psd.js というのを作り始めました。 以下のURLで公開しています。
https://github.com/imaya/psd.js

psd.js と聞いて、なんか前に聞いた事あるって言う人もいると思いますが、以前話題になった psd.js は Twitpic へ譲渡されたあと GitHub で公開しなくなったようなので、3日ほどでまったく新しく作り始めました。

現在できること

まだざっくりとしか実装していません。

  • 基本的な parse
  • Image Data, Channel Image Data からキャンバス生成

未実装の部分はすごく大雑把にデータを切り出しているだけです。

将来的にやりたいこと

  • ブラウザ上で簡単な PSD Viewer の実装
  • PSD の書き出し実装

Demo

GitHub Pagesで試せます。ぜひお試しください。

psd ファイルを選択すると、自動的に parse されます。parse すると、Image Data は Canvas で描画され、コンソールにはパースされた情報が表示されます。

ライセンス

MIT ライセンスです。

参考資料


その他

うまく parse できない psd ファイルを募集します

実装時に一番苦労しているのがサンプルとなるファイル集めです。
とりあえずざっくりと動けばいいやという感じで作っていたので、まだまだうまく動かないファイルがあると思います。
そういったファイルを見つけた場合、教えていただければ改善(できそうなら)します。

以前あった実装を真似てるんじゃないの?

ありえません。自分の最も嫌いなもののひとつに「〜〜.js」とか「〜〜JS」ってプロジェクト名なのにソースコードが全て .coffee というのがあるのですが、以前存在した psd.js はまさにこれでした。
話題になったときに少し興味があったのでリポジトリを見てみたのですが、.coffee という文字列をみて回れ右しました。

jsPerf, JSPerfView を使った、JavaScript コードのベンチマーク計測とブログなどで計測結果を利用する方法

jsPerf とは

JavaScript のコードスニペットに対してベンチマークを計測するサービスです。

一般的に、コードの速度を計測する際は console.time, console.timeEnd を使う事が多いと思いますが、 実行するたびに結果がブレたり、短い処理では正確な比較ができなかったりします。

jsPerf では何度か同じ処理を実行して最終的に一秒間に何回実行できたかをスコアにするので、実行時間が 1ms より小さい処理でも計測できたり、ブレがあっても大体のスコアが分かったりします。 このスコアを計算する部分は Benchmark.js というライブラリで書かれていますので、サーバサイドの JavaScript コードの速度を計測する際にも利用できます。

どういう時に使うのか

JavaScript では全く同じ事をするのに複数の手段があるということがよくあります。 例えば、Array オブジェクトで数値を先頭から順に書き込んでいくとき、Indexer を使って代入する方法と push メソッドを使う方法があります。

こういった際に、テスト用の HTML + JavaScript を作ってポチポチとリロードして各ブラウザで実行した結果をメモ帳にまとめていっても良いのですが、 jsPerf では比較したい部分のコードを書くだけで簡単に比較することができます。

上記の例のベンチマーク

使用上の注意

コードスニペットの正当性はチェックしてくれないので、各コードスニペットが同じ結果を返すのかなどは予めチェックしておく必要があります。 以前出回った i++, ++i の速度比較など、 不公平な条件での結果をスコアだけみて「こっちの方がはやい!」などと思わないようにしましょう。 あまりに直感と掛け離れた結果は自分でいじってみるなど、疑ったり、理由を考える事も大切です。 ちなみに、上記の例ではベンチマーク対象データの生成を setup でやっておけば問題ありません。

JSPerfViewとは

jsPerf を使いだすと、ベンチマーク結果の共有を行いたい事が多々あります。
JSPerfView は HTML5 Rocks の canvas パフォーマンスチューニングのページで利用されている、jsPerf の計測結果をページに埋め込むためのものです。 上で表示されているグラフは JSPerfView を使って表示されています。 iframe を使って埋め込みます。 jsPerf の出力結果とは異なり、スニペットごとに各ブラウザの結果をまとめて表示します。(jsPerfでは各ブラウザごとにスニペットの結果をまとめて表示する)

簡単な使い方

プロジェクトページから何でも良いのでダウンロードしてきて、そのまま丸ごとどこか見れる場所にアップロードします。
自分は GitHub で fork してそのまま qh-pages ブランチに push して利用しています。

ベンチマーク結果を埋め込みたい場所で、以下のように iframe 要素に embed.html を表示したい jsPerf ベンチマークの Browserscope test ID 付きで指定する。

<iframe src="http://imaya.github.com/jsperfview/embed.html?id=agt1YS1wcm9maWxlcnINCxIEVGVzdBiPnYkODA"></iframe>

Browserscope test ID の確認方法

対象となる jsPerf のページを開き、計測結果のグラフの上の方にある "Browserscope" というリンクがあるので、これの URL の末尾が Browserscope test ID です。 例えば、以下の URL の強調した部分です。

http://www.browserscope.org/user/tests/table/agt1YS1wcm9maWxlcnINCxIEVGVzdBiPnYkODA
jsperf-browserscope-ss

バグとか表示方法の変更とか

グラフの表示がおかしくなる

現在、重い処理や貧弱なスマートフォンなどで実行して Ops/sec が 1 未満の結果を含む際にグラフがずれるようです。 この現象への対処は以下の変更を行う事で可能です。

diff --git a/js/chart.js b/js/chart.js
index e778b45..0281d4f 100644
--- a/js/chart.js
+++ b/js/chart.js
@@ -60,7 +60,7 @@ function parseChart_(response) {
       }
       // Compute series data
       var result = parseInt(platformResults[testName].result, 10);
-      if (result && !isNaN(result)) {
+      if (typeof result === 'number' && !isNaN(result)) {
         data.push(result);
       }
     }

全てのブラウザでの結果を表示したい

デフォルトのままでは、jsPerf でテストを行ったブラウザでも結果が表示されないものがあります。 これは、Browserscope の API でデータを取得する際にパラメータを省略すると "Top Browsers" のしか結果を返さないようになっているためです。 詳しくは Browserscope の API ページを参照してください。 全ての結果を表示するには以下のように変更します。

diff --git a/js/chart.js b/js/chart.js
index 2aa93f6..f682877 100644
--- a/js/chart.js
+++ b/js/chart.js
@@ -12,7 +12,7 @@ function Chart(testId) {
   this.chart = null;
 }
 
-Chart.URL_FORMAT = 'http://www.browserscope.org/user/tests/table/{ID}?o=json&callback=?';
+Chart.URL_FORMAT = 'http://www.browserscope.org/user/tests/table/{ID}?v=3&o=json&callback=?';
 Chart.MODERN = /Firefox ([4-9]|[1-2][0-9])|Chrome [1-2][0-9]|IE 9|IE 1[0-9]|Safari ([5-9]|1[0-9])/;
 Chart.MOBILE = /iPhone|iPad|Android/
 

グラフのサイズを変更したい

グラフが大きすぎる場合などサイズを変更したいことがあります。そういう場合は以下のように Highchart のオプションを指定してやれば変更できます。
ちなみに、iframe の height はこのグラフの大きさ + 40px くらいで指定するとちょうど良くなる事が多いようです。

diff --git a/js/chart.js b/js/chart.js
index b967797..6859bb8 100644
--- a/js/chart.js
+++ b/js/chart.js
@@ -87,7 +87,8 @@ function parseChart_(response) {
 function renderChart_(chartInfo, id, type) {
   chartInfo.chart = {
     renderTo: id,
-    type: type
+    type: type,
+    height: 300
   };
   chartInfo.yAxis = {
     title: {
記事検索
最新コメント
最新トラックバック
カテゴリ別アーカイブ
タグクラウド
QRコード
QRコード
  • ライブドアブログ