JavaScript の Canvas で画像を扱うとき、ImageBitmap
にすることで描画の遅延を減らすことができます。
ただし、ImageBitmap
はメモリ消費が大きい場合があるため、注意が必要です (※具体的な扱い方は後述) 。
ImageData
は CORS によって取得できないことがありますが、ImageBitmap
は取得できます。
参考「ImageBitmap - Web API | MDN」
参考「OffscreenCanvas: transferToImageBitmap() method - Web APIs | MDN」
1. 生成
1.1. createImageBitmap()
関数
一般的な画像ソースから ImageBitmap
を生成するには createImageBitmap()
関数を用います。
const offscreenCanvas = new OffscreenCanvas(300, 150);
// ...
const imageBitmap = await createImageBitmap(offscreenCanvas);
const canvas = document.createElement('canvas');
// ...
const imageBitmap = await createImageBitmap(canvas);
※他にも createImageBitmap()
関数が使える型があります。
位置や大きさ等を指定することもできます。
const offscreenCanvas = new OffscreenCanvas(300, 150);
// ...
const imageBitmap = await createImageBitmap(offscreenCanvas, 100, 0, 100, 75);
※他の操作に関しては公式ドキュメント等参照。
参考「createImageBitmap() - Web API | MDN」
1.2. transferToImageBitmap()
メソッド
OffscreenCanvas
から ImageBitmap
を取得して OffscreenCanvas
を初期化するには transferToImageBitmap()
メソッドを用います。
const offscreenCanvas = new OffscreenCanvas(300, 150);
// ...
const imageBitmap = offscreenCanvas.transferToImageBitmap();
参考「OffscreenCanvas: transferToImageBitmap() method - Web APIs | MDN」
※後述する transferFromImageBitmap()
メソッドは transferToImageBitmap()
メソッドと異なり、通常の HTMLCanvasElement
でも使用可能です。
※ transferToImageBitmap()
は OffscreenCanvas
型のメソッドですが、transferFromImageBitmap()
は ImageBitmapRenderingContext
型のメソッドです。
1.3. createImageBitmap()
関数と transferToImageBitmap()
メソッドの違い
OffscreenCanvas
に関しては createImageBitmap()
関数でも transferToImageBitmap()
メソッドでも ImageBitmap
を得ることができますが、以下の表のような違いがあります。
createImageBitmap() 関数 |
transferToImageBitmap() メソッド |
|
---|---|---|
画像ソースの型 |
HTMLImageElement SVGImageElement HTMLVideoElement HTMLCanvasElement Blob ImageData ImageBitmap OffscreenCanvas
|
OffscreenCanvas |
画像ソースの扱い | そのまま | 初期化 |
位置や大きさ等を指定 | 可 | 不可 |
処理方法 | 非同期 | 同期 |
2. 描画および破棄
2.1. transferFromImageBitmap()
メソッド
HTMLCanvasElement
または OffscreenCanvas
に ImageBitmap
全体を描画して ImageBitmap
を破棄するには transferFromImageBitmap()
メソッドを用います。
const context = canvas.getContext('bitmaprenderer');
context.transferFromImageBitmap(imageBitmap);
const offscreenContext = offscreenCanvas.getContext('bitmaprenderer');
offscreenContext.transferFromImageBitmap(imageBitmap);
ちなみに、Canvas と大きさが一致しない ImageBitmap
を transferFromImageBitmap()
メソッドで描画すると内部的には ImageBitmap
の大きさで扱われますが、Canvas の width
および height
は更新されないため注意が必要です。
//
const offscreenCanvasA = new OffscreenCanvas(300, 300);
const imageBitmapA = await createImageBitmap(offscreenCanvasA);
console.log(imageBitmapA.width, imageBitmapA.height);
//
const offscreenCanvasB = new OffscreenCanvas(300, 150);
const offscreenContextB = offscreenCanvasB.getContext('bitmaprenderer');
offscreenContextB.transferFromImageBitmap(imageBitmapA);
console.log(offscreenCanvasB.width, offscreenCanvasB.height);
const imageBitmapB = await createImageBitmap(offscreenCanvasB);
console.log(imageBitmapB.width, imageBitmapB.height);
300 300
300 150
300 300
※ transferFromImageBitmap()
メソッドは transferToImageBitmap()
メソッドと異なり、通常の HTMLCanvasElement
でも使用可能です。
※ transferToImageBitmap()
は OffscreenCanvas
型のメソッドですが、transferFromImageBitmap()
は ImageBitmapRenderingContext
型のメソッドです。
参考「ImageBitmapRenderingContext: transferFromImageBitmap() method - Web APIs | MDN」
2.2. close()
メソッド
drawImage()
メソッド等、transferFromImageBitmap()
メソッド以外でも ImageBitmap
を描画することができますが、その場合は ImageBitmap
が破棄されないため、close()
メソッドを呼ぶことで明示的に破棄します。
const context = canvas.getContext('2d');
context.drawImage(imageBitmap, 0, 0);
imageBitmap.close();
const offscreenContext = offscreenCanvas.getContext('2d');
offscreenContext.drawImage(imageBitmap, 0, 0);
imageBitmap.close();
参考「CanvasRenderingContext2D: drawImage() メソッド - Web API | MDN」
参考「WebGLRenderingContext: texImage2D() method - Web APIs | MDN」
参考「ImageBitmap.close() - Web API | MDN」
2.3. transferFromImageBitmap()
メソッドと drawImage()
メソッドの違い
transferFromImageBitmap()
メソッドでも drawImage()
メソッドでも ImageBitmap
を描画することができますが、以下の表のような違いがあります。
transferFromImageBitmap() メソッド |
drawImage() メソッド |
|
---|---|---|
Context の型 | ImageBitmapRenderingContext |
CanvasRenderingContext2D |
画像ソースの型 | ImageBitmap |
HTMLImageElement SVGImageElement HTMLVideoElement HTMLCanvasElement ImageBitmap OffscreenCanvas VideoFrame
|
画像ソースの扱い | 破棄 | そのまま |
位置や大きさ等を指定 | 不可 | 可 |
3. ImageBitmap
を使うべきでない状況
頻繁に ImageBitmap
を生成しつつ drawImage()
メソッドで描画するような使い方だと ImageBitmap
の恩恵を得にくいため、直接 Canvas を drawImage()
メソッドで描画した方が良いです。
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const offscreenCanvas = new OffscreenCanvas(300, 150);
// ...
context.drawImage(offscreenCanvas, 0, 0);
参考「CanvasRenderingContext2D: drawImage() メソッド - Web API | MDN」
参考「WebGLRenderingContext: texImage2D() method - Web APIs | MDN」