Большинство программистов, работающих с изображениями, даже не подозревают, что их код выдаёт неверные результаты. Всё из-за гамма-коррекции — темы, которую обычно игнорируют в учебниках и на практике.
Человеческий глаз воспринимает яркость нелинейно. Разница по физической интенсивности между соседними полосками может быть одинаковой, но мы видим её неравномерно. Поэтому для хранения изображений придумали гамма-кодирование: вместо того чтобы хранить физически линейные значения (где на тёмные участки тратится слишком много точности), данные переводят в перцептивно линейное пространство. Так 256 оттенков на канал (8 бит) распределяются эффективнее.
Стандарт sRGB — де-факто для всех потребительских устройств и интернета. Он использует гамму примерно 2.2, то есть значение пикселя RGB(128,128,128) излучает не 50% света от RGB(255,255,255), а всего около 22%. Это нормально — так они и должны выглядеть для человеческого глаза.
Проблема возникает, когда начинаешь обрабатывать такие изображения напрямую, без преобразования в линейное пространство. Практически все алгоритмы — интерполяция градиентов, смешивание цветов, альфа-композитинг, ресайз, антиалиасинг — ожидают на входе линейные данные. Если скормить им sRGB-пиксели, результат будет нефизичным: тёмные переходы, странные оттенки, искажённая яркость.
Автор приводит конкретные примеры. Градиенты, посчитанные в sRGB, выглядят темнее и насыщеннее, чем должны. Смешивание цветов мягкой кистью даёт тёмные полосы. Альфа-блендинг — зелёный оттенок при наложении фотографий. Ресайз чёрно-белой шахматки в sRGB вместо ожидаемого 50% серого даёт неверный тон. Антиалиасинг текста делает буквы жирнее. В физически корректном рендеринге (PBR) игнорирование гаммы — главная причина «пластикового» CGI, особенно на коже.
Большинство софта делает неправильно: CSS-градиенты, Photoshop (до CS6 как минимум). Исключения — Krita и Pixelmator, которые обрабатывают гамму верно. SVG позволяет выбирать пространство.
Вывод один: перед любой обработкой нужно декодировать sRGB в линейное пространство (гамма-расширение), выполнить алгоритмы, а затем закодировать обратно. Если сомневаетесь — используйте sRGB, но всегда явно указывайте, в каком пространстве работаете.