Canvas drawImage size error
Asked Answered
T

1

2

I’m using two html canvas, the fronendCanvas is visible to the users and is part of the html DOM tree and is set to have 100% of the window width and height, the backendCanvas is created on the javascript code and is used to contain the huge diagram that I need to draw.

/** FrontendCanvas */
// HTML
<canvas id="canvas"></canvas> 

// JavaScript
frontCanvas.width = window.innerWidth;
frontCanvas.height = window.innerHeight;

// CSS
#canvas {
   display: block;
   background-color: #dddddd;
}

/** BackendCanvas */
// JavaScript
backCanvas = document.createElement('canvas');
backCanvas.width = diagram.maxX;
backCanvas.height = diagram.maxY;

Basically, to have a smooth visualisation the frontendCanvas only shows a part of the huge image drawn in the backendCanvas using the drawImage function (user can use the mouse to drag the visualisation area across the diagram, see the example Move HTML5 Canvas with a background image).

frontCanvas.getContext('2d').drawImage(
    backCanvas,
    (-ix - offsetX),
    (-iy - offsetY),
    (frontCanvas.width),
    (frontCanvas.height),
    0,
    0,
    (frontCanvas.width),
    (frontCanvas.height)
);

When I set the backendCanvas width and height to 15000 everything works fine, but when I set it to the size that I actually need, width 62322 and height 50946, somehow the drawImage doesn’t work any more and throws the size error:

IndexSizeError: Index or size is negative or greater than the allowed amount
(frontCanvas.height)

My guess would be that I’m reaching the maximum size of the canvas and it’s reseted, but it doesn’t seem the case because:

  1. the canvas reference says that the canvas width and height limit is an unsigned long, therefore much bigger than the numbers that I mentioned;

  2. I checked the size of the backendCanvas right before the drawImage function call and it is correct.

Any help would be very much appreciated!

Thanks.

Titre answered 8/8, 2013 at 9:21 Comment(2)
The last time I looked, the max canvas element size was well below 50946 (I vaguely remember Chrome had the largest allowable size at 32K+-). Anyway, just test it yourself by increasing the size of context.rect until you get an error. And, some math: 62322 x 50946 x 4 bytes per pixel is 12GB+ memory required.Mahican
I saw for instance here (whatwg.org/specs/web-apps/current-work/multipage/…) that the max value of width and height was an unsigned long, but indeed your calculations make perfect sense. So basically what I’m doing is infeasible… Maybe what I should do is something like draw if visible and call this every time the user pans the screen. Many thanks for the reply.Titre
C
2

Oo, those sizes (62322 x 50946) are way outside what you can use with canvas - even in 2013. ::-)

The max current supported size in the major browsers vary between some 6-15000 points depending on implementation (a few months back only 6-8000). It is related to actual need with most techniques as well as hardware acceleration, memory etc.

The raw size of the image you want to use is 11.83 GB (RGB + alpha as canvas uses RGBA only). In addition you will have to store the source image somewhere in memory before you can paint it to canvas which means you are up in 23+ GB memory usage even before the fun begin. This will force paging on most computers which will make everything very slow.

What you need to implement here is tiling/caching/buffering technique (think Google maps - this is why they tile their maps).

Describing this is perhaps a bit too broad for this Q&A site so I can also suggest you look at for example PanJS3 or Leaflet. Disclaimer: I don't know these libraries but you can at least study them to see how they deal with large images/maps.

Corey answered 8/8, 2013 at 15:25 Comment(1)
Indeed, I only realise now that is too big. Fortunately, what I have to draw is a network that I have stored in a very simple and light format. Basically, I use a similar method as here (#18058357) but instead of drawing all the network in the backgroundCanvas I simply check before drawing in the frontendCanvas which elements are visible directly in the file. This way I’m able of displaying the whole network by tweaking a little bit the panning feature. Many thanks to everyone and specially to you Ken.Titre

© 2022 - 2024 — McMap. All rights reserved.