GetImageData: примеры (JAVASCRIPT)

Метод getImageData для манипуляций с пикселями на холсте
Раздел: Canvas, Пиксели
getImageData(sx: Number, sy: Number, sw: Number, sh: Number): ImageData

Функция getImageData в JavaScript

Метод getImageData() является частью Canvas API и применяется для получения массива данных о пикселях указанного участка холста. Он используется при необходимости низкоуровневой обработки изображений, такой как фильтры, анализ цвета или манипуляции с пикселями.

Синтаксис: context.getImageData(sx, sy, sw, sh);

  • sx: Координата X верхнего левого угла прямоугольной области для считывания.
  • sy: Координата Y верхнего левого угла прямоугольной области для считывания.
  • sw: Ширина прямоугольной области в пикселях.
  • sh: Высота прямоугольной области в пикселях.

Возвращает объект ImageData, содержащий три свойства:

  • width: Ширина области в пикселях.
  • height: Высота области в пикселях.
  • data: Одномерный массив Uint8ClampedArray, содержащий данные о пикселях в формате RGBA (Red, Green, Blue, Alpha) для каждого пикселя. Значения каждого канала варьируются от 0 до 255.

Примеры применения getImageData

Получение данных всего холста:

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
console.log(imageData.width, imageData.height);
// Вывод: ширина и высота canvas

Чтение цвета первого пикселя:

const data = imageData.data;
const red = data[0];
const green = data[1];
const blue = data[2];
const alpha = data[3];
console.log(`RGBA: ${red}, ${green}, ${blue}, ${alpha}`);
// Вывод: значения RGBA первого пикселя

Альтернативные функции в JavaScript

  • createImageData(): Создает новый пустой объект ImageData. Используется для подготовки данных перед размещением на холсте с помощью putImageData().
  • putImageData(): Обратная операция - помещает данные ImageData обратно на холст. Применяется после манипуляций с пикселями.
  • drawImage(): Рисует изображение, видео или другой canvas на холст. Подходит для копирования целых изображений без поэлементного анализа.

Аналоги в других языках программирования

Python (библиотека Pillow):

from PIL import Image
img = Image.open('image.jpg')
pixels = img.load()
print(pixels[0, 0])  # RGB значение
(255, 128, 64)

PHP (библиотека GD):

$img = imagecreatefromjpeg('image.jpg');
$color = imagecolorat($img, 0, 0);
$r = ($color >> 16) & 0xFF;
$g = ($color >> 8) & 0xFF;
$b = $color & 0xFF;
echo "$r, $g, $b";
255, 128, 64

Основное отличие - в этих языках часто используются двумерные координаты для доступа к пикселям, в отличие от одномерного массива в JavaScript.

Типичные ошибки

Ошибка безопасности из-за CORS:

// Изображение загружено с другого домена без CORS заголовков
ctx.drawImage(externalImage, 0, 0);
const data = ctx.getImageData(0, 0, 100, 100); // Ошибка
// DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D'

Выход за границы холста:

const canvas = document.createElement('canvas');
canvas.width = 100;
canvas.height = 100;
const ctx = canvas.getContext('2d');
const data = ctx.getImageData(90, 90, 20, 20); // Запрашивается область за пределами
// Возвращается ImageData, но пиксели вне холста прозрачные (0,0,0,0)

Изменения в последних версиях

Спецификация Canvas API постоянно развивается. В современных браузерах были добавлены:

  • Поддержка цветовых пространств через параметр colorSpace в getImageData() и putImageData().
  • Метод getImageData() теперь работает в Web Workers с OffscreenCanvas, что позволяет обрабатывать изображения в фоновом потоке.
  • Улучшения производительности при работе с большими массивами пикселей.

Расширенные примеры использования

Применение сепии через манипуляцию пикселями:

Пример javascript
function applySepia(imageData) {
  const data = imageData.data;
  for(let i = 0; i < data.length; i += 4) {
    const r = data[i];
    const g = data[i + 1];
    const b = data[i + 2];
    data[i] = Math.min(255, r * 0.393 + g * 0.769 + b * 0.189);
    data[i + 1] = Math.min(255, r * 0.349 + g * 0.686 + b * 0.168);
    data[i + 2] = Math.min(255, r * 0.272 + g * 0.534 + b * 0.131);
  }
  return imageData;
}
// Использование
const originalData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const sepiaData = applySepia(originalData);
ctx.putImageData(sepiaData, 0, 0);

Обнаружение краев с помощью оператора Собеля:

Пример javascript
function detectEdges(imageData) {
  const width = imageData.width;
  const height = imageData.height;
  const data = imageData.data;
  const output = new Uint8ClampedArray(data.length);
  
  // Ядра Собеля
  const kernelX = [-1, 0, 1, -2, 0, 2, -1, 0, 1];
  const kernelY = [-1, -2, -1, 0, 0, 0, 1, 2, 1];
  
  for(let y = 1; y < height - 1; y++) {
    for(let x = 1; x < width - 1; x++) {
      let pixelX = 0, pixelY = 0;
      let idx = (y * width + x) * 4;
      
      // Свертка
      for(let ky = -1; ky <= 1; ky++) {
        for(let kx = -1; kx <= 1; kx++) {
          const kidx = ((y + ky) * width + (x + kx)) * 4;
          const luminance = (data[kidx] + data[kidx+1] + data[kidx+2]) / 3;
          const k = (ky + 1) * 3 + (kx + 1);
          pixelX += luminance * kernelX[k];
          pixelY += luminance * kernelY[k];
        }
      }
      
      const magnitude = Math.sqrt(pixelX * pixelX + pixelY * pixelY);
      const value = Math.min(255, magnitude);
      output[idx] = output[idx+1] = output[idx+2] = value;
      output[idx+3] = 255;
    }
  }
  
  return new ImageData(output, width, height);
}

JS getImageData function comments

En
GetImageData Returns an ImageData object representing the underlying pixel data for a specified portion of the canvas