3

I am writing a data viz app that requires me to process very large 2D arrays of data and convert that data into a scaled down image for display in a canvas in the DOM.

I am bumping up against DOM canvas size limitations. My arrays can be as large as 5000 x 5000. I want to get around the canvas size limitation by using createImageBitmap() to simultaneously scale down and convert the large array to an ImageBitMap of smaller size - 256 x 256 - for insertion into an onscreen canvas.

How can I convert the raw array data into the proper format? Will this approach work?

dugla
  • 12,774
  • 26
  • 88
  • 136
  • what is the raw data that you have in your 2D array, can you elaborate on that? – 123survesh Sep 13 '19 at 14:44
  • It is a bit hard to isolate. My current approach is: 1) Draw array into OffScreenCanvas of identical size. 2) call drawImage() on the smaller destination canvas - 256 x 256 which performs both to minify and to copy. For an array large then about 4K x 4K the destination canvas is never written. No error. Below that size it works fine. – dugla Sep 13 '19 at 15:14
  • You could potentially reduce the data algorithmicly, it's a bit of a step away from what you currently have, but e.g. averaging each 2x2 block of pixels down to a single pixel worth of colour would quarter the number of pixels. – DBS Sep 13 '19 at 15:25
  • Yes I agree. The "proper" approach would be to downsample the array data and just hand it to the destination canvas. I am hoping to get "free" downsampling using imaging functionality rather then rolling my own, – dugla Sep 13 '19 at 15:26

1 Answers1

5

You can create and manipulate your image before rendering it to canvas. 5000x5000 shouldn't be too large for canvas though. What limitations are you running into? Answer here covers resizing as on canvas then grabbing data.

var raw = new Uint8ClampedArray(5000*5000*4); // 4 for RBGA
var imageData = new ImageData(raw, 5000,5000);
var bitmap = createImageBitmap(imageData);
Gavin
  • 2,214
  • 2
  • 18
  • 26
  • Nice. I'll give it a try. – dugla Sep 13 '19 at 15:15
  • Works great. Cheers. – dugla Sep 13 '19 at 20:29
  • And orders of magnitude faster than using drawImage(). Wow! – dugla Sep 13 '19 at 20:29
  • Just a note, ImageData constructor has [the same size limits](https://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element) than HTMLCanvasElement. So indeed for 5K*5K it should be ok, and even a good alternative, but the question asked about working around these limits, and this solution won't do. cc @dugla – Kaiido Sep 14 '19 at 02:34
  • Good to know Kaido. You are correct, it is still an open question why my original implementation was not working. For one of the user's of my app their browser - Chrome I believe - crashed. With Gavin's approach speed is up 20x - on the down sampling - and mems usage is way down. – dugla Sep 16 '19 at 14:05