Глюки PNG как искусство

97508458c9924bee942c2f017964da49.png

PNG – графический формат, который появился в далёком 1995 году и до сих пор широко используется. Его основными свойствами считаются сжатие без потерь и поддержка прозрачных пикселей. Однако японский программист и художник под ником UCNV заинтересован не уникальными свойствами этого формата, а тем, как заставить его художественно глючить.

Чтобы научиться внедрять глюки, нужно более тщательно изучить детали формата.

Контрольная сумма


Первым делом, следует обратить внимание на механизм генерации контрольной суммы по коду CRC32. Она используется для подтверждения повреждённых изображений. Если обнаружено повреждение, то приложение просмотра отказывается его отображать. Поэтому нельзя генерировать глюки простыми методами, просто повреждая бинарный файл. Другими словами, формат PNG трудно подвергнуть глюкам.

Нам придётся генерировать искажения в соответствии со спецификациями PNG. То есть мы должны декодировать CRC32, затем переписать данные, пересчитать контрольную сумму и добавить её к отредактированным данным.

Состояние


Затем смотрим на процесс перекодирования в PNG.

2cf0d197cfb44b26b6b943d3b21a821d.png

Каждое из четырёх состояний, указанных на диаграмме, может быть мишенью глюка. Но внедрение искажений в первое состояние (сырые данные) — это то же самое, что искажать BMP, в этом нет смысла, да и технически это не глюк PNG. Искажение в последнем состоянии не сработает из-за вышеупомянутой системы подсчёта контрольной суммы. Остаётся внедрение искажений во второе и третье состояния, то есть в фильтрованные данные и сжатые данные. Наиболее эффективны манипуляции с фильтрами, они действительно дают хороший эффект. С помощью хаков можно наглядно показать различия между фильтрами. Внедрение глюков в состояние сжатых данных тоже имеет мало смысла. В PNG используется компрессия Deflate, и какие-то искажения выглядят просто как белый снег.

Есть и другие элементы, кроме названных, которые могут повлиять на внешний вид итоговой картинки. Это прозрачные пиксели и т.д.

Пять фильтров


Фактор, который больше всего влияет на внешний вид картинки после внедрения хака, это фильтры. Они конвертируют несжатые пиксельные данные по каждой линии, используя определённые алгоритмы, чтобы увеличить эффективность сжатия. Есть всего пять типов фильтров, включая четыре алгоритма под названием Sub, Up, Average и Paeth, а также None (то есть фильтры не применяются). Изображения PNG обычно сжимаются после того как наиболее эффективный фильтр применён по каждой линии. Поэтому обычно в готовом изображении PNG использованы все пять фильтров.

Пять фильтров влияют только на степень компрессии, то есть сама картинка не изменяется в зависимости от того, какой из фильтров был использован. Однако явное искажение итогового результата происходит в случае повреждения отфильтрованных данных. Трудно понять разницу между фильтрами, если используются все пять из них. Но эта разница становится очевидной, когда мы внедряем глюк, а при этом был использован один и тот же фильтр для каждой линии.

Каждый из фильтров отвечает за свою часть той красоты, которую мы увидим на искажённых PNG.

Глюки на практике


Оригинальное изображение
2da08a24d7b848a9b3b1fb17f7b6577d.jpg

Искажённое изображение
e78b7c2380f74e1091d0e686c40e7375.jpg

Вверху мы видим пример глюка фильтра. В оригинальном изображении при сжатии использовались оптимизированные фильтры для каждой линии. При этом применялись все пять фильтров.

Разница между фильтрами


Вот искажённое изображение, предварительно отфильтрованное фильтром None (то есть без фильтров).

e6ab7d5cafb14867890c19ccf4c1b35b.jpg

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

Увеличенный фрагмент изображения
9bc51769dda3471e8c8e67fa72eedc8e.png

Теперь искажённое изображение, предварительно отфильтрованное Sub.

1b2342c93fa243d59baa74becc6c2063.jpg

Если применить этот фильтр, то пиксель переписывает себя, отсылаясь к рядом стоящему пикселю. Вот почему проявляется уклон в правую сторону.

Увеличенный фрагмент изображения
905e3f9c0cb6426b9ee501e0f7293951.png

Далее искажённое изображение, предварительно отфильтрованное Up.

88fd7cf7a21f4171a6eb60e32d87a7db.jpg

Эффект аналогичен Sub, только направлен по вертикали.

Увеличенный фрагмент изображения
ce0cebf2e29e4f80baa5ff4204e98252.png

Искажённое изображение, предварительно отфильтрованное Average.

5a06229aaec44fc2a6f34c0518f9ffb6.jpg

Фильтр Average отвечает за диагональное направление. Он генерирует метеороподобные тени, которые начинаются с повреждённого пикселя. Эффект мягкого перехода — также одно из последствий. Cамый красивый глюк.

Увеличенный фрагмент изображения
a6e0c92ceb184c0c9409287aa7e343a1.png

Искажённое изображение, предварительно отфильтрованное Paeth.

3ea303b5d27e49529d21a78bdc877e98.jpg

В фильтре Paeth реализован самый сложный алгоритм, по сравнению со всеми остальными фильтрами. Эффект затрагивает обширные области изображения даже при небольшом количестве искажённых пикселей. Оригинальное изображение сохраняется, но при этом интенсивно уничтожается.

Увеличенный фрагмент изображения
9c00d547e562463cb14175c3ed0fd43f.png

PNG – относительно простой формат, в сравнении с JPEG и более современными форматами. Алгоритмы фильтров как игрушки, а метод сжатия тоже довольно простой. Тем не менее, он проявляет довольно интересное разнообразие глюков.

Японский программист выложил Ruby-библиотеку PNGlitch, которая помогает внедрять глюки и перезаписывать контрольную сумму. На его странице можно посмотреть каталог работ и получить инструкции, как пользоваться библиотекой.

© Geektimes