<canvas> 요소의 최대 크기


112

높이 6001000픽셀이고 너비가 수만 또는 수십만 픽셀 인 캔버스 요소로 작업하고 있습니다. 그러나 특정 픽셀 수 (분명히 알려지지 않음)가 지나면 캔버스에 JS로 그린 모양이 더 이상 표시되지 않습니다.

제한이 있는지 아는 사람이 있습니까?

Chrome 12 및 Firefox 4에서 모두 테스트되었습니다.


2
@ Šime 그는 말했다 tens OR hundreds of thousands...
Tadeck

6
나도 이것을 경험한다. 제대로 작동하는 8000x8000 캔버스가 있지만 더 크게 만들면 내용이 사라지고 그림이 그려지지 않습니다. 작동하지 않는 크기는 iPad에서 훨씬 더 작습니다. 나는 그것이 일종의 메모리 제한인지 궁금합니다.
여호수아

28
2 년 전에 자신의 의견을 발견하고 여전히 동일한 문제를 다루고있는 것은 이상합니다.
여호수아

4
@Joshua와 여전히 1 년 후!
Eugene Yu

1
문제는 이러한 오류 또는 더 나은 경고를 어떻게 포착합니까? 장치 하드웨어를 감지 할 수 없어서 오류에 대응해야합니다.
br4nnigan

답변:


115

2014 년 10 월 13 일 업데이트 됨

테스트 된 모든 브라우저에는 캔버스 요소의 높이 / 너비에 대한 제한이 있지만 많은 브라우저는 캔버스 요소의 전체 영역도 제한합니다. 테스트 할 수있는 브라우저에 대한 제한은 다음과 같습니다.

크롬:

최대 높이 / 너비 : 32,767 픽셀
최대 영역 : 268,435,456 픽셀 (예 : 16,384 x 16,384)

Firefox :

최대 높이 / 너비 : 32,767 픽셀
최대 영역 : 472,907,776 픽셀 (예 : 22,528 x 20,992)

IE :

최대 높이 / 너비 : 8,192 픽셀
최대 영역 : N / A

IE 모바일 :

최대 높이 / 너비 : 4,096 픽셀
최대 영역 : N / A

다른:

지금은 다른 브라우저를 테스트 할 수 없습니다. 추가 제한 사항은이 페이지의 다른 답변을 참조하십시오.


대부분의 브라우저에서 최대 길이 / 너비 / 영역을 초과하면 캔버스를 사용할 수 없게됩니다. (사용 가능한 영역에서도 그리기 명령을 무시합니다.) IE 및 IE Mobile은 사용 가능한 공간 내의 모든 그리기 명령을 준수합니다.


3
따라서 관련 질문 ... 허용 된 최대 값보다 큰 캔버스가 필요한 경우 제한을 어떻게 해결합니까?
aroth

2
@aroth, 나는 여러 스택 <canvas>요소 를 사용 하고 적절한 컨텍스트에 자동으로 그리기 지침을 적용 하는 캔버스 API 주위에 래퍼를 작성했습니다 .
Brandon Gano 2014

1
매우 유용하게 들립니다. github에 있다고 생각하지 않습니까?
aroth

5
Safari (비 iOS 버전)는 Chrome.Firefox와 같은 32K를 사용합니다. 또한 래퍼 코드 중 일부를 다시 만들고 싶다면
aroth

7
iPhone 6 Plus의 iOS 9.3.1 Safari는 16777216 픽셀 (예 : 4096 x 4096)의 영역으로 제한됩니다. 나는이 새로운 iOS 기기에서 공통의 번호입니다 의심
matb33

16

캔버스 높이가 8000보다 큰 Firefox에서 메모리 부족 오류가 발생했습니다. 크롬은 최소한 32000까지 훨씬 더 높은 수준으로 처리하는 것 같습니다.

편집 : 더 많은 테스트를 실행 한 후 Firefox 16.0.2에서 매우 이상한 오류를 발견했습니다.

첫째, html 선언 캔버스와 달리 메모리 (자바 스크립트로 생성) 캔버스에서 다른 동작을 얻는 것 같습니다.

둘째, 적절한 html 태그와 메타 문자 세트가 없으면 캔버스가 8196으로 제한 될 수 있으며 그렇지 않으면 32767까지 이동할 수 있습니다.

셋째, 캔버스의 2d 컨텍스트를 얻은 다음 캔버스 크기를 변경하면 8196으로 제한 될 수도 있습니다. 2d 컨텍스트를 잡기 전에 캔버스 크기를 설정하기 만하면 메모리 오류없이 최대 32767을 가질 수 있습니다.

일관되게 메모리 오류를 얻을 수 없었으며 때로는 첫 번째 페이지로드에서만 발생하고 후속 높이 변경이 작동합니다. 이것은 http://pastebin.com/zK8nZxdE 로 테스트 한 html 파일 입니다.


4
"둘째, 적절한 html 태그와 메타 문자 세트가 없으면 캔버스가 8196으로 제한 될 수 있습니다. 그렇지 않으면 32767까지 올라갈 수 있습니다."-여기서 적절한 html 태그와 메타 문자 세트는 무엇을 의미합니까?
Jack Aidley

확실히 8192 (2 ^ 13)를 의미합니까? 8196은 이상한 숫자입니다.
jamesdlin

14

iOS 최대 캔버스 크기 (너비 x 높이) :

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

2014 년 3 월에 테스트되었습니다.


이러한 값은 임의적입니다. 사파리의 내용 가이드가있는 참조 아래에 내 게시물을 참조하시기 바랍니다
dcbarans

11

@FredericCharette 답변에 대해 조금 확장하려면 : "iOS 리소스 제한 이해"섹션 아래에있는 safari의 콘텐츠 가이드에 따라 :

캔버스 요소의 최대 크기는 RAM이 256MB 미만인 장치의 경우 3 메가 픽셀이고 RAM이 256MB 이상인 장치의 경우 5 메가 픽셀입니다.

따라서 5242880 (5 x 1024 x 1024) 픽셀의 모든 크기 변형은 대용량 메모리 장치에서 작동하고 그렇지 않으면 3145728 픽셀입니다.

5 메가 픽셀 캔버스의 예 (너비 x 높이) :

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

등등..

가장 큰 SQUARE 캔버스는 ( "MiB"= 1024x1024 바이트)입니다.

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

1
보다 구체적으로 iPhone5 제한은 3 * 1024 * 1024 = 3145728 픽셀입니다. (내 캔버스가 iOS에서 안드로이드에 잘하지만 빈은 왜 궁금 후, 나는이 대답을 발견하고, 또한 stackoverflow.com/questions/12556198/... 내 폰갭 앱 작업을 얻었다.)
매그너스 스미스

참고로 Apple은 "Safari / Know iOS Resource Limits"에서 특정 크기 정보를 제거했습니다. 이제 작은 이미지를 사용하여 대역폭을 최소화하는 것에 대한 일반적인 조언 일뿐입니다.
ToolmakerSteve 2017 년

@ matb33은 iPhone 6의 제한이 16 * 1024 * 1024 인 것으로 보이는 질문에 대한 의견에서보고했습니다.
ToolmakerSteve 2017 년

11

2018 년 업데이트 :

시간이 지남에 따라 캔버스 제한이 변경되었습니다. 안타깝게도 변경되지 않은 것은 브라우저가 여전히 Canvas API를 통해 캔버스 크기 제한에 대한 정보를 제공하지 않는다는 사실입니다.

프로그래밍 방식으로 브라우저의 최대 캔버스 크기를 결정하거나 사용자 정의 캔버스 크기에 대한 지원을 테스트하려는 경우 canvas-size를 확인하십시오 .

문서에서 :

HTML 캔버스 요소는 최신 및 레거시 브라우저에서 널리 지원되지만 각 브라우저 및 플랫폼 조합은 초과시 캔버스를 사용할 수 없게 만드는 고유 한 크기 제한을 부과합니다. 안타깝게도 브라우저는 제한 사항을 확인할 수있는 방법을 제공하지 않으며 사용할 수없는 캔버스가 생성 된 후 어떤 종류의 피드백도 제공하지 않습니다. 따라서 특히 다양한 브라우저와 플랫폼을 지원하는 응용 프로그램의 경우 큰 캔버스 요소로 작업하는 것이 어렵습니다.

이 마이크로 라이브러리는 브라우저에서 지원하는 HTML 캔버스 요소의 최대 영역, 높이 및 너비와 사용자 정의 캔버스 크기를 테스트하는 기능을 제공합니다. 새 캔버스 요소가 생성되기 전에이 정보를 수집함으로써 애플리케이션은 각 브라우저 / 플랫폼의 크기 제한 내에서 캔버스 크기를 안정적으로 설정할 수 있습니다.

데모 링크 및 테스트 결과는 에서 사용할 수있는 README 뿐만 아니라 알려진 문제 성능 및 가상 머신 고려 사항에 닿는 부분.

전체 공개, 나는 도서관의 저자입니다. 2014 년에 다시 만들었고 최근에 새로운 캔버스 관련 프로젝트의 코드를 다시 검토했습니다. 2018 년에 캔버스 크기 제한을 감지하는 데 사용할 수있는 도구가 똑같이 부족하다는 사실에 놀랐 기 때문에 코드를 업데이트하고 릴리스했으며 다른 사람들이 유사한 문제를 겪는 데 도움이되기를 바랍니다.


8

w3 사양 에 따르면 너비 / 높이 인터페이스는 부호없는 길이이므로 0에서 4,294,967,295까지입니다 (그 숫자를 기억한다면-약간 떨어져있을 수 있습니다).

편집 : 이상하게도 unsigned long이라고 말하지만 테스트는 최대 길이 인 2147483647로 정상 long 값만 표시합니다. Jsfiddle -47은 작동하지만 최대 48 개이며 기본값으로 돌아갑니다.


흠. 흥미롭지 만 15 억도되지 않습니다.
seriousdev

편집, 죄송합니다 (먼저 테스트하지 않아서 얻은 것입니다)-jsfiddle을 추가했습니다.
WSkid

7

캔버스에서 height = 2147483647을 입력 할 수 있지만 그리기를 시작하면 아무 일도 일어나지 않습니다.

드로잉은 높이를 32767로 되돌릴 때만 발생합니다.


7

iOS에는 다른 제한이 있습니다.

iOS 7 시뮬레이터를 사용하여 다음과 같이 제한이 5MB임을 입증 할 수있었습니다.

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

그러나 캔버스 크기를 한 행의 픽셀만큼 위로 이동하면 :

var canvas = document.createElement('canvas');
canvas.width = 1024 * 5;
canvas.height = 1025;
alert(canvas.toDataURL('image/jpeg'));
// prints "data:," - a broken dataURL

2
이러한 데이터를 iOS 시뮬레이터를 기반으로해서는 안됩니다.
Zoltán

5

PC에서-
나는 제한이 없다고 생각하지만 네 메모리 예외를 벗어날 수 있습니다.

모바일 장치 -에
여기에 모바일 장치에 대한 캔버스에 대한 제한입니다 : -

캔버스 요소의 최대 크기는 RAM이 256MB 미만인 장치의 경우 3 메가 픽셀이고 RAM이 256MB보다 크거나 같은 장치의 경우 5 메가 픽셀입니다.

예를 들어 Apple의 이전 하드웨어를 지원하려는 경우 캔버스 크기는 2048 × 1464를 초과 할 수 없습니다.

이 자료가 당신을 끌어내는 데 도움이되기를 바랍니다.


3

Safari (모든 플랫폼)에 대한 제한은 훨씬 낮습니다.

알려진 iOS / Safari 제한 사항

예를 들어, 데이터가 그려진 6400x6400px 캔버스 버퍼가 있습니다. 콘텐츠를 추적 / 내 보낸 다음 다른 브라우저에서 테스트하여 모든 것이 정상임을 확인할 수있었습니다. 그러나 Safari에서는이 특정 버퍼의 그리기를 내 주요 컨텍스트로 건너 뜁니다.


그래! 더 큰 캔버스를 "허용됨"으로 사용하기 때문에 Safari는 캔버스 그리기를 건너 뜁니다. 위에 게시 한 최대 치수를 참조하십시오! 그것은 최대입니다. 이 사파리 / 장치에 캔버스.
Dado

귀하의 크기는 매우 임의적입니다. 문서가 있습니까? 테스트 과정은 어땠습니까?
NodeNodeNode

3

저는 프로그래밍 방식으로 한계를 알아 내려고했습니다. 캔버스 크기를 35000에서 시작하여 유효한 크기를 찾을 때까지 100 씩 줄였습니다. 모든 단계에서 오른쪽 하단 픽셀을 쓰고 읽습니다. 조심스럽게 작동합니다.

너비 또는 높이가 다음과 같이 낮은 값 (예 : 10-200)으로 설정된 경우 속도가 허용됩니다 get_max_canvas_size('height', 20).

그러나 너비 나 높이없이 호출 get_max_canvas_size()하면 생성 된 캔버스가 너무 커서 단일 픽셀 색상을 읽는 것이 매우 느리고 IE에서는 심각한 중단이 발생합니다.

픽셀 값을 읽지 않고 이와 같은 테스트를 수행 할 수 있다면 속도가 허용됩니다.

물론 최대 크기를 감지하는 가장 쉬운 방법은 최대 너비와 높이를 쿼리하는 기본 방법입니다. 그러나 캔버스는 '생활 표준'이므로 언젠가는 올 수 있습니다.

http://jsfiddle.net/timo2012/tcg6363r/2/ (주의! 브라우저가 멈출 수 있습니다!)

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;
  }
}

2
이것은 크게 사용하여 최적화 될 수 en.wikipedia.org/wiki/Exponential_search
브랜든 Annable

1
이처럼 큰 캔버스를 만드는 데 실패한 것이 조용해서 감지 할 방법이 없다는 것은 정말 미친 짓입니다. 어떤 방법 으로든 나쁘지 않습니다. 브라우저가 우리에게 떠오르는 것은 미친 일입니다
Colin D

@ColinD 동의합니다. 어딘가에있는 작은 정보 일뿐입니다. 그것은 것. 그리고해야합니다.
Timo Kähkönen

3

WebGL 캔버스를 사용하는 경우 브라우저 (데스크톱 포함)는 기본 버퍼의 크기에 추가 제한을 부과합니다. 캔버스가 16,000x16,000과 같이 크더라도 대부분의 브라우저는 더 작은 (4096x4096) 그림을 렌더링하고 크기를 늘립니다. 이는보기 흉한 픽셀 화 등을 유발할 수 있습니다.

누군가 필요할 경우 지수 검색을 사용하여 최대 크기를 결정하는 코드를 작성했습니다. determineMaxCanvasSize()관심있는 기능입니다.

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];
}

또한 jsfiddle https://jsfiddle.net/1sh47wfk/1/


확장 동작에 대한 공식 문서가 있습니까?
Magnus Lind Oxlund

1
@MagnusLindOxlund 답변의 정보는 실험적으로 결정되었습니다. 빠른 검색 후 내가 찾은 가장 가까운 것은 다음과 같습니다 : khronos.org/registry/webgl/specs/latest/1.0/#2.2 , "위의 제약 조건은 웹 페이지에서 캔버스 요소가 소비하는 공간의 양을 변경하지 않습니다. "드로잉 버퍼의 크기 제한에 대해 이야기 할 때. WebGL 표준은 캔버스 요소가 드로잉 버퍼를 표시하는 방법에 대해 미친 세부 사항으로 들어 가지 않는 것 같습니다.
Michał

1

당신은 그것을 청크하고 자바 스크립트에서 필요한만큼 작은 캔버스를 자동으로 추가하고 적절한 캔버스에 요소를 그릴 수 있습니다. 결국에는 여전히 메모리가 부족할 수 있지만 단일 캔버스 제한으로 인해 발생합니다.


0

나는 itteration없이 가능한 최대 크기를 감지하는 방법을 모르지만 주어진 캔버스 크기가 픽셀을 채운 다음 색상을 다시 읽어서 작동하는지 감지 할 수 있습니다. 캔버스가 렌더링되지 않은 경우 반환되는 색상이 일치하지 않습니다. W

부분 코드 :

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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.