Chrome поддерживает createImageBitmap() в Chrome 50.

Декодирование изображений для использования с холстом является довольно распространенным явлением, будь то возможность пользователям настраивать аватар, обрезать изображение или просто увеличивать изображение. Проблема с декодированием изображений заключается в том, что оно может нагружать процессор, а это иногда может означать зависание или шахматную доску. Начиная с Chrome 50 (и Firefox 42+) у вас теперь есть еще один вариант: createImageBitmap() . Он позволяет вам декодировать изображение в фоновом режиме и получить доступ к новому примитиву ImageBitmap , который вы можете нарисовать на холсте так же, как и элемент <img> , другой холст или видео.

Рисование BLOB-объектов с помощью createImageBitmap()

Допустим, вы загружаете изображение большого двоичного объекта с помощью fetch() (или XHR) и хотите нарисовать его на холсте. Без createImageBitmap() вам пришлось бы создать элемент изображения и URL-адрес Blob, чтобы преобразовать изображение в формат, который вы могли бы использовать. С его помощью вы получите гораздо более прямой путь к рисованию:

fetch(url)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => ctx.drawImage(imageBitmap, 0, 0));

Этот подход также будет работать с изображениями, хранящимися в виде больших двоичных объектов в IndexedDB, что делает большие двоичные объекты своего рода удобным промежуточным форматом. Кстати , Chrome 50 также поддерживает метод .toBlob() для элементов холста, что означает, что вы можете, например, генерировать большие двоичные объекты из элементов холста.

Использование createImageBitmap() в веб-воркерах

Одна из самых приятных особенностей createImageBitmap() заключается в том, что она также доступна в рабочих процессах, а это означает, что теперь вы можете декодировать изображения где угодно. Если вам нужно декодировать много изображений, которые вы считаете несущественными, вы должны отправить их URL-адреса веб-работнику, который загрузит и декодирует их, как только позволит время. Затем он перенесет их обратно в основной поток для рисования на холсте.

Поток данных с помощью createImageBitmap и веб-воркеров.

Код для этого может выглядеть примерно так:

// In the worker.
fetch(imageURL)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => {
    // Transfer the imageBitmap back to main thread.
    self.postMessage({ imageBitmap }, [imageBitmap]);
    }, err => {
    self.postMessage({ err });
    });

// In the main thread.
worker.onmessage = (evt) => {
    if (evt.data.err)
    throw new Error(evt.data.err);

    canvasContext.drawImage(evt.data.imageBitmap, 0, 0);
}

Сегодня, если вы вызовете createImageBitmap() в основном потоке, именно там и будет выполняться декодирование. Однако в планах Chrome автоматически выполнять декодирование в другом потоке , что поможет снизить нагрузку на основной поток. Тем временем, однако, вам следует помнить о выполнении декодирования в основном потоке, поскольку это интенсивная работа, которая может заблокировать другие важные задачи, такие как JavaScript, вычисления стилей, макетирование, рисование или композицию.

Вспомогательная библиотека

Чтобы немного упростить жизнь, я создал вспомогательную библиотеку , которая обрабатывает декодирование в рабочем потоке, отправляет обратно декодированное изображение в основной поток и рисует его на холсте. Вы, конечно, можете свободно перепроектировать ее и применить модель к своим собственным приложениям. Основным преимуществом является больший контроль, но при этом (как обычно) требуется больше кода, больше задач для отладки и больше крайних случаев, которые необходимо учитывать, чем при использовании элемента <img> .

Если вам нужно больше контроля над декодированием изображений, createImageBitmap() — ваш новый лучший друг. Проверьте это в Chrome 50 и дайте нам знать, как у вас дела!