Обработка изображений 6. Яркость, насыщенность, контрастность, гамма-коррекция
от aNNiMON

Содержание:
1. Введение
2. Изображения. Простая трансформация
3. Негатив, извлечение и инверсия каналов
4. Обесцвечивание
5. Цветовые модели
6. Яркость, насыщенность, контрастность, гамма-коррекция
7. Гистограмма
8. Масштабирование изображения
9. Размытие
10. Свёртка
ЯркостьЕё мы уже рассматривали, просто вспомним ещё раз.
See the Pen Image processing 6.1. Brightness by aNNiMON (@aNNiMON) on CodePen.

НасыщенностьДля регулировки насыщенности не обязательно переходить к цветовой модели HSV, менять значения и затем снова возвращаться к модели RGB. Можно обойтись обычными расчётами разницы цветовых компонент и значения серого:
- 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 gray = (r * 0.2126 + g * 0.7152 + b * 0.0722);
- r += (r - gray) * value / 255;
- g += (g - gray) * value / 255;
- b += (b - gray) * value / 255;
- if (r > 255) r = 255;
- else if (r < 0) r = 0;
- if (g > 255) g = 255;
- else if (g < 0) g = 0;
- if (b > 255) b = 255;
- else if (b < 0) b = 0;
- dst[i] = (src[i] & 0xFF000000) | (b << 16) | (g << 8) | r;
- }
See the Pen Image processing 6.2. Saturation by aNNiMON (@aNNiMON) on CodePen.
В коде примера я изменил value / 255 на value / max, где max = (value < 0) ? 255 : 128.Сделано это лишь для того, чтобы повысить максимальную насыщенность. Попробуйте оба варианта, либо уменьшите 128 и выкрутите насыщенность на максимум.
В отличие от перехода к HSV, этот способ даёт больше точности и плавности. В Photoshop есть коррекция Вибрация, которая делает так же. Поэтому, не советую использовать в фотошопе Цветовой тон/Насыщенность только лишь для изменения насыщенности.

КонтрастностьКонтрастность это разница между максимальной и минимальной яркостью на изображении.
Давайте ещё раз посмотрим на формулу подсчёта значения цветовых компонент при изменении насыщенности из предыдущего примера:
- let gray = (r * 0.2126 + g * 0.7152 + b * 0.0722);
- r += (r - gray) * value / 255;
- g += (g - gray) * value / 255;
- b += (b - gray) * value / 255;
- let gray = 0;
- 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;
- gray += (r * 0.2126 + g * 0.7152 + b * 0.0722);
- }
- gray /= dst.length;
- 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;
- r += (r - gray) * delta / 255;
- g += (g - gray) * delta / 255;
- b += (b - gray) * delta / 255;
- if (r > 255) r = 255;
- else if (r < 0) r = 0;
- if (g > 255) g = 255;
- else if (g < 0) g = 0;
- if (b > 255) b = 255;
- else if (b < 0) b = 0;
- dst[i] = (src[i] & 0xFF000000) | (b << 16) | (g << 8) | r;
- }
See the Pen Image processing 6.3. Contrast by aNNiMON (@aNNiMON) on CodePen.

Гамма-коррекция
Гамма задаёт отношение между числовым значением яркости пикселя и его фактической яркостью. Наше зрение воспринимает яркость нелинейно и более чувствительно к тёмным тонам, нежели к светлым. Сенсор цифровой камеры, напротив, воспринимает любую яркость линейно.

Применение гамма-коррекции как раз и позволяет перейти от цифрового представления яркости к яркости, правильно воспринимаемой человеком, и наоборот.
Обычно для гамма-коррекции применяется простая степенная функция:
- let gamma = parseInt($("#rangeGamma").val()); // 0.1 ~ 6.0
- let level = 1.0 / (gamma / 100.0);
- let pow = [];
- for (let i = 0; i < 256; i++) {
- let value = (255 * Math.pow(i / 255.0, level) + 0.5);
- if (value > 255) value = 255;
- else if (value < 0) value = 0;
- else value = Math.floor(value);
- pow.push(value);
- }
- 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;
- r = pow[r];
- g = pow[g];
- b = pow[b];
- dst[i] = (src[i] & 0xFF000000) | (b << 16) | (g << 8) | r;
- }
See the Pen Image processing 6.4. Gamma by aNNiMON (@aNNiMON) on CodePen.
Благодаря гамма-коррекции, на тёмных фотографиях могут проявиться незаметные до этого детали.


7. Гистограмма