2025-11-26     #article

Имитация пиксельных фото

О камере

Увидел пост про Pixless Camera и подумал, что такую стилизацию несложно повторить софтово.

Известные характеристики: разрешение 256×128, 64 цвета. Остальное только пытаться понять видеоанонса и примеров с сайта.

Первая попытка (провал)

Казалось, достаточно сжать и подрезать фотографию без сглаживания и заквантовать цвета до 64. Не тут-то было. Фотографии получаются почти обычными. Особенно на фото природы, где в 64 цвета влезает основная гамма. Вместо красивой стилизации у нас просто мелкий шакальный jpeg. Любые интерполяции кроме линейной делают ещё намного хуже.

Предположил, что если количество цветов слишком большое, то какое должно быть? Последовательным уменьшением дошёл до 8, но часто и этого было слишком много. Посчитал сам цвета из анонса, часто их было около 5. На результате стали протекать странные заливки, например лезвие топора в лесу становилось зелёными разводами с оборванными летающими пикселями, когда цветов стало слишком мало для отображения собственно топора, пня и деревьев. К тому же, рисунок становился всё более нечётким, состоящим из перемешанной россыпи.

Ещё немного рассмотрел видео и нашёл там признаки дизеринга. А именно - шахматный паттерн. В ImageMagick есть такой фильтр. Потенциально это позволяет выразить больше цветов малым набором. По всему изображению появляются повторяющиеся вкрапления и рисует "как бы цвет" двумя другими чередующимися. Но результат стал только хуже и ещё больше не похож на целевой. Поперебирал разные алгоритмы дизеринга, но это явно тупиковая идея. Зато узнал, что по умолчанию дизеринг как раз присутствует и его нужно явно отключить.

Вторая попытка (успех)

Снова вернулся к видео. На примерах мало цветов внутри одного кадра, но цвета между самими кадрами совершенно разные. Например, залив становился сильной голубой гаммы, а площадь розовой. Вот только таких цветов и близко не было на оригинале фотографии. Это точно не квантование. Палитра состоит не из цветов оригинала.

Ушёл не один час экспериментов, прежде чем понял, что они ремапят палитру документа на другую. Стал разбираться, как работает этот ремап, какие бывают палитры. Попал на сайт с палитрами для ретроигр. Там были файлы в нужном формате: по одному пикселю каждого цвета в одну линию. Ремап нужно делать до всех преобразований, когда картинка ещё "оригинал". Тогда на результате гораздо меньше мусорных пикселей.

При ремапе используется "Floyd-Steinberg dithering", если не указано иначе. Казалось бы, стоит его отключить заранее. Но при ремапе дизеринг работает более "органично", чем при квантовании. Наоборот, при отключении на некоторых фото появлялись нежелательные участки, залитые не тем цветом. Например, заилованный бетон становился чисто зелёным. Сохранение дизеринга сделает его смесью серых и зелёных пикселей, что гораздо красивее. Улучшений от отключения дизеринга не нашёл. Все фото либо такие же, либо хуже. Но можете поэкспериментировать, добавив -dither None перед -remap.

Полный порядок операций:

  1. Ремап на выбранную палитру;
  2. Убрать интерполяцию (преобразование будет линейное);
  3. Уменьшить изображение;
  4. Установить кадрирование по центру и обрезать до заданных пропорций;
  5. Увеличить изображение в 4-8 раз для удобства просмотра, иначе многие просмотрщики интерполируют его до мутной кляксы.

Результат сильно зависит от выбранной палитры. Если в ней совсем нет хоть сколько-то похожих цветов, конвертер подставит серый цвет. Поэтому для преобразования тёплых фото лучше использовать тёплые палитры и т.д. Как понял, в Pixless Camera используется одна палитра на 64 цвета для фото, но заложена далеко не одна. Программа как-то выбирает подходящую под кадр. Это я естественно не реализовал, остановился на одной универсальной old-z64-1x.png.

Программа

Архив программы под MacOS: pixless.zip . Возможно, подойдёт без изменений под Linux. Это всего лишь несколько последовательных преобразований в утилите ImageMagick над файлами из папки input с сохранением в output. В качестве аргументов принимает -w, -h, -s, -p: ширина, высота, масштабирование, файл палитры. Оптимальные параметры уже прописаны в коде.

Оставил в архиве четыре палитры, с которыми экспериментировал. Дополнительные можно взять с lospec.com . Подойдут любые малоцветные. Скачивать в размере PNG Image (1x).

Примеры результатов

Для отладки использовал уличные фотографии разного времени года, помещения, предметы, цифровые арты. Результат мне в целом понравился и посчитал "правильным".

Image Image

Image Image

Image Image

Image Image