Обработка изображений 3. Негатив, извлечение и инверсия каналов
от aNNiMON
Работа с графикой
image processing, обработка изображений, javascript, js, инверсия, негатив, negate, invert, extract channel
В этой статье разделяем изображение на цветовые компоненты, делаем эффект Негатив и инвертируем каналы по отдельности. Наконец-то будет манипуляция с RGB-компонентами!
Содержание:
1. Введение
2. Изображения. Простая трансформация
3. Негатив, извлечение и инверсия каналов
4. Обесцвечивание
5. Цветовые модели
6. Яркость, насыщенность, контрастность, гамма-коррекция
7. Гистограмма
8. Масштабирование изображения
9. Размытие
10. Свёртка
Домашнее заданиеВернёмся к домашнему заданию, которое я дал в прошлой статье. Необходимо было реализовать отражение одновременно по горизонтали и по вертикали. Вот решение:
- for (let i = 0; i < dst.length; i++) {
- dst[i] = src[dst.length - i - 1];
- }
https://codepen.io/aNNiMON/pen/EMYyVJ
Извлечение канала (extract channel)Разделим полноценное изображение на четыре отдельных изображения.
Первое будет содержать только красные компоненты, второе только зелёные, третье только синие:
- // Red
- for (let i = 0; i < dst.length; i++) {
- let r = src[i] & 0xFF;
- dst[i] = 0xFF000000 | r;
- }
- // Green
- for (let i = 0; i < dst.length; i++) {
- let g = (src[i] >> 8) & 0xFF;
- dst[i] = 0xFF000000 | (g << 8);
- }
- // Blue
- for (let i = 0; i < dst.length; i++) {
- let b = (src[i] >> 16) & 0xFF;
- dst[i] = 0xFF000000 | (b << 16);
- }
Можно было бы написать так:
- dst[i] = (255 << 24) | (b << 16);
Четвёртое изображение будет содержать только канал прозрачности, цвета будут чёрными:
- for (let i = 0; i < dst.length; i++) {
- let a = (src[i] >> 24) & 0xFF;
- dst[i] = (a << 24);
- }
Для демонстрации возьмём фотографию, которую любезно нам предоставил vl@volk:
Так как на фотографии преобладает зелёный цвет, то зелёный канал ярче и детальнее остальных.
Яркие светлые участки видны на всех каналах, потому что они близки к оттенкам серого, а серый — объединение всех трёх цветов в равных пропорциях.
Вот другой пример (оригинал фотографии):
Первое, что бросается в глаза — красная подсветка на колесе обозрения. Она отчётливо видна на красном канале, и практически незаметна на зелёном и синем. Только там, где красный переходит в более светлый, появляются и зелёный, и синий цвет.
Жёлтое отражение на дороге хорошо видно на красном и зелёном каналах, потому что смешение этих цветов даёт жёлтый цвет.
Домашнее задание
Сделайте так, чтобы красный, зелёный и синий каналы выводились в оттенках серого.
See the Pen Image processing 3.1. Channels by aNNiMON (@aNNiMON) on CodePen.
Негатив и инверсия каналовДля реализации эффекта Негатив, нужно инвертировать каналы R, G и B. Чёрный (0,0,0) должен превратиться в белый (255,255,255) и наоборот.
- for (let i = 0; i < dst.length; i++) {
- let r = src[i] & 0xFF;
- let g = (src[i] >> 8) & 0xFF;
- let b = (src[i] >> 16) & 0xFF;
- let a = (src[i] >> 24) & 0xFF;
- r = 255 - r;
- g = 255 - g;
- b = 255 - b;
- dst[i] = (src[i] & 0xFF000000) | (b << 16) | (g << 8) | r;
- }
Также реализуем возможность инвертировать отдельный канал, поставив соответствующую галочку.
- let invRed = isChecked('cbRed');
- let invGreen = isChecked('cbGreen');
- let invBlue = isChecked('cbBlue');
- let invAlpha = isChecked('cbAlpha');
- for (let i = 0; i < dst.length; i++) {
- let r = src[i] & 0xFF;
- let g = (src[i] >> 8) & 0xFF;
- let b = (src[i] >> 16) & 0xFF;
- let a = (src[i] >> 24) & 0xFF;
- if (invRed) r = 255 - r;
- if (invGreen) g = 255 - g;
- if (invBlue) b = 255 - b;
- if (invAlpha) a = 255 - a;
- dst[i] = (a << 24) | (b << 16) | (g << 8) | r;
- }
- function isChecked(el) {
- return document.getElementById(el).checked;
- }
See the Pen Image processing 3.2. Negate filter by aNNiMON (@aNNiMON) on CodePen.
4. Обесцвечивание