Maximum size of a <canvas> element
Asked Answered
C

14

135

I'm working with a canvas element with a height of 600 to 1000 pixels and a width of several tens or hundreds of thousands of pixels. However, after a certain number of pixels (obviously unknown), the canvas no longer display shapes I draw with JS.

Does anyone know if there's a limit?

Tested both in Chrome 12 and Firefox 4.

Clubfoot answered 21/5, 2011 at 11:40 Comment(7)
@Šime He said tens OR hundreds of thousands...Erubescent
I experience this too. I have an 8000x8000 canvas which works ok, but when I make it bigger the content disappears and it just won't draw. The size that it fails to work at is a lot lower on my iPad. I wonder if its a memory limitation of some sort.Kainite
It's weird when you find your own comment from 2 years earlier and you are still dealing with the same darn problem.Kainite
@Kainite and still a year later!Weigand
FWIW, based on the answers, since one dimension was reasonably small, it likely broke when the larger dimension exceeded 32767. (Unless viewing on a mobile device, where smaller limits apply.)Upstanding
The question is how do I catch these errors, or better warnings, which is what they are? I can't detect the devices hardware, so I have to react to an error.Commination
So pretty much a safe value is 4096 * 4096 anything over that is asking for trouble on mobile devicesIrate
C
141

Updated 10/13/2014

All tested browsers have limits to the height/width of canvas elements, but many browsers also limit the total area of the canvas element. The limits are as follows for the browsers I'm able to test:

Chrome:

Maximum height/width: 32,767 pixels
Maximum area: 268,435,456 pixels (e.g., 16,384 x 16,384)

Firefox:

Maximum height/width: 32,767 pixels
Maximum area: 472,907,776 pixels (e.g., 22,528 x 20,992)

IE:

Maximum height/width: 8,192 pixels
Maximum area: N/A

IE Mobile:

Maximum height/width: 4,096 pixels
Maximum area: N/A

Other:

I'm not able to test other browsers at this time. Refer to the other answers on this page for additional limits.


Exceeding the maximum length/width/area on most browsers renders the canvas unusable. (It will ignore any draw commands, even in the usable area.) IE and IE Mobile will honor all draw commands within the usable space.

Contort answered 20/7, 2012 at 19:39 Comment(19)
So, related question...how does one work around the limit if they need a canvas that is larger than the allowed maximum?Tramway
@aroth, I ended up writing a wrapper around the canvas API that used multiple stacked <canvas> elements and automatically applied drawing instructions to the appropriate context.Contort
Sounds very useful. Don't suppose it's on github?Tramway
Sadly, I wrote the code as a contractor over two years ago and the site is no longer live. Even if I could track down the code, I wouldn't have a license to share it.Contort
Safari (non-iOS version) uses 32K like Chrome.Firefox. Also, if you'd like to try to recreate some of that wrapper code, I started an open-source version of my own thanks to IE's paltry 8K limit: github.com/adam-roth/wrapped-canvasTramway
@BrandonGano how do you determine maximum area? I'm trying to evaluate if my animation that has multiple elements staged from offscreen and then animated in could be running up against that limit.Neese
I used trial and error to determine these limits. (i.e., Create a very large canvas and see if you can draw in the bottom right corner. If not, decrease the size until you can. If so, increase the size until you can't.)Contort
iOS 9.3.1 Safari on an iPhone 6 Plus is limited to an area of 16777216 pixels (for example, 4096 x 4096). I suspect this is a common number across newer iOS devicesBrookner
@BrandonGano what would you do with those stacked canvas elements if you want to export the result?Aerification
@jayarjo: One option would be to call toDataURL() on each of the canvases and send them all to the server via AJAX. On the server, you'd need to figure out a way to join the image data and return it as a single image. It sounds like a fun project if you're getting paid. :)Contort
IE 11 now has a max canvas width/height of 16384 from my testing.Fresh
Is this answer still relevant for Chrome 63? @BrandonGanoVocoid
I'm not sure, @Tlatis. I haven't had a need to test this since the last update to this post a few years back. There are a couple answers here that provide programmatic ways to determine the maximum on a given browser. I'd recommend using one of those on the latest version of Chrome.Contort
How did you test? My own empirical tests of filling a canvas with random RGB data seem to indicate that Firefox (at least as of 57.0.4 on Windows x64) doesn't seem to handle canvases with height >= 8192 pixels and just duplicates the last row.Glengarry
Not sure if this is true but it seems like recent Chrome versions (post 60 for example) are making the max canvas size even smaller. Haven't run tests to confirmCottontail
There is, at the very least, some activity related to this issue on chrome/skia bug tracker bugs.chromium.org/p/skia/issues/detail?id=2122 bugs.chromium.org/p/chromium/issues/detail?id=339725Cottontail
There may be lower limits depending (I suspect) on the size of your RAM. On my laptop with 4GB of RAM, I hit limits lower than the ones above. Firefox will handle 12500x10000 (125,000,000) but not 12500x10001 (125,012,500).Monto
(Chrome on the same machine is exactly as described above.)Monto
See my answer below for a 2018 update. Included are links to a library used to determine canvas size limitations and up to date area, height, and width limits for a wider range of browsers/platforms.Harrelson
H
33

The accepted answer is outdated and incomplete.

Browsers impose different canvas size limitations, but these limitations often change based on the platform and hardware available. This makes it difficult to make statements like "the maximum canvas [area/height/width] of [browser] is [value]" because [value] can change based the operating system, available RAM, or GPU type.

There are two approaches to working with large HTML <canvas> elements:

  1. Limit canvas dimensions to those known to work on all supported platforms.
  2. Programmatically determine canvas limitations on the client before rendering.

Those looking to programmatically determine canvas limitations on the client should consider using canvas-size.

From the docs:

The HTML canvas element is widely supported by modern and legacy browsers, but each browser and platform combination imposes unique size limitations that will render a canvas unusable when exceeded. Unfortunately, browsers do not provide a way to determine what their limitations are, nor do they provide any kind of feedback after an unusable canvas has been created. This makes working with large canvas elements a challenge, especially for applications that support a variety of browsers and platforms.

This micro-library provides the maximum area, height, and width of an HTML canvas element supported by the browser as well as the ability to test custom canvas dimensions. By collecting this information before a new canvas element is created, applications are able to reliably set canvas dimensions within the size limitations of each browser/platform.

Test results for a variety of platform and browser combinations are available here:

Full disclosure, I am the author of the library. I created it back in 2014 and recently revisited the code for a new canvas-related project. I was surprised to find the same lack of available tools for detecting canvas size limitations in 2018 so I updated code, released it, and hope it helps others running into similar issues.

Harrelson answered 7/12, 2018 at 22:23 Comment(0)
C
16

I've ran into out of memory errors on Firefox with canvas heights greater than 8000, chrome seems to handle much higher, at least to 32000.

EDIT: After running some more tests, I've found some very strange errors with Firefox 16.0.2.

First, I seem to get different behavior from in memory (created in javascript) canvas as opposed to html declared canvas.

Second, if you don't have the proper html tag and meta charset, the canvas might be restricted to 8196, otherwise you can go up to 32767.

Third, if you get the 2d context of the canvas and then change the canvas size, you might be restricted to 8196 as well. Simply setting the canvas size before grabbing the 2d context allows you to have up to 32767 without getting memory errors.

I haven't been able to consistently get the memory errors, sometimes it's only on the first page load, and then subsequent height changes work. This is the html file I was testing with http://pastebin.com/zK8nZxdE.

Cora answered 2/11, 2012 at 15:55 Comment(2)
"Second, if you don't have the proper html tag and meta charset, the canvas might be restricted to 8196, otherwise you can go up to 32767" - what do you mean by proper html tag and meta charset here?Oscilloscope
Surely you mean 8192 (2^13)? 8196 is a weird number.Glengarry
L
14

iOS max canvas size (width x height):

 iPod Touch 16GB = 1448x1448
 iPad Mini       = 2290x2289
 iPhone 3        = 1448x1448
 iPhone 5        = 2290x2289

tested on march 2014.

Linc answered 12/3, 2014 at 8:27 Comment(1)
These values are arbitrary. Please see my post below which references the safari's content guideAnnatto
A
12

To expand a bit on @FredericCharette answer: As per safari's content guide under section "Know iOS Resource Limits":

The maximum size for a canvas element is 3 megapixels for devices with less than 256 MB RAM and 5 megapixels for devices with greater or equal than 256 MB RAM

Therefore, any size variation of 5242880 (5 x 1024 x 1024) pixels will work on large memory devices, otherwise it's 3145728 pixels.

Example for 5 megapixel canvas (width x height):

Any total <= 5242880
--------------------
5 x 1048576 ~= 5MP   (1048576 = 1024 x 1024)
50 x 104857 ~= 5MP
500 x 10485 ~= 5MP

and so on..

The largest SQUARE canvases are ("MiB" = 1024x1024 Bytes):

device < 256 MiB   device >= 256 MiB   iPhone 6 [not confirmed]
-----------------  -----------------   ---------------------
<= 3145728 pixels  <= 5242880 pixels   <= 16 x 1024 x 1024 p
1773 x 1773        2289 x 2289         4096 x 4096
Annatto answered 30/4, 2014 at 15:2 Comment(3)
To be more specific, the iPhone5 limit is 3 * 1024 * 1024 = 3145728 pixels. (After wondering why my canvas was fine on Android but blank on iOS, I found this answer, and also #12556698 and got my Phonegap app working.)Disraeli
FYI, Apple has removed specific size info from "Safari / Know iOS Resource Limits". Now it is merely generic advice about minimizing bandwidth by using small images.Upstanding
@Brookner reported in a comment on the question that iPhone 6 appears to have limit 16 * 1024 * 1024.Upstanding
A
8

According to w3 specs, the width/height interface is an unsigned long - so 0 to 4,294,967,295 (if I remember that number right -- might be off a few).

EDIT: Strangely, it says unsigned long, but it testing shows just a normal long value as the max: 2147483647. Jsfiddle - 47 works but up to 48 and it reverts back to default.

Ayeaye answered 21/5, 2011 at 11:47 Comment(2)
Hmm. Interesting, but I don't even get to 1.5 billion.Clubfoot
Edited, sorry (thats what I get for not testing first) -- added a jsfiddle to show.Ayeaye
E
7

Even though the canvas will allow you to put height=2147483647, when you start drawing, nothing will happen

Drawing happens only when I bring the height back to 32767

Envisage answered 19/7, 2013 at 19:57 Comment(0)
T
7

iOS has different limits.

Using the iOS 7 simulator I was able to demonstrate the limit is 5MB like this:

var canvas = document.createElement('canvas');
canvas.width = 1024 * 5;
canvas.height = 1024;
alert(canvas.toDataURL('image/jpeg').length);
// prints "110087" - the expected length of the dataURL

but if I nudge the canvas size up by a single row of pixels:

var canvas = document.createElement('canvas');
canvas.width = 1024 * 5;
canvas.height = 1025;
alert(canvas.toDataURL('image/jpeg'));
// prints "data:," - a broken dataURL
Trinitarianism answered 18/9, 2014 at 17:34 Comment(1)
You should not base such data on the iOS simulator.Sitar
J
5

On PC-
I don't think there is a restriction but yes you can get out of memory exception.

On Mobile devices-
Here is the restrictions for the canvas for mobile devices:-

The maximum size for a canvas element is 3 megapixels for devices with less than 256 MB RAM and 5 megapixels for devices with greater or equal than 256 MB RAM.

So for example - if you want to support Apple’s older hardware, the size of your canvas cannot exceed 2048×1464.

Hope these resources will help you to pull you out.

Jevon answered 13/5, 2014 at 13:11 Comment(0)
C
4

When you are using WebGL canvases, the browsers (including the desktop ones) will impose extra limits on the size of the underlying buffer. Even if your canvas is big, e.g. 16,000x16,000, most browsers will render a smaller (let's say 4096x4096) picture, and scale it up. That might cause ugly pixelating, etc.

I have written some code to determine that maximum size using exponential search, if anyone ever needs it. determineMaxCanvasSize() is the function you are interested in.

function makeGLCanvas()
{
    // Get A WebGL context
    var canvas = document.createElement('canvas');
    var contextNames = ["webgl", "experimental-webgl"];
    var gl = null;
    for (var i = 0; i < contextNames.length; ++i)
    {
        try
        {
            gl = canvas.getContext(contextNames[i], {
                // Used so that the buffer contains valid information, and bytes can
                // be retrieved from it. Otherwise, WebGL will switch to the back buffer
                preserveDrawingBuffer: true
            });
        }
        catch(e) {}
        if (gl != null)
        {
            break;
        }
    }
    if (gl == null)
    {
        alert("WebGL not supported.\nGlobus won't work\nTry using browsers such as Mozilla " +
            "Firefox, Google Chrome or Opera");
        // TODO: Expecting that the canvas will be collected. If that is not the case, it will
        // need to be destroyed somehow.
        return;
    }

    return [canvas, gl];
}

// From Wikipedia
function gcd(a,b) {
    a = Math.abs(a);
    b = Math.abs(b);
    if (b > a) {var temp = a; a = b; b = temp;}
    while (true) {
        if (b == 0) return a;
        a %= b;
        if (a == 0) return b;
        b %= a;
    }
}

function isGlContextFillingTheCanvas(gl) {
    return gl.canvas.width == gl.drawingBufferWidth && gl.canvas.height == gl.drawingBufferHeight;
}

// (See issue #2) All browsers reduce the size of the WebGL draw buffer for large canvases 
// (usually over 4096px in width or height). This function uses a varian of binary search to
// find the maximum size for a canvas given the provided x to y size ratio.
//
// To produce exact results, this function expects an integer ratio. The ratio will be equal to:
// xRatio/yRatio.
function determineMaxCanvasSize(xRatio, yRatio) {
    // This function works experimentally, by creating an actual canvas and finding the maximum
    // value, the browser allows.
    [canvas, gl] = makeGLCanvas();

    // Reduce the ratio to minimum
    gcdOfRatios = gcd(xRatio, yRatio);
    [xRatio, yRatio] = [xRatio/gcdOfRatios, yRatio/gcdOfRatios];

    // if the browser cannot handle the minimum ratio, there is not much we can do
    canvas.width = xRatio;
    canvas.height = yRatio;

    if (!isGlContextFillingTheCanvas(gl)) {
        throw "The browser is unable to use WebGL canvases with the specified ratio: " + 
            xRatio + ":" + yRatio;
    }

    // First find an upper bound
    var ratioMultiple = 1;  // to maintain the exact ratio, we will keep the multiplyer that
                            // resulted in the upper bound for the canvas size
    while (isGlContextFillingTheCanvas(gl)) {
        canvas.width *= 2;
        canvas.height *= 2;
        ratioMultiple *= 2;
    }

    // Search with minVal inclusive, maxVal exclusive
    function binarySearch(minVal, maxVal) {
        if (minVal == maxVal) {
            return minVal;
        }

        middle = Math.floor((maxVal - minVal)/2) + minVal;

        canvas.width = middle * xRatio;
        canvas.height = middle * yRatio;

        if (isGlContextFillingTheCanvas(gl)) {
            return binarySearch(middle + 1, maxVal);
        } else {
            return binarySearch(minVal, middle);
        }
    }

    ratioMultiple = binarySearch(1, ratioMultiple);
    return [xRatio * ratioMultiple, yRatio * ratioMultiple];
}

Also in a jsfiddle https://jsfiddle.net/1sh47wfk/1/

Cauliflower answered 24/3, 2018 at 6:29 Comment(2)
Is there any official documentation on the scaling-up behavior?Materialism
@MagnusLindOxlund The information from the answer has been determined experimentally. The closest thing I found after a quick search is this: khronos.org/registry/webgl/specs/latest/1.0/#2.2, saying: "The constraint above does not change the amount of space the canvas element consumes on the web page" when it talks about limiting the size of the drawing buffer. It seems that the WebGL standard does not go into crazy detail about how the canvas element is supposed to display the drawing buffer.Gaudy
P
3

The limitations for Safari (all platforms) are much lower.

Known iOS/Safari Limitations

For example, I had a 6400x6400px canvas buffer with data drawn onto it. By tracing/ exporting the content and by testing on other browsers, I was able to see that everything was fine. But on Safari, it would skip the drawing of this specific buffer onto my main context.

Praemunire answered 21/8, 2013 at 19:44 Comment(2)
Yeep! Safari skips drawing your canvas because you use bigger canvas as "allowed". See max dimensions i've posted above! That's max. canvas on this safari/devices.Linc
Your sizes are pretty arbitrary, aren't they ? Do you have any documentation ? What was your testing process ?Praemunire
L
3

I tried to programmatically figure out the limit: setting canvas size starting from 35000, stepping down by 100 until valid size is found. In every step writing the right-bottom pixel and then reading it. It works - with caution.

The speed is acceptable if either width or height is set to some low value (eg. 10-200) this way: get_max_canvas_size('height', 20).

But if called without width or height like get_max_canvas_size(), the created canvas is so big that reading SINGLE pixel color is very slow, and in IE causes serious hang.

If this like test could be done someway without reading pixel value, the speed would be acceptable.

Of course the easiest way to detect maximum size would be some native way to query the max width and height. But Canvas is 'a living standard', so may be it is coming some day.

http://jsfiddle.net/timo2012/tcg6363r/2/ (Be aware! Your browser may hang!)

if (!Date.now)
{
  Date.now = function now()
  {
    return new Date().getTime();
  };
}

var t0 = Date.now();
//var size = get_max_canvas_size('width', 200);
var size = get_max_canvas_size('height', 20);
//var size = get_max_canvas_size();
var t1 = Date.now();
var c = size.canvas;
delete size.canvas;
$('body').append('time: ' + (t1 - t0) + '<br>max size:' + JSON.stringify(size) + '<br>');
//$('body').append(c);

function get_max_canvas_size(h_or_w, _size)
{
  var c = document.createElement('canvas');
  if (h_or_w == 'height') h = _size;
  else if (h_or_w == 'width') w = _size;
  else if (h_or_w && h_or_w !== 'width' && h_or_w !== 'height' || !window.CanvasRenderingContext2D)
    return {
      width: null,
      height: null
    };
  var w, h;
  var size = 35000;
  var cnt = 0;
  if (h_or_w == 'height') w = size;
  else if (h_or_w == 'width') h = size;
  else
  {
    w = size;
    h = size;
  }

  if (!valid(w, h))
    for (; size > 10; size -= 100)
    {
      cnt++;
      if (h_or_w == 'height') w = size;
      else if (h_or_w == 'width') h = size;
      else
      {
        w = size;
        h = size;
      }
      if (valid(w, h)) break;
    }
  return {
    width: w,
    height: h,
    iterations: cnt,
    canvas: c
  };

  function valid(w, h)
  {
    var t0 = Date.now();
    var color, p, ctx;
    c.width = w;
    c.height = h;
    if (c && c.getContext)
      ctx = c.getContext("2d");
    if (ctx)
    {
      ctx.fillStyle = "#ff0000";
      try
      {
        ctx.fillRect(w - 1, h - 1, 1, 1);
        p = ctx.getImageData(w - 1, h - 1, 1, 1).data;
      }
      catch (err)
      {
        console.log('err');
      }

      if (p)
        color = p[0] + '' + p[1] + '' + p[2];
    }
    var t1 = Date.now();

    if (color == '25500')
    {
      console.log(w, h, true, t1 - t0);
      return true;
    }
    console.log(w, h, false, t1 - t0);
    return false;
  }
}
Langouste answered 2/6, 2015 at 5:15 Comment(3)
This would be greatly optimised by using en.wikipedia.org/wiki/Exponential_searchExsect
It is really insane that the failure of creating a canvas this large is silent so there is no way to detect...not bad by any means on your part, it's just a crazy thing for browsers to spring on usCottontail
@ColinD I agree. It would be just one little piece of information somewhere. It would. And should.Sincerity
H
1

You could chunk it and in javascript auto add as many smaller canvases as needed and draw the elements on the appropriate canvas. You may still run out of memory eventually but would get you by the single canvas limit.

Hypha answered 3/6, 2015 at 18:52 Comment(0)
M
0

I don't know how to detect the max possible size without itteration, but you can detect if a given canvas size works by filling a pixel and then reading the colour back out. If the canvas has not rendered then the color you get back will not match. W

partial code:

function rgbToHex(r, g, b) {
    if (r > 255 || g > 255 || b > 255)
        throw "Invalid color component";
    return ((r << 16) | (g << 8) | b).toString(16);
}
var test_colour = '8ed6ff';
working_context.fillStyle = '#' + test_colour;
working_context.fillRect(0,0,1,1);
var colour_data = working_context.getImageData(0, 0, 1, 1).data;
var colour_hex = ("000000" + rgbToHex(colour_data[0], colour_data[1], colour_data[2])).slice(-6);
Mither answered 26/10, 2015 at 16:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.