Обработка изображений 2. Изображения. Простая трансформация
от aNNiMON
Работа с графикой
image processing, обработка изображений, javascript, js, flip, mirror, transpose, отражение, поворот
В этой статье реализуем отражение и поворот на 90 и 270 градусов уже для реального изображения. Но прежде, чем это сделать, разберёмся, что вообще из себя представляют изображения и как получить данные о них в JavaScript.
Содержание:
1. Введение
2. Изображения. Простая трансформация
3. Негатив, извлечение и инверсия каналов
4. Обесцвечивание
5. Цветовые модели
6. Яркость, насыщенность, контрастность, гамма-коррекция
7. Гистограмма
8. Масштабирование изображения
9. Размытие
10. Свёртка
Изображения
Здесь всё очень просто: изображение — это набор цветных точек, то есть пикселей. У изображения есть ширина и высота, а также другие параметры, о которых я расскажу потом.
Представить изображение можно в виде двумерного массива, тогда, чтобы получить нижний правый пиксель, просто отнимем единицу от ширины и высоты (помним же, что массивы индексируются с нуля и что обычно сначала получают строку, а потом уже столбец):
pixel = img[height - 1][width - 1].
И как бы такой способ представления не казался удобным, на практике очень часто изображение представляют в виде одномерного массива длиной width*height.
вы только посмотрите, что они сделали с Кенни
Нижний правый пиксель в таком случае получается так: pixel = img[img.length - 1], а чтобы получить пиксель по координате (x, y), нужно сместиться на y строк и x позиций: (y * width + x)
Получение пикселей из <img>
Чтобы получить массив пикселей из картинки в теге <img>, нужно:
1. Получить объект тега img
2. Получить или создать canvas
3. Задать размер канваса, чтобы он соответствовал размеру картинки
4. Отрисовать картинку.
- // <img id="image1" src="..." />
- // img = getImageData('image1');
- function getImageData(el) {
- const canvas = document.createElement('canvas');
- const context = canvas.getContext('2d');
- const img = document.getElementById(el);
- canvas.width = img.width;
- canvas.height = img.height;
- context.drawImage(img, 0, 0);
- return context.getImageData(0, 0, img.width, img.height);
- }
Однако, из-за ограничений безопасности, отрисовывать в канвасе можно те картинки, которые поддерживают CORS, либо кодировать изображение в base64. Я в примерах буду пользоваться вторым способом.
Отражение (flip) и поворот на 90° и 270°
Пока что мы не будем раскладывать пиксели на отдельные цветовые компоненты, потому что отражение и поворот картинки это манипуляция с позициями пикселей. Вспоминаем уроки информатики, где были задачи на работу с матрицами, транспонирование, вот это всё.
Отражение по горизонтали. В каждой позиции x рисуем пиксель из позиции (width - x - 1):
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- dst[y * width + x] = src[y * width + (width - x - 1)];
- }
- }
Отражение по вертикали. В каждой позиции y рисуем пиксель из позиции (height - y - 1):
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- dst[y * width + x] = src[(height - y - 1) * width + x];
- }
- }
Поворот на 90°. Здесь не забываем, что ширина станет высотой, а высота шириной, поэтому нужно создать новый канвас с нужными размерами.
- let newWidth = height;
- let newHeight = width;
- for (let y = 0; y < newHeight; y++) {
- for (let x = 0; x < newWidth; x++) {
- dst[y * newWidth + x] = src[(height - x - 1) * width + y];
- }
- }
Поворот на 270°:
- let newWidth = height;
- let newHeight = width;
- for (let y = 0; y < newHeight; y++) {
- for (let x = 0; x < newWidth; x++) {
- dst[y * newWidth + x] = src[x * width + y];
- }
- }
Реализацию отражения одновременно по горизонтали и вертикали я оставляю вам в качестве домашнего задания. В следующей статье будет ответ.
See the Pen Image processing 2 by aNNiMON (@aNNiMON) on CodePen.
3. Негатив, извлечение и инверсия каналов