фона НастройкаВозможно ли создать изображение (blob или data-url) в веб-работнике из getImageData контекста canvas?
У меня есть веб-приложение, которое имеет дело с созданием изображения из набора других изображений. То, как я решил сделать это, - это чтение в виде набора изображений и размещение их на холсте HTML. Затем я экспортирую каждый холст как jpeg в сторонний API, используя toDataURL
и конвертируя его в Blob. Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть многие из этих холстов, которые экспортируют данные в формате jpg и потребляют много ресурсов. Приложение замедляется и становится невосприимчивым, так как каждый холст пытается вызвать toDataURL
.
Вопрос
Я обнаружил, что вызов холст-х toDataUrl()
или toBlob()
может быть очень медленным, особенно для больших размеров холста. Я бы хотел использовать многопоточный характер веб-работников.
Во-первых, я пробовал пропустить в объекте canvas, но была выброшена ошибка. Оказывается, объекты являются проблемой, и кажется, что они либо преобразуются в строки, либо терпят неудачу, когда их нельзя клонировать. В любом случае, я обнаружил, что передача данных изображения контекста действительно работает. Данные передаются в виде необработанных значений RGB как Uint8ClampedArray
из метода контекста canvas getImageData()
.
Main.js
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var worker = new Worker('myWorker.js');
worker.postMessage({
image: context.getImageData(0, 0, canvas.width, canvas.height)
});
myWorker.js
this.onmessage = function(e) {
// GOAL: turn e.data.image into an image blob or dataUrl and return it.
// e.g. this.postMessage(new Blob([e.data.image.data], {type: 'image/jpg'});
}
Я думаю, что это сводится к тому, зная, как преобразовать Uint8ClampedArray
который содержит информацию RGB в JPG/PNG данные.
Причина, по которой я думаю, что это может быть полезно, заключается в том, что я считаю, что getImageData
просто копирует существующую структуру данных из контекста canvas и, следовательно, не так дорого, как toDataUrl
. Я захватил профиль центрального процессора при вызове что-то похожее на блок кода ниже:
var image = context.getImageData(0, 0, canvas.width, canvas.height)
var dataUrl = canvas.toDataURL('image/jpeg');
и получил:
Таким образом, учитывая, что я хотел бы, чтобы разгрузить основную тяжесть процесса в веб-работника. Я даже не возражаю, если он занимает больше времени внутри веб-рабочего, если это происходит в другом процессе.
Пара лишних мыслей о нем:
- Добавление дополнительных библиотек, чтобы сделать преобразование в порядке, но бонусные баллы для предложения, как добавить внешнюю библиотеку в качестве зависимости к файлам веб-рабочих. Сейчас я использую браузер для приложения. Возможно, создайте еще один браузерный веб-сайт?
- Мне нужен jpeg в конце (для стороннего API), поэтому преобразование его в png настолько хорошее, чтобы быть шагом в преобразовании в jpeg.
- Я попытался опускании
encoderOptions
, второй вариант вtoDataURL
, как способ ускорить процесс, но я не видел много изменений
Это может быть возможно, но очень сложно, и я не уверен, какую пользу вы будете иметь: вы можете создать Blob и отправить его на главную страницу с веб-работника. Вы можете сделать кодировку в jpeg или png самостоятельно (даже если я рекомендую искать некоторые библиотеки). Начните с png, [specs] (https://www.w3.org/TR/PNG-Introduction.html) понятнее jpeg. Примечание: вам также необходимо отправить метаданные изображения. Но самая тяжелая операция - 'ctx.getImageData()'. Я не уверен, что вы выиграете что-либо, передав часть сжатия веб-работнику. – Kaiido
Возможно, вам стоит показать нам свой код, чтобы мы могли узнать, можно ли что-то улучшить. (например, вы используете некоторые асинхронные методы, чтобы графический интерфейс не блокировался?) – Kaiido
@ Kaiido - Я обновил вопрос, чтобы больше узнать о моем понимании проблемы. Похоже, что getImageData не так обременительна, как ожидалось. А что касается моего кода, я использую метод defercore defer для обертывания canvas.toDataURL, чтобы не блокировать пользовательский интерфейс, но как только начнется метод (который он в конечном итоге), он заблокирует выполнение других js. Кроме того, стоит отметить, что я делаю это много раз для многих изображений на странице, поэтому стоимость выше, чем сообщенные 400 мс. –