This page was translated from English by the community.Learn more and join the MDN Web Docs community.
Пиксельная манипуляция с холстом
До сих пор мы не смотрели на фактические пиксели нашего объекта canvas (далее "холст"). С объектомImageData вы можете напрямую читать и писать массив данных для управления пиксельными данными. Мы также рассмотрим, как можно сгладить сглаживание изображения (сглаживание) и как сохранить изображения с вашего холста.
In this article
ОбъектImageData
ОбъектImageData представляет базовые пиксельные данные области объекта холста. Он содержит следующие атрибуты только для чтения:
widthШирина изображения в пикселях.
heightВысота изображения в пикселях.
dataA
Uint8ClampedArrayпредставляет собой одномерный массив, содержащий данные в порядке RGBA, с целыми значениями от0до255(в комплекте).
Свойствоdata возвращаетUint8ClampedArray, к которому можно получить доступ, чтобы посмотреть на необработанные пиксельные данные; каждый пиксель представлен четырьмя однобайтовыми значениями (красный, зелёный, синий и альфа в этом порядке, то есть формат «RGBA»). Каждый компонент цвета представлен целым числом от 0 до 255. Каждому компоненту присваивается последовательный индекс внутри массива, причём красный компонент верхнего левого пикселя находится в индексе 0 внутри массива. Затем пиксели идут слева направо, затем вниз, по всему массиву.
Uint8ClampedArray содержит высоту × ширину × 4 байта данных, значения индекса варьируются от 0 до (высота × ширина × 4) -1.
Например, чтобы прочитать значение синего компонента из пикселя в столбце 200, строка 50 на изображении, вы должны сделать следующее:
blueComponent = imageData.data[50 * (imageData.width * 4) + 200 * 4 + 2];Вы можете получить доступ к размеру массива пикселей в байтах, прочитав атрибутUint8ClampedArray.length:
var numBytes = imageData.data.length;Создание объектаImageData
Чтобы создать новый пустой объектImageData , вы должны использовать методcreateImageData (). Существуют две версии методаcreateImageData() :
var myImageData = ctx.createImageData(width, height);Это создаёт новый объектImageData с указанными параметрами. Все пиксели заданы прозрачным черным.
Вы также можете создать новый объектImageData ImageData с теми же размерами, что и объект, заданныйanotherImageData . Все пиксели нового объекта установлены на прозрачный чёрный.Это не копирует данные изображения!
var myImageData = ctx.createImageData(anotherImageData);Получение пиксельных данных для контекста
Чтобы получить объектImageData , содержащий копию пиксельных данных для контекста холста, вы можете использовать методgetImageData() :
var myImageData = ctx.getImageData(left, top, width, height);Этот метод возвращает объектImageData , представляющий пиксельные данные для области холста, углы которого представлены точками (left ,top), (left+width ,top), (left ,top+height) и (left+width ,top+height). Координаты задаются в единицах пространства координат холста.
Примечание:Любые пиксели за пределами холста возвращаются как прозрачный чёрный цвет в результирующий объектImageData .
Этот метод также показан в статьеManipulating video using canvas.
Выбор цвета
В этом примере мы используем методgetImageData() для отображения цвета под курсором мыши. Для этого нам нужна текущая позиция мыши сlayerX иlayerY, затем мы просматриваем пиксельные данные в этой позиции в массиве пикселей, который предоставляет намgetImageData(). Наконец, мы используем данные массива для установки цвета фона и текста<div> для отображения цвета.
<canvas width="300" height="227"></canvas><div></div>var img = new Image();img.src = "rhino.jpg";var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");img.onload = function () { ctx.drawImage(img, 0, 0); img.style.display = "none";};var color = document.getElementById("color");function pick(event) { var x = event.layerX; var y = event.layerY; var pixel = ctx.getImageData(x, y, 1, 1); var data = pixel.data; var rgba = "rgba(" + data[0] + ", " + data[1] + ", " + data[2] + ", " + data[3] / 255 + ")"; color.style.background = rgba; color.textContent = rgba;}canvas.addEventListener("mousemove", pick);Отображение пиксельных данных в контекст
Вы можете использовать методputImageData() для рисования пиксельных данных в контексте:
ctx.putImageData(myImageData, dx, dy);Параметрыdx иdy указывают координаты устройства в контексте, в котором будет отображаться верхний левый угол пиксельных данных, которые вы хотите нарисовать.
Например, чтобы нарисовать все изображение, представленноеmyImageData, в верхнем левом углу контекста, вы можете просто сделать следующее:
ctx.putImageData(myImageData, 0, 0);Оттенки серого цвета и инвертирование цветов
В этом примере мы перебираем все пиксели для изменения их значений, а затем помещаем модифицированный массив пикселей обратно в canvas с помощьюputImageData(). Функция инвертирования просто вычитает каждый цвет из максимального значения 255. Функция оттенков серого просто использует среднее значение красного, зелёного и синего. Вы также можете использовать средневзвешенное значение, заданное формулойx = 0.299r + 0.587g + 0.114b, например. Для дополнительной информации смотритеОттенки серого в Википедии.
<canvas width="300" height="227"></canvas><div> <input value="Grayscale" type="button" /> <input value="Invert" type="button" /></div>var img = new Image();img.src = "rhino.jpg";img.onload = function () { draw(this);};function draw(img) { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); img.style.display = "none"; var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var data = imageData.data; var invert = function () { for (var i = 0; i < data.length; i += 4) { data[i] = 255 - data[i]; // red data[i + 1] = 255 - data[i + 1]; // green data[i + 2] = 255 - data[i + 2]; // blue } ctx.putImageData(imageData, 0, 0); }; var grayscale = function () { for (var i = 0; i < data.length; i += 4) { var avg = (data[i] + data[i + 1] + data[i + 2]) / 3; data[i] = avg; // red data[i + 1] = avg; // green data[i + 2] = avg; // blue } ctx.putImageData(imageData, 0, 0); }; var invertbtn = document.getElementById("invertbtn"); invertbtn.addEventListener("click", invert); var grayscalebtn = document.getElementById("grayscalebtn"); grayscalebtn.addEventListener("click", grayscale);}Масштабирование и сглаживание
С помощью методаdrawImage (), второго холста и свойстваimageSmoothingEnabled мы способны увеличить изображение и посмотреть его более детально.
Мы получаем положение мыши и обрезаем изображение на 5 пикселей левее и выше и на 5 пикселей правее и ниже положения мыши. Затем мы копируем его на другой холст и изменяем размер изображения до размера, который мы хотим. При масштабировании мы изменяем холст с исходного размера 10×10 пикселей до 200×200.
zoomctx.drawImage( canvas, Math.abs(x - 5), Math.abs(y - 5), 10, 10, 0, 0, 200, 200,);Поскольку по умолчанию включено сглаживание, мы можем захотеть отключить сглаживание, чтобы увидеть чёткие пиксели. Вы можете переключить флажок, чтобы увидеть эффект свойстваimageSmoothingEnabled (которому нужны префиксы для разных браузеров).
<canvas width="300" height="227"></canvas><canvas width="300" height="227"></canvas><div> <label for="smoothbtn"> <input type="checkbox" name="smoothbtn" checked="checked" /> Enable image smoothing </label></div>var img = new Image();img.src = "rhino.jpg";img.onload = function () { draw(this);};function draw(img) { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); img.style.display = "none"; var zoomctx = document.getElementById("zoom").getContext("2d"); var smoothbtn = document.getElementById("smoothbtn"); var toggleSmoothing = function (event) { zoomctx.imageSmoothingEnabled = this.checked; zoomctx.mozImageSmoothingEnabled = this.checked; zoomctx.webkitImageSmoothingEnabled = this.checked; zoomctx.msImageSmoothingEnabled = this.checked; }; smoothbtn.addEventListener("change", toggleSmoothing); var zoom = function (event) { var x = event.layerX; var y = event.layerY; zoomctx.drawImage( canvas, Math.abs(x - 5), Math.abs(y - 5), 10, 10, 0, 0, 200, 200, ); }; canvas.addEventListener("mousemove", zoom);}Сохранение изображений
HTMLCanvasElement предоставляет методtoDataURL(), который полезен при сохранении изображений. Он возвращаетdata URI, содержащий представление изображения в формате, заданном параметромtype (по умолчанию используется вPNG ). Возвращаемое изображение имеет разрешение 96 точек на дюйм.
- Примечание:
Имейте в виду, что если холст содержит пиксели, полученные из другогоorigin без использования CORS, холст будетиспорчен, и его содержимое больше не будет считываться и сохраняться. СмотритеБезопасность и испорченные холсты
canvas.toDataURL('image/png')Настройки по умолчанию. Создаёт изображение в формате PNG.
canvas.toDataURL('image/jpeg', quality)Создаёт изображение в формате JPG. Дополнительно вы можете задать параметр "качество" (quality) в диапазоне от 0 до 1, причём единица задаёт лучшее качество и 0 - почти не распознаваемый, но небольшой по размеру файл.
После того как вы создали URI данные из своего холста, вы можете использовать его как источник любого<image> или поместить его в гиперссылку сdownload attribute, чтобы сохранить его на диске, например.
Вы также можете создатьBlob из холста.
canvas.toBlob(callback, type, encoderOptions)Создаёт объект
Blob, представляющий изображение, содержащееся в холсте.