画像処理

【JavaScript】 画像ファイルを読み込んでCanvasに表示する

更新日:2022/07/05

JavaScriptで画像ファイルをCanvasに表示するとき少し悩んだので、方法をメモとして残しておきます。

 

手順

今回は次の二つ手順で、画像ファイルをCanvasに描画してみます。

一つ目がこちら。

  1. 画像データをデータ URLで読み込む
  2. imageオブジェクトの src にデータ URLをセット
  3. imageオブジェクトの内容をCanvasに描画

この方法は、バイナリデータをテキスト(データ URL)に変換しています。
JavaScriptの文字列は、一文字2バイトなので、それなりにメモリを使用します。

二つ目がこちら。

  1. 画像データをArrayBufferに読み込む
  2. 読み込んだデータからBlobを生成する
  3. BlobからオブジェクトURLを取得する
  4. imageオブジェクトの src にオブジェクトURLをセット
  5. imageオブジェクトの内容をCanvasに描画

こちらは、Blob生成時に、ArrayBufferの内容をBlobにコピーします。
そのため、メモリを2倍使用します。

 

ソース

二つの方法で画像ファイルを読み込んでみます。

次のHTMLは、二つの方法で共通して使用しています。

共通HTML


<p><input type="file" id="file_select"></p>
<p><canvas id="canvas"></canvas></p>

データ URLで読み込む

一つ目の方法のJavaScriptコードです。

JavaScript


const start = (fileSelectId,canvasId) =>{

    const canvas = document.getElementById(canvasId);
    const context = canvas.getContext("2d");

    const image = new Image();
       // 画像読み込み完了
    image.onload =  ()=>{
        canvas.width = image.width;
        canvas.height = image.height;
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
    };
    image.onerror = ()=>alert("読み込めませんでした");

       // ファイル読み込み完了
    const reader = new FileReader();
   
    reader.onload = () => image.src = reader.result;

    document.getElementById(fileSelectId)
        .addEventListener("change",function(){
                // ファイル読み込み開始
            reader.readAsDataURL(this.files[0]);
        });

};
window.addEventListener( "DOMContentLoaded" , ()=>
    start("file_select","canvas")
);

ArrayBufferに読み込む

JavaScript


const start = (fileSelectId,canvasId) =>{

    const canvas = document.getElementById(canvasId);
    const context = canvas.getContext("2d");

    const image = new Image();
       // 画像読み込み完了
    image.onload =  ()=>{
        URL.revokeObjectURL(image.src);
        canvas.width = image.width;
        canvas.height = image.height;
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
    };
    image.onerror = ()=>alert("読み込めませんでした");

       // ファイル読み込み完了
    const reader = new FileReader();
   
    reader.onload = () =>{
        const blob = new Blob([reader.result]);
        image.src = URL.createObjectURL(blob);
    };

    document.getElementById(fileSelectId)
        .addEventListener("change",function(){
                // ファイル読み込み開始
           reader.readAsArrayBuffer(this.files[0]);
        });

};
window.addEventListener( "DOMContentLoaded" , ()=>
    start("file_select","canvas")
);

URL.createObjectURLを実行すると、blobが所持しているデータが解放されなくなるので、URL.revokeObjectURLを忘れずに実行する必要があります。

関連記事
URL.revokeObjectURL

 

imgタグに表示した後Canvasに描画する

今度は読み込んだ画像をimgタグに表示して、Canvasに縦横サイズを半分にして描画してみます。

HTML


<p><input type="file" id="file_select"></p>
<p><img id="image"></p>
<p><canvas id="canvas"></canvas></p>

JavaScript


const start = (fileSelectId,canvasId,imageId) =>{

    const canvas = document.getElementById(canvasId);
    const context = canvas.getContext("2d");

    const image = document.getElementById(imageId);
    image.onload = ()=>{
        canvas.width = Math.floor(image.width / 2);
        canvas.height = Math.floor(image.height / 2);
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
    };
    image.onerror = ()=>alert("読み込めませんでした");

    const reader = new FileReader();
    reader.onload = () => image.src = reader.result;

    document.getElementById(fileSelectId)
        .addEventListener("change",function(){
            reader.readAsDataURL(this.files[0])
        });

};
window.addEventListener( "DOMContentLoaded" , ()=>
    start("file_select","canvas","image")
);

imageオブジェクトの生成していた箇所を、既存のimgタグから取得するようにするだけで、ブラウザ上に表示してくれます。

 

サーバーから取得した画像データをCanvasに描画する

サーバー上にある画像を読み込んで、キャンバスに表示してみます。

HTML


<p><button id="button">画像取得</button></p>
<p><canvas id="canvas"></canvas></p>

JavaScript


const start = (buttonId,canvasId) =>{

    const canvas = document.getElementById(canvasId);
    const context = canvas.getContext("2d");

    const image = new Image();
    image.onload = ()=>{
        window.URL.revokeObjectURL(image.src);
        canvas.width = image.width;
        canvas.height = image.height;
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
    };
    image.onerror = ()=>alert("読み込めませんでした");

    document.getElementById(buttonId)
        .addEventListener("click",function(){
            fetch("https://○○○.com/image.jpg")
                .then(response => response.blob())
                .then(blob =>image.src = window.URL.createObjectURL(blob))
                .catch(error => console.error(error));
        });

};
window.addEventListener( "DOMContentLoaded" , ()=>
    start("button","canvas")
);

fetch()関数で画像データを取得したあと、blobに変換します。
その後blobをcreateObjectURL()でオブジェクトURLして、Imageオブジェクトのsrcにセットしています。

なお、異なるドメイン上の画像ファイルを読み込むときは、画像があるサーバーでAccess-Control-Allow-Originを設定する必要があります。
良く考えたら、fetch()使わないで、imageオブジェクトに直接画像URLを渡せばいいですね・・・

これでもよさそう


document.getElementById(buttonId)
    .addEventListener("click",function(){
        image.src = "https://○○○.com/image.jpg";
    });

更新日:2022/07/05

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。