« 超強引に画像データを同期して読み込む方法 | メイン | iPhone向けトラックアップ地図を作った »

有須子時計

○○時計と言うのが流行っているようですね。
1分毎に画像が入れ替わり、画像は24時間分用意されているとか。24時間*60分で1440枚の写真ですか。有須子時計は違います。毎分毎分違う有須子が表示されます。しかもほんの一瞬だけ。
例1
例1
例2
例2
例3
例3
例4
例4
例5
例5
今見た有須子はもう見る事ができません。次に見る有須子ははじめて見る有須子です。いつも新鮮な表情をしてくれる有須子時計をお楽しみ下さい。
注意
unsafeWindowを使用しています。意味が理解できない方はインストールしないで下さい。少なくとも有須子時計がインストールされた状態では信用できないサイトを開かないで下さい。
技術的解説
何故かGreasemonkey配下では2DコンテキストのputImageDataとgetImageDataが動かないため、unsafeWindowを仕様しています。注意して下さい。
今回は、JavaScriptでかなりまじめに画像処理を行なっています。処理の大まかな流れは以下の通り。

事前準備
有須子の画像はBase64化されてGreasemonkey内に記述されています。
「0」〜「9」までの数字と「:」の文字は、赤いハロー効果を強く効かせた画像と弱く効かせた画像の各2種類、合計22枚を有須子画像と同様に保存しています。

(1) Base64の有須子画像をImageオブジェクト化
(2) Imageオブジェクトの有須子画像をCanvasオブジェクト化
(3) Canvasのコンテキストを取得し、三角関数を使って画像を歪ませた新たなCanvasを生成(歪み方は乱数で毎回変化する)
(4) 歪ませた有須子のCanvasからBase64化された画像を取得
(5) Base64の歪んだ有須子画像をImageオブジェクト化
(6) 時刻表示に必要な文字の選定とハローの強弱を決定
(7) Imageオブジェクト化されていない時刻表示用文字をImageオブジェクト化
(8) 有須子画像と同じサイズの時刻画像をCanvasとして生成(乱数で表示位置を散らしている)
(9) 有須子画像同様に、三角関数を使って画像を歪ませた新たなCanvasを生成(定数が有須子と違うため、同じ歪み方にならない)
(10) 歪ませた時刻画像のCanvasからBase64化された画像を取得
(11) 歪んだ時刻画像のBase64のデータからImageオブジェクトを生成
(12) 歪んだ有須子画像と同じく歪んだ時刻画像を合成し表示用画像のCanvasを生成
(13) 表示用画像のCanvasからBase64化されたデータを取得
(14) これまでと同様に、Base64化されたデータからImageオブジェクトを生成
(15) 表示用画像表示処理をタイマーを設定して表示待ち
(2009/12/27 追記:※version1.1では(4)(5)(10)(11)が不要になっています。)

Imageオブジェクトにいちいち変換しているのは、CanvasのコンテキストのdrawImageメソッドがImageオブジェクト以外を引数に指定できないとの事だからです(2009/12/27 追記:Canvasオブジェクトも可能でした。)。また、Image#srcにdataスキームや画像のURLを指定した場合、画像は非同期で読み込まれます。CanvasのコンテキストのdrawImageメソッドは、読み込まれていない画像を引数に渡された場合、処理がそこで終了してしまいます。つまり「image.src="...";」とした直後に「ctx.drawImage(image,0,0);」とした場合、そこそこの頻度で落ちてしまいます。仕方がないので、Imageオブジェクト化する部分はonloadを用いて処理を再開するようにしています。

処理時間で一番かかっているのはこのImageオブジェクト化の部分で、処理時間の大半を占めていました。drawImageメソッドを使わず、全ての合成処理をCanvasPixelArrayで行なう方法もあるらしいのですが、今回は諦めました。2Dコンテキストから取得できるImageDataオブジェクトにはdataプロパティがあり、そこにはCanvasPixelArrayが格納されているらしく、CanvasPixelArrayは全てのピクセルデータのRGBとアルファ値が個別に取得できるらしいので、そちらを使った方が処理時間は速いかもしれません。機会があればそのうち試してみようと思います。10秒以上かかることもあったため、時間がきてから画像処理を実行するのではなく、まず画像を処理してから表示の時間がくるまで待機するような仕組みになっています。(2009/12/27 追記:処理のほとんどは非同期処理部分なので処理が重くはならないはずです。)

処理時間が長いので、アクティブになっているウィンドウやタブのみで実行されるような処理を組み込もうかと思いましたが、うまく動作しませんでした。ソース内でコメントアウトされている部分(2009/12/27 追記:version1.1ではBase64化とImageオブジェクト化の一部もコメントアウトされています。)がその制御部分です。タブやウィンドウを複数開いている場合、それぞれで処理が実行されますので重くなる事があると思います。Firefoxが重くなった場合、まず有須子時計を無効にすることをお勧めします。
参考ページ
開設当初はそうでもなかったのですが、最近は充実してきており、よく参考にさせてもらっています。
関連エントリー
これに関連する技術的な話や、これまでの有須子ネタをご覧になりたい方は以下を参照して下さい。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

Google

タグ クラウド