Canvas画像処理

【JavaScript】 Canvas画像をPNG/JPEGに変換してバッファに格納

更新日:2024/02/27

あまり需要がなさそうですが、Canvas画像をPNGまたはJPEGに変換して、その結果をバッファに格納する方法をお伝えします。

 

toDataURL()でバッファに格納

一つ目はtoDataURL()を使う方法です。

次のコードは、引数として受け取ったCanvasの画像をJPEGに変換して、そのバイナリデータを格納したバッファを返しています。

const getJpegBinary = canvas =>{
    const dataURL = canvas.toDataURL("image/jpeg", 0.75);
    const imageBase64 = dataURL.split(',')[1];
    const decodeURL = atob( imageBase64 );
    const buffer = new Uint8Array(decodeURL.length);
    for( let i = 0 ; i < decodeURL.length ; i ++)
        buffer[i] = decodeURL.charCodeAt(i);
    return buffer;
}
  1. toDataURLを実行して、PNGまたはJPEGのデータURLを生成
  2. データURLから画像データのみを抜き出す
  3. atob()関数でbase64をバイナリに戻したものを、テキストとして取得
  4. 取得したテキストと同じサイズでUint8Arrayを確保
  5. テキストから一文字ずつ取り出して、Uint8Arrayにセット

①で生成されるデータURLは次のような形式になっています。

data:[タイプ];base64,[base64データ]
[タイプ]は、image/jpeg または image/png に置き換えられます。
[base64データ]は、PNGまたはJPEGのバイナリデータをBase64でテキストに変換したものです。

②は、データURLから ,(カンマ) 以降を抜き出しています。

③のatob()関数はbase64データをバイナリに戻して、テキストとして生成します。
※むりやりテキストにしただけなので、画面表示すると文字化けします。

base64は元となるバイナリデータよりも1.3~1.4倍程度大きくなります。
これは1文字1バイトで計算したときの値です。
JavaScriptは1文字2バイトなので、2.6倍にもなります。
意外と大きいですね。

 

toBlob()でバッファに格納

二つ目はtoBlob()を使う方法です。

const getJpegBinary =  (canvas) =>{
    return new Promise( resolve=>{
        canvas.toBlob( blob =>resolve(blob.arrayBuffer()),"image/jpeg",0.75);
    });
}

Promiseが好きな人でも頭痛がしそうなコードができました。

canvas.toBlob()は、canvasの画像をblobに変換して、その結果を第一引数のコールバック関数に渡します。

blob.arrayBuffer()は、blobが持っているバイナリデータをarrayBufferにコピーして、その結果をPromiseで通知します。

一連の処理に非同期処理がかかわってくるので、この関数はPromiseを生成して返しています。

なお、次のような感じで呼び出し側はthenを呼び出すなどの対応が必要です。

const yobidasigawa =  ()=>{
   … いろいろ処理
   getJpegBinary( canvas ).then( buffer => {
           // bufferの処理
    });
}

 

どちらを使うべきか

toDataURL()は少し非効率なのですが、わかりやすいですね。
toBlob()は非同期処理がかかわってくるので、少し複雑になります。

個人的には、どちらでもいいと思います。

 

保存するならtoBlob()を使う

バッファに格納するのではなくてPCやスマホに保存するのなら、toBlob()を使います。

詳しくは次のページをみてください!

更新日:2024/02/27

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

スポンサーリンク

記事の内容について

null

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

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

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

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

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

 

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