HTML5 Canvas toBlob приводит к null [duplicate]

Если вы используете VS2008 / .net 3.5, см. подсказку Alex James № 8: http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing -where-in-style-queries-using-linq-to-entities.aspx

В противном случае просто используйте метод array.Contains (someEntity.Member).

90
задан seriousdev 21 May 2011 в 12:40
поделиться

13 ответов

Обновлено 10/13/2014

Все проверенные браузеры имеют ограничения на высоту / ширину элементов холста, но многие браузеры также ограничивают общую площадь элемента холста. Ограничения для браузеров, которые я могу проверить, следующие:

Chrome:

Максимальная высота / ширина: 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 Mobile:

Максимальная высота / ширина: 4 096 пикселей Максимальная площадь: N / A

Другое:

В настоящее время я не могу протестировать другие браузеры. См. Другие ответы на этой странице для дополнительных ограничений.


Превышение максимальной длины / ширины / области в большинстве браузеров делает невозможным использование холста. (Он игнорирует любые команды рисования даже в полезной области.) IE и IE Mobile будут отмечать все команды рисования в используемом пространстве.

94
ответ дан Brandon Gano 18 August 2018 в 15:22
поделиться
  • 1
    Итак, связанный с этим вопрос ... как работать над пределом, если им нужен холст, который больше допустимого максимума? – aroth 3 April 2014 в 05:47
  • 2
    @aroth, я закончил тем, что написал обертку вокруг API-интерфейса холста, который использовал несколько уложенных элементов <canvas> и автоматически применял инструкции рисования к соответствующему контексту. – Brandon Gano 7 April 2014 в 02:50
  • 3
    Звучит очень полезно. Не думайте, что это на github? – aroth 7 April 2014 в 02:57
  • 4
    Safari (версия, отличная от iOS) использует 32K, например Chrome.Firefox. Кроме того, если вы хотите попытаться воссоздать часть этого кода оболочки, я начал собственную версию с открытым исходным кодом благодаря незначительному ограничению 8K IE: github.com/adam-roth/wrapped-canvas – aroth 3 November 2014 в 07:09
  • 5

Несмотря на то, что холст позволит вам установить высоту = 2147483647, когда вы начнете рисовать, ничего не произойдет

Рисование происходит только тогда, когда я возвращаю высоту до 32767

7
ответ дан avikaza123 18 August 2018 в 15:22
поделиться

Я столкнулся с ошибками памяти в Firefox с высотой холста больше 8000, хром, похоже, обрабатывает гораздо больше, по крайней мере до 32000.

EDIT: после запуска еще нескольких тестов, ve обнаружил некоторые очень странные ошибки с Firefox 16.0.2.

Во-первых, я, кажется, получаю другое поведение из памяти (созданного в javascript) canvas в отличие от html объявленного холста.

Во-вторых, если у вас нет правильного html-тега и мета-кодировки, холст может быть ограничен 8196, в противном случае вы можете перейти до 32767.

В-третьих, если вы получить 2d контекст холста, а затем изменить размер холста, вы можете быть ограничены также 8196. Просто установив размер холста, прежде чем захватить 2d-контекст, вы можете иметь до 32767 без ошибок памяти.

Я не смог последовательно получить ошибки памяти, иногда это только при загрузке первой страницы, а затем последующие изменения высоты работы. Это файл html, который я тестировал с помощью http://pastebin.com/zK8nZxdE .

16
ответ дан Ben Burnett 18 August 2018 в 15:22
поделиться
  • 1
    «Во-вторых, если у вас нет правильного html-тега и мета-кодировки, холст может быть ограничен 8196, в противном случае вы можете перейти до 32767 & quot; - Что вы подразумеваете под правильным тегом html и мета-charset здесь? – Jack Aidley 20 October 2015 в 11:34
  • 2
    Тестовая страница не работает. – Fatih Hayrioğlu 3 December 2015 в 07:30
  • 3
    Неужели вы имеете в виду 8192 (2 ^ 13)? 8196 - странное число. – jamesdlin 20 January 2018 в 01:58

Размер холста iOS max (ширина x высота):

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

проверен в марте 2014 г.

13
ответ дан Dado 18 August 2018 в 15:22
поделиться
  • 1
    Эти значения произвольны. См. Мое сообщение ниже, в котором приведены ссылки на содержание сафари. – dcbarans 20 March 2015 в 17:45

Ограничения для Safari (все платформы) намного ниже.

Известные ограничения iOS / Safari

Например, у меня был буфер холста 6400x6400px с данными, нарисованными на нем. Трассируя / экспортируя контент и тестируя в других браузерах, я смог увидеть, что все в порядке. Но в Safari он пропускает чертеж этого конкретного буфера в мой основной контекст.

2
ответ дан Frederic Charette 18 August 2018 в 15:22
поделиться
  • 1
    Джип! Safari пропускает ваш холст, потому что вы используете более крупный холст как «разрешенный». См. Макс. Размеры, которые я разместил выше! Это максимум. холст на этом сафари / устройства. – Dado 18 March 2014 в 18:07
  • 2
    Ваши размеры довольно произвольны, не так ли? У вас есть документация? Каков был ваш процесс тестирования? – Frederic Charette 19 March 2014 в 18:06

Вы можете его обрезать, а в javascript автоматически добавить столько маленьких холстов, сколько необходимо, и нарисовать элементы на соответствующем холсте. В конечном итоге у вас может быть нехватка памяти, но вы получите единственное ограничение на холст.

0
ответ дан JJ_Coder4Hire 18 August 2018 в 15:22
поделиться

На ПК я не думаю, что есть ограничение, но да, вы можете избавиться от исключения из памяти.

На мобильных устройствах. Вот ограничения для холста для мобильных устройств: -

Максимальный размер элемента canvas составляет 3 мегапикселя для устройств с ОЗУ менее 256 МБ и 5 мегапикселей для устройств с большей или равной 256 МБ ОЗУ.

Так, например, если вы хотят поддерживать более старое оборудование Apple, размер вашего холста не может превышать 2048 × 1464.

Надеюсь, эти ресурсы помогут вам вытащить вас.

4
ответ дан Manish Gupta 18 August 2018 в 15:22
поделиться

iOS имеет разные пределы.

Используя симулятор iOS 7, я смог продемонстрировать, что предел равен 5 МБ следующим образом:

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
7
ответ дан matt burns 18 August 2018 в 15:22
поделиться
  • 1
    Вы не должны основывать такие данные на симуляторе iOS. – Zoltán 12 December 2017 в 11:09

Когда вы используете веб-холсты 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/

0
ответ дан Michał 18 August 2018 в 15:22
поделиться

Я не знаю, как определить максимальный размер без итерации, но вы можете определить, работает ли данный размер холста, заполнив пиксель, а затем прочитав цвет обратно. Если холст не отображен, тогда цвет, который вы получите, не будет соответствовать. 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);
0
ответ дан SystemicPlural 18 August 2018 в 15:22
поделиться

Я попытался программно определить ограничение: установив размер холста, начиная с 35000, уступив 100, пока не будет найден действительный размер. На каждом шаге записывается правый нижний пиксель, а затем читается. Он работает - с осторожностью.

Скорость приемлема, если ширина или высота установлены на некоторое низкое значение (например, 10-200) следующим образом: get_max_canvas_size('height', 20).

Но если вызывается без ширины или высоты, например get_max_canvas_size(), созданный холст настолько велик, что чтение ОДИНОЧНОГО пиксельного цвета происходит очень медленно, а в IE вызывает серьезную зависание.

Если такой тест можно было бы сделать каким-то образом без чтения пиксель, скорость будет приемлемой.

Конечно, самый простой способ определить максимальный размер - это собственный способ запроса максимальной ширины и высоты. Но Canvas - это «живой стандарт», так может случиться, что он наступит.

http://jsfiddle.net/timo2012/tcg6363r/2/ (Помните! Ваш браузер может висеть!) [/ ​​G6]

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;
  }
}
3
ответ дан Timo Kähkönen 18 August 2018 в 15:22
поделиться
  • 1
    Это было бы сильно оптимизировано с помощью ru.wikipedia.org/wiki/Exponential_search – Brendan Annable 23 September 2016 в 05:40
  • 2
    Это действительно безумие, что неудача создания холста в этом большом молчат, поэтому нет никакого способа обнаружить ... неважно каким-либо образом с вашей стороны, это просто сумасшедшая вещь для браузеров на нас – Colin D 8 February 2017 в 19:42
  • 3
    @ColinD Я согласен. Это будет всего лишь небольшая часть информации. Это было бы. И должен. – Timo Kähkönen 9 February 2017 в 23:15

Чтобы развернуть бит в ответе @FredericCharette: согласно руководству по содержанию сафари в разделе «Знать ограничения ресурсов iOS»:

Максимальный размер для элемента холста 3 мегапикселя для устройств с оперативной памятью менее 256 МБ и 5 мегапикселей для устройств с большей или равной 256 МБ ОЗУ

Поэтому любое изменение размера 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

и т. д ..

Крупнейшие холсты CQUARE («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
11
ответ дан ToolmakerSteve 18 August 2018 в 15:22
поделиться
  • 1
    Чтобы быть более конкретным, предел iPhone5 составляет 3 * 1024 * 1024 = 3145728 пикселей. (После того, как я спросил, почему мой холст отлично работает на Android, но пустым в iOS, я нашел этот ответ, а также stackoverflow.com/questions/12556198/… и получил приложение Phonegap.) – Magnus Smith 25 January 2016 в 14:37
  • 2
    Интересно, спасибо! – dcbarans 26 January 2016 в 16:12
  • 3
    FYI, Apple удалила информацию определенного размера из «Ограничений ресурсов Safari / Know iOS». Теперь это всего лишь общий совет о минимизации полосы пропускания с помощью небольших изображений. – ToolmakerSteve 2 March 2017 в 01:28
  • 4
    @ matb33 сообщил в комментарии к вопросу о том, что iPhone 6 имеет ограничение 16 * 1024 * 1024. – ToolmakerSteve 2 March 2017 в 01:29

В соответствии с спецификациями w3 интерфейс ширины / высоты является unsigned long, поэтому от 0 до 4,294,967,295 (если я помню, что число справа - может быть несколько).

EDIT: Странно, он говорит unsigned long, но это тестирование показывает только нормальное длинное значение как max: 2147483647. Jsfiddle - 47 работает, но до 48 и возвращается к умолчанию.

7
ответ дан WSkid 18 August 2018 в 15:22
поделиться
  • 1
    Хм. Интересно, но я даже не добираюсь до 1,5 миллиарда. – seriousdev 21 May 2011 в 12:56
  • 2
    Отредактировано, извините (это то, что я получаю для не тестирования в первую очередь) - добавлен jsfiddle для показа. – WSkid 21 May 2011 в 12:58
Другие вопросы по тегам:

Похожие вопросы: