I am trying to colorize a large image using a d3 interpolated color scheme and running into 2 issues:
unexpected factor of 2 rescaling
slow performance
Both issues are demonstrated in Colorize / David Kirkby / Observable where the image data transform is working correctly (except for the 2x rescaling), but too slow for my application which involves 6000x6000 images. Is there a different approach that would be faster? I do not need (or want) to display the large source image at all, so OffscreenCanvas looked promising but still experimental so not widely supported.
In case anyone lands here with a similar issue, I updated my simple example with @Fil’s suggestions and also replaced the ImageBitmap (which I discovered is not available on Safari) with an HTMLCanvasElement.
You can speed up things further by using a Uint32Array data view for your colors.
First, we create an array of all colors (your lookup table) as 32-bit values:
function getPalette(num, colorFn) {
const c = DOM.context2d(num, 1, 1);
for(let i = 0; i < num; i++) c.fillStyle = colorFn(i), c.fillRect(i, 0, 1, 1);
return new Uint32Array(c.getImageData(0, 0, num, 1).data.buffer);
}
then
colorized={
// [...]
// generate the colors
const LUT = getPalette(256, i => d3.color(interpolator(i / 255)));
// [...]
// create a 32-bit data view of your Uint8ClampedArray
const uint32 = new Uint32Array(imgData.data.buffer);
// lookup and assign colors for all values
for(let i = 0; i < uint32.length; i++) uint32[i] = LUT[imgData.data[i*4]];
// [...]
}