スキップしてメイン コンテンツに移動

[JavaScript]canvasのdrawImage()とputImageData()を比べてみました。

PixelArtsという個人的なプロジェクトでcanvasをガンガン使っているんですが、canvasとその周辺技術についてTipsをまとめたいと思います。canvasを使って、複雑な描画をしようとすると、canvasが1枚では足りない状況に陥ります。その場合はゲームなどでよく使われるように別に一時描画用のcanvasを用意して予め画面を作って一気にコピーすると色々捗ります。その際に利用するメソッドは、drawImage()か、はたまたputImageData()なのか。どっちでも良いわけじゃなかった、2つの違いを比べてみました。




drawImage()とputImageData()の違い

drawImage()とputImageData()の違いは、昔はコピーによる画像の劣化が指摘されていました(こちらのサイトで詳しく調べられている方がおられます)が、今は特に考えなくてもいいような気がします。それより何より、この2つは両方共異なるcanvas間で画像をコピーするのですが、コピーする内容が微妙に違うので、用途に合わせて使い分けする事で表現の幅が広がるように思います。

putImageData()はgetImageData()で取得したりcreateImageData()で作成したイメージデータ(=imagedata)をcanvasに配置する訳ですが、このイメージデータの内容は配列になっていて(imagedata.data)、この配列を直接書き換えるメソッドです。
一方drawImage()はcanvas上の指定した短形のデータをコピーしますが、コピー元の透過情報をコピー先に適用するので、何も描画していないコピー元の部分はコピー先に描画されているものが表示されます。つまりは画像処理ソフトでいうレイヤーのように利用できるわけです。
以下はサンプルです。右のcanvasはコピー先で左のcanvasがコピー元です。また赤の円はdrawImage()でコピーしたもので、緑の円はputImageData()でコピーしたものになります。




ソースは以下の通りです。
function test3(){
    var canvas1 = document.getElementById('test3');
    var ctx1 = canvas1.getContext('2d');
    var canvas2 = document.createElement('canvas');    // バッファリング用の表示しないcanvas
    var ctx2 = canvas2.getContext('2d');
    var btn = document.getElementById('btn3');
    // canvas 2D contextが使える前提

    canvas1.width = 300;
    canvas1.height = 300;
    canvas2.width = 300;
    canvas2.height = 300;
    ctx1.fillStyle = '#000000';
    ctx1.fillRect(0, 0, 300, 300);
    ctx1.fill();
    draw();

    function draw(){
        ctx2.beginPath();
        ctx2.fillStyle = '#ff0000';
        ctx2.arc(100, 100, 20, 0, Math.PI * 2, false);
        ctx2.fill();
        ctx2.beginPath();
        ctx2.fillStyle = '#00ff00';
        ctx2.arc(200, 200, 20, 0, Math.PI * 2, false);
        ctx2.fill();

        ctx1.drawImage(canvas2, 80, 80, 40, 40, 80, 80, 40, 40);
        var imagedata = ctx2.getImageData(180, 180, 40, 40);
        ctx1.putImageData(imagedata, 180, 180);
    };
};

canvasを複数枚使うというのは、処理がややこしくなりますし、最初はあまりメリットを感じないですが、描画する点数が多かったり、同じ画像をローテーションして何回か使ったりする場合は利用価値があるように思います。
私は、パーツ毎にバッファ用のcanvasに描画しておいて、最終的にdrawImage()で表示するcanvasにコピーするという方法をよく使います。

また、合成の方法描画した時の合成処理の方法をglobalCompositeOperationプロパティで指定する事で、マスク処理のように合成したり加算処理したりもできます。 → globalCompositeOperation プロパティ - Canvasリファレンス - HTML5.JP

画像処理に関してはマシンパワーを使わず、高速で高品質に描画する方法を日々模索している、といった感じです。

PixelArtsはMath.random()を使ってプログラマーが芸術に挑戦するというものです。
PixelArtsの方もよろしくお願いします。

PixelArts


コメント

このブログの人気の投稿

[VB.NET]オレオレ証明書でSSL通信するための短絡的な解決法

VB.NETソフトウェアでサーバーと通信することはよくある事だと思いますが、最近はHTTPを使って明けっ広げに刺しに行くよりHTTPSを使って暗号化してこそこそやった方が時代の流れに即した感じですよね(違うか)。 いちいちテスト環境でSSL証明書を用意するのも面倒だということで、セキュリティ的には全くよろしくない方法で迂回できるので紹介します。

[JS]Canvasでよく使う描画テクまとめ

HTMLで画像をいじくりたい時は、canvasを利用して編集するのは一般的ですが、WindowsストアアプリではHTML+CSS+JSでのアプリ開発ができる事もあって、簡単な画像編集であれば、C#やVBを使うより分かりやすいし資料が多く、C++でDirectXをガリガリ書くよりお手軽。入出力もファイルピッカーを使えば簡単に実装できます。今回は、Windowsのコードではなく、Canvasを利用する時のJavaScriptを使いどきに合わせてまとめていきます。

curl の基本的な使い方 -設定編-

今回のcurl TIPSは、curlをより日常的に使っていくためのHow toです。curlには、数多くのオプションが用意されていて、それらを組み合わせる事で様々な事が楽になるでしょう。サービス監視の自動化などにはまさにcurlの得意分野です。 今回は、curlを更に自分のものにしていくために大事なカスタマイズの部分を解説します。