Редактирование пикселей

Последнее обновление: 06.11.2023

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

Метод getImageData()

Метод getImageData() позволяет извлечь из canvas какую-либо часть изображеня. Он имеет следующее определение:

getImageData(sx, sy, sw, sh);

Здесь sx и sy - координаты верхнего левого угла области, из которой извлекаются данные на canvas, а sw и sh - соотвественно ширина и высота этой области.

Данные из определенной этими параметрами области извлекаются в виде объекта ImageData, который потом используется для манипуляции пикселями.

Пример использования:

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
				
const img = new Image();
img.src = "forest.png";
img.onload = function() {
	context.drawImage(img, 0, 0);
	const imageData = context.getImageData(0,0, 100, 100);
};

Все данные об изображении в объекте ImageData хранятся в массиве data. Каждый пиксель на canvas характеризуется четырьмя компонентами в формате RGBA: красной, зеленой, синей компонентой, которые устанавливают цвет, и альфа-компонентой, которая устанавливает прозрачность. Каждая компонента принимает значени от 0 до 255. И чтобы получить значения цвета для самого первого пикселя в ImageData, нам надо последовательно получить четыре значения из массива data:

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
				
const img = new Image();
img.src = "dubi.png";
img.onload = function() {
				
	context.drawImage(img, 0, 0);
	const imageData = context.getImageData(0,0, 100, 100);
	const red = imageData.data[0];	// компонента красного цвета
	const green = imageData.data[1];	// компонента зеленого цвета
	const blue = imageData.data[2];	// компонента синего цвета
	const alpha = imageData.data[3];	// компонента прозрачности
};

В данном случае мы получаем информацию о самом первом пикселе, который находится в самом верхнем левом углу, то есть имеет координаты x=0 и y=0.

Чтобы получить информацию о втором пикселе, который имеет координаты x=1 и y=0, нам надо получить следующие четыре значения из массива data:

imageData.data[4];	// компонента красного цвета
imageData.data[5];	// компонента зеленого цвета
imageData.data[6];	// компонента синего цвета
imageData.data[7];	// компонента прозрачности

И так далее мы можем получить информацию обо всех пикселях.

Метод putImageData()

Метод putImageData() устанавливает на canvas новые данные. Этот метод имеет следующие виды:

putImageData(imageData, dx, dy)
putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)

Параметры dx и dy указывают координаты верхнего левого угла условного прямоугольника imageData, в который размещается на canvas.

Дополнительные параметры dirtyX и dirtyY указывают соотвественно на координаты X и Y левого угла прямоугольной области, которая будет извлекаться из полученного изображения. А параметры dirtyWidth и dirtyHeight задают соотвественно ширину и высоту этой области.

Используем методы getImageData() и putImageData() для преобразования изображения:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>METANIT.COM</title>
</head>
<body>
<canvas id="canvas" width="700" height="300"></canvas>
<script>
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

const img = new Image();
img.src = "forest3.png";
img.onload = function() {
                 
    context.drawImage(img, 0, 0);
    const imageData = context.getImageData(0,0, img.width, img.height);
    let red, green, blue, grayscale;
                 
    for (let i = 0; i < imageData.data.length; i += 4) {
        red = imageData.data[i]; // получаем компоненту красного цвета
        green = imageData.data[i + 1];  // получаем компоненту зеленого цвета
    	blue = imageData.data[i + 2];   // получаем компоненту синего цвета
        grayscale = red * 0.3 + green * 0.59 + blue * 0.11; // получаем серый фон
        imageData.data[i] = grayscale;  // установка серого цвета
        imageData.data[i + 1] = grayscale;
        imageData.data[i + 2] = grayscale;
    }   
    context.putImageData(imageData, img.width + 10, 0);
};
</script>
</body>
</html>
Трансформация изображения в серое на canvas в JavaScript

Ключевым участком кода здесь является цикл, в котором и происходит преобразование изображения в серое:

let red, green, blue, grayscale;
                 
for (let i = 0; i < imageData.data.length; i += 4) {
    red = imageData.data[i]; // получаем компоненту красного цвета
    green = imageData.data[i + 1];  // получаем компоненту зеленого цвета
    blue = imageData.data[i + 2];   // получаем компоненту синего цвета
    grayscale = red * 0.3 + green * 0.59 + blue * 0.11; // получаем серый фон
    imageData.data[i] = grayscale;  // установка серого цвета
    imageData.data[i + 1] = grayscale;
    imageData.data[i + 2] = grayscale;
}  

Здесь мы перемещаемся по всему массиву imageData.data, обрабатывая за раз четыре элемента, которые и представляют отдельный пиксель. При этом учитываются только три элемента, поскольку компонента прозрачности в данном случае нас не интересует.

Сначала мы получаем компоненты RGB. Затем, применяя математическую формулу, преобразуем значения RGB в серый цвет. И в конце серый цвет устанавливается для элементов пикселя.

Вопросы безопасности

Если мы попробуем просто кинуть файл веб-страницы с выше описанным кодом в браузер Google Chrome или попытаемся открыть файл по двойному клику, то Google Chrome не отобразит нам преобразованное серое изображение в связи с политикой браузера. Хотя в других браузерах, как Firefox или Microsoft Edge все может быть нормально. Дело в том, что в Google Chrome не позволяет манипулировать изображением сайта из одного домена пользователю из другого домена. По сути, когда мы загружаем файл по протоколу file:// (просто кинув файл в браузер или по двойному клику), браузер рассматривает пользователя и открытую веб-страницу как разные домены.

Если веб-страница будет расположена на веб-сервере и загружена по протоколу http, как это обычно бывает, то, конечно, проблемы не возникнет, так как пользователь и сайт будут работать в рамках одного домена. Но для тестирования опять же либо придется использовать веб-сервер, либо изменить соответствующим образом настройки браузера Google Chrome.

Метод createImageData()

Метод createImageData() создает новый объект ImageData, который затем может использоваться на canvas. Метод createImageData() имеет две формы:

createImageData(width, height);
createImageData(imagedata);

Первая форма принимает параметры width и height, которые устанавливают соотвественно ширину и высоту создаваемого объекта ImageData.

Вторая форма принимает в качестве параметра другой объект ImageData, по которому будет создан новый объект ImageData.

Пример использования:

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

const img = new Image();
img.src = "river2.png";
img.onload = function() {
				
	context.drawImage(img, 0, 0);
	const imageData = context.getImageData(0,0, img.width, img.height);
	const newImageData = context.createImageData(imageData);
				
	for (let i = 0; i < newImageData.data.length; i++) {
				
		newImageData.data[i] = imageData.data[i];
		// если это альфа-компонента
		if( (i+1)%4===0){
						
			newImageData.data[i] = 120;
		}
	}
	context.putImageData(newImageData, img.width + 10, 0);
};

В данном случае создаем новый объект newImageData, в этот объект копируем все данные из текущего imageData, который представляет изображение на canvas. При этом при копировании значения альфа-компоненты, которая отвечает за прозрачность, устанавливаем ей значение 120, то есть делаем пиксель полупрозрачным.

Эффекты изображения на canvas в JavaScript
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850