What is the difference between ImageBitmap and ImageData in JavaScript? when do you want the one or the other?
The ImageBitmap interface represents a bitmap image which can be drawn to a <canvas> without undue latency. It can be created from a variety of source objects using the createImageBitmap() factory method. ImageBitmap provides an asynchronous and resource efficient pathway to prepare textures for rendering in WebGL.
The ImageData interface represents the underlying pixel data of an area of a <canvas> element. It is created using the ImageData() constructor or creator methods on the CanvasRenderingContext2D object associated with a canvas: createImageData() and getImageData() .
To get the pixel of any specific portion from HTML canvas you can use the HTML canvas getImageData() Method. The getImageData() method usually returns an ImageData object that contains the pixel information of the specified object on the HTML canvas.
The getImageData() method returns an ImageData object that copies the pixel data for the specified rectangle on a canvas. Note: The ImageData object is not a picture, it specifies a part (rectangle) on the canvas, and holds information of every pixel inside that rectangle.
An ImageBitmap holds a reference to bitmap data, which can be passed to and stored directly in the GPU.
An ImageData holds a reference to a canvas pixel ArrayBuffer, which itself represents raw pixel values as an Array of un-premultiplied RGBA color channel values, which is only used by the CPU.
The former can be painted directly by the GPU, with no other operations required. The latter needs to be read (often with alpha pre-multiplication) then moved to the GPU before it can be painted.
They will not take the same amount of time to get copied to the canvas bitmap (a.k.a "painted").
var target = document.getElementById('target');
var ctx = target.getContext("2d");
var imageData = ctx.createImageData(300,150);
var imageBitmap = null;
// fill our ImageData with noise
const data = new Uint32Array(imageData.data.buffer);
for(let i=0; i<data.length; i++) {
data[i] = Math.random()*0xFFFFFF + 0xFF000000;
}
// initial draw
ctx.putImageData(imageData, 0,0);
// we create our ImageBitmap from the current state
// (=> ~ same bitmap as 'imageData')
createImageBitmap(target).then((bmp)=>{
imageBitmap = bmp;
btn.disabled = false;
});
// Benchmark.js playground borrowed from
// https://jsfiddle.net/533hc71h/
var test1_name = 'ImageData';
function test1()
{
ctx.putImageData(imageData, 0, 0);
}
var test2_name = 'ImageBitmap';
function test2()
{
ctx.drawImage(imageBitmap, 0, 0);
}
function teardown()
{
ctx.clearRect(0,0,target.width,target.height);
}
var cycleResults = document.getElementById('cycleResults');
var result = document.getElementById('result');
var btn = document.getElementById('btn');
// BENCHMARK ====================
btn.onclick = function runTests(){
btn.setAttribute('disable', true);
cycleResults.innerHTML = '';
result.textContent = 'Tests running...';
var suite = new Benchmark.Suite;
// add tests
suite
.add(test1_name || 'test1', test1)
.add(test2_name || 'test2', test2)
// add listeners
.on('cycle', function(event) {
var result = document.createElement('li');
result.textContent = String(event.target);
document.getElementById('cycleResults')
.appendChild(result);
})
.on('complete', function() {
result.textContent = 'Fastest is ' + this.filter('fastest').pluck('name');
btn.setAttribute('disable', false);
teardown();
})
// run async
.run({ 'async': true });
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<ul id='cycleResults'>
</ul>
<div id="result">
</div>
<br>
<button id="btn" disabled>
Run Tests
</button><br>
<canvas id="target"></canvas>
Running the above snippet I get around 5K OPS (Operations Per Seconds) for drawing the ImageData, and 200K+ for the ImageBitmap on Chrome (44K vs 125K in FF).
However you can't modify an ImageBitmap, nor read its content in any meaningful way.
So,
And remember that now we also have means to hold canvas contexts directly in a Worker thanks to the OffscreenCanvas API, might suit your needs too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With