До сих пор мы не смотрели на фактические пиксели нашего холста. С объектом ImageData вы можете напрямую читать и писать массив данных для управления пиксельными данными. Мы также рассмотрим, как можно сгладить сглаживание изображения (сглаживание) и как сохранить изображения с вашего холста.

ОбъекImageData

Объект ImageData представляет базовые пиксельные данные области объекта холста. Он содержит следующие атрибуты только для чтения:

width
Ширина изображения в пикселях.
height
Высота изображения в пикселях.
data
A 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 , содержащий копию данных пикселя для контекста canvas, вы можете использовать метод getImageData() :

var myImageData = ctx.getImageData(left, top, width, height);

Этот метод возвращает объект ImageData , представляющий данные пикселя для области холста, углы которого представлены точками (слева, сверху), (слева + ширина, верх), (слева, верх + высота) и (слева + ширина , верх + высота). Координаты задаются в единицах пространства координат холста.

Note: Любые пиксели за пределами холста возвращаются как прозрачный черный в результирующий объект ImageData .

Этот метод также показан в статье Manipulating video using canvas.

Выбор цвета

В этом примере мы используем метод getImageData() для отображения цвета под курсором мыши. Для этого нам нужна текущая позиция мыши с layerX и layerY, затем мы просматриваем пиксельные данные в этой позиции в массиве пикселей, который предоставляет нам getImageData() . Наконец, мы используем данные массива для установки цвета фона и текста <div> для отображения цвета.

var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/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);

Гранулирование и инвертирование цветов

В этом примере мы перебираем все пиксели для изменения их значений, а затем помещаем модифицированный массив пикселей обратно в холст с помощью putImageData(). Функция инвертирования просто вычитает каждый цвет с максимального значения 255. Функция оттенков серого просто использует среднее значение красного, зеленого и синего. Вы также можете использовать средневзвешенное значение, заданное формулой x = 0.299r + 0.587g + 0.114b, например. Дополнительную информацию см. в Grayscale серого в Википедии.

var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/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 (которому нужны префиксы для разных браузеров).

var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/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, содержащий представление изображения в формате, заданном параметром типа (по умолчанию используется PNG ). Возвращаемое изображение имеет разрешение 96 точек на дюйм.

canvas.toDataURL('image/png')
Настройки по умолчанию. Создает изображение PNG.
canvas.toDataURL('image/jpeg', quality)
Создает изображение в формате JPG. При желании вы можете обеспечить качество в диапазоне от 0 до 1, причем одно из них является лучшим качеством и с 0 почти не распознаваемым, но небольшим размером файла.

После того как вы создали URI данных из своего холста, вы можете использовать его как источник любого <image> или поместить его в гиперссылку с download attribute, чтобы сохранить его на диске, для пример.

Вы также можете создать Blob из холста.

canvas.toBlob(callback, type, encoderOptions)
Создает объект Blob, представляющий изображение, содержащееся в холсте.

Смотрите также

Метки документа и участники

Внесли вклад в эту страницу: Garloy, Liubava77
Обновлялась последний раз: Garloy,