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, aft
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.
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
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
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
iOS max canvas size (width x height):
iPod Touch 16GB = 1448x1448
iPad Mini = 2290x2289
iPhone 3 = 1448x1448
iPhone 5 = 2290x2289
tested on march 2014.
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;
}
}