Этот вопрос предназначен для более глубокого понимания моего предыдущего вопроса об анимации холста большого размера. Вопрос здесь: Повторите элемент холста HTML (поле), чтобы заполнить всю область просмотра.
Я пытаюсь понять логику TypedArray — Uint8ClampedArray. Я сначала начну с моего исследования и перейду к самому вопросу позже.
Итак, ImageData представляет пиксельные данные холста HTML5. Он обеспечивает гораздо более высокую производительность и хорош для тяжелых анимаций. После того, как у нас есть объект ImageData, мы создаем для него буферное пространство. Поскольку мы не можем читать и писать напрямую из/в буфер, мы передаем этот буфер в TypedArray. В данном случае это Uint8ClampedArray, который похож на обычный массив и позволяет получить доступ к данным внутри него.
Каждый пиксель на нашем холсте представлен 4 целочисленными значениями, которые обозначают красный, зеленый, синий, альфа — как в RGBA — в диапазоне от 0 до 255. Каждому из этих значений присваивается индекс Uint8ClampedArray, начиная с 0, и массив делится на куски по 4. Таким образом, первые 4 значения — это самый первый пиксель, вторые 4 значения — это 2-й пиксель и так далее. Пиксели Cavnas считываются слева направо, строка за строкой.
Итак, если, например, мы хотим получить индекс массива красного значения пикселя в xCoord = 3; yCoord = 1; canvasWidth = 10;
. Формула из MDN: Манипулирование пикселями с холстом предполагает, что мы делаем следующую математику:
var red = y * (width * 4) + x * 4;
= 1 * 10 * 4 + 3 * 4 = 52;
Но если мы попытаемся сделать то же самое вручную и просто вычислим себя попиксельно, мы не получим того же значения. Это всегда немного не так. Как бы мы рассчитали вручную? На этой картинке мы начинаем с 0 X 0
до 0 X 9
и до 1 X 3
. Поскольку мы начинаем сверху слева и двигаемся вправо, это инвертируется, и Y — наша первая координата, а X — наша вторая координата. Всего от 0 X 0
до 0 X 9
записываем 40 значений (по 4 значения на каждый пиксель, 10 пикселей в общей ширине); Всего от 1 X 0
до 1 X 3
записываем 16 значений. В итоге получаем 56-й индекс, а не 52, как мы рассчитали по формуле.
Итак, пожалуйста, помогите мне понять всю логику в Uint8ClampedArray и как она вычисляется.
Всего от 1 X 0 до 1 X 3 мы записываем 16 значений.
Последние 4 байта из этих 16 представляют пиксель в (3, 1). Красный канал является первым из них, ему предшествуют 12 байтов для пикселей слева и 40 байтов для пикселей в первой строке. Он находится под индексом 52 в общем массиве.
Помните, что массивы индексируются как
0 1 2
+---+---+--
| | |
+---+---+--
не как
+---+---+--
| 0 | 1 | 2
+---+---+--
Другими словами, пиксель с координатами 3,1 охватывает индексы от 52 до 55, и поскольку массивы имеют индекс 0, 56-е значение находится в индексе 55 -> их метод получает конечный индекс пикселя, а метод MDN получает начальный индекс. И, кстати, для OP более понятным способом написания формулы MDN было бы ((y * width) + x) * 4
-> индекс пикселя * байт на пиксель.