Контекст холста putImageData: потеря данных из-за оптимизации браузера

Я работаю над репликой Paint, включающей манипуляции с ImageData. На этой странице документации MDN статья говорит:

Из-за характера преобразования с потерями в предварительно умноженные значения альфа-цвета и обратно пиксели, которые только что были установлены с помощью putImageData(), могут быть возвращены в эквивалентный getImageData() как разные значения.

И приводит такой пример:

const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
const context = canvas.getContext("2d");
const imgData = context.getImageData(0, 0, canvas.width, canvas.height);
const pixels = imgData.data;
pixels[0 + 0] = 1;
pixels[0 + 1] = 127;
pixels[0 + 2] = 255;
pixels[0 + 3] = 1;
console.log("before:", pixels);
context.putImageData(imgData, 0, 0);
const imgData2 = context.getImageData(0, 0, canvas.width, canvas.height);
const pixels2 = imgData2.data;
console.log("after:", pixels2);

Вывод в этом примере

before: Uint8ClampedArray(4) [ 1, 127, 255, 1 ]
after: Uint8ClampedArray(4) [ 255, 255, 255, 1 ]

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

Итак, в статье не говорится о том, почему это происходит и как это обойти. Что я должен сделать, чтобы убедиться, что мой вызов putImageData приведет к тем же самым данным, которые впоследствии будут возвращены getImageData?

Прежде чем я увидел, как это работает таким образом, я всегда работал с полностью непрозрачными (каждый 4-й элемент равен 255) холстами. Это единственный способ гарантировать, что остальные данные не будут каким-то образом изменены при вызове putImageData?


person 1valdis    schedule 04.02.2020    source источник
comment
Из-за того, что преобразование в предварительно умноженные значения альфа-цвета и из них связано с потерями, в вашей цитате написано: предварительное умножение альфа-канала выполняется с потерями. Поскольку в их примере у них действительно низкая непрозрачность (1/255), это действительно может привести к такому большому расхождению.   -  person Kaiido    schedule 04.02.2020
comment
@Kaiido, почему это умножение вообще происходит? Есть ли способ предотвратить такое поведение, чтобы значение альфы не влияло на другие значения?   -  person 1valdis    schedule 04.02.2020