PNG – графический формат, который появился в далёком 1995 году и до сих пор широко используется. Его основными свойствами считаются сжатие без потерь и поддержка прозрачных пикселей. Однако японский программист и художник под ником UCNV заинтересован не уникальными свойствами этого формата, а тем, как заставить его художественно глючить.
Чтобы научиться внедрять глюки, нужно более тщательно изучить детали формата.
Контрольная сумма
Первым делом, следует обратить внимание на механизм генерации контрольной суммы по коду CRC32. Она используется для подтверждения повреждённых изображений. Если обнаружено повреждение, то приложение просмотра отказывается его отображать. Поэтому нельзя генерировать глюки простыми методами, просто повреждая бинарный файл. Другими словами, формат PNG трудно подвергнуть глюкам.
Нам придётся генерировать искажения в соответствии со спецификациями PNG. То есть мы должны декодировать CRC32, затем переписать данные, пересчитать контрольную сумму и добавить её к отредактированным данным.
Состояние
Затем смотрим на процесс перекодирования в PNG.
Каждое из четырёх состояний, указанных на диаграмме, может быть мишенью глюка. Но внедрение искажений в первое состояние (сырые данные) — это то же самое, что искажать BMP, в этом нет смысла, да и технически это не глюк PNG. Искажение в последнем состоянии не сработает из-за вышеупомянутой системы подсчёта контрольной суммы. Остаётся внедрение искажений во второе и третье состояния, то есть в фильтрованные данные и сжатые данные. Наиболее эффективны манипуляции с фильтрами, они действительно дают хороший эффект. С помощью хаков можно наглядно показать различия между фильтрами. Внедрение глюков в состояние сжатых данных тоже имеет мало смысла. В PNG используется компрессия Deflate, и какие-то искажения выглядят просто как белый снег.
Есть и другие элементы, кроме названных, которые могут повлиять на внешний вид итоговой картинки. Это прозрачные пиксели и т.д.
Пять фильтров
Фактор, который больше всего влияет на внешний вид картинки после внедрения хака, это фильтры. Они конвертируют несжатые пиксельные данные по каждой линии, используя определённые алгоритмы, чтобы увеличить эффективность сжатия. Есть всего пять типов фильтров, включая четыре алгоритма под названием Sub, Up, Average и Paeth, а также None (то есть фильтры не применяются). Изображения PNG обычно сжимаются после того как наиболее эффективный фильтр применён по каждой линии. Поэтому обычно в готовом изображении PNG использованы все пять фильтров.
Пять фильтров влияют только на степень компрессии, то есть сама картинка не изменяется в зависимости от того, какой из фильтров был использован. Однако явное искажение итогового результата происходит в случае повреждения отфильтрованных данных. Трудно понять разницу между фильтрами, если используются все пять из них. Но эта разница становится очевидной, когда мы внедряем глюк, а при этом был использован один и тот же фильтр для каждой линии.
Каждый из фильтров отвечает за свою часть той красоты, которую мы увидим на искажённых PNG.
Глюки на практике
Оригинальное изображение
Искажённое изображение
Вверху мы видим пример глюка фильтра. В оригинальном изображении при сжатии использовались оптимизированные фильтры для каждой линии. При этом применялись все пять фильтров.
Разница между фильтрами
Вот искажённое изображение, предварительно отфильтрованное фильтром None (то есть без фильтров).
Поскольку фильтры не применяются, то данное искажение приравнивается к искажению в сырых данных. Каждый пиксель изолирован и не имеет никакого отношения к соседним. Поэтому единственный изменённый байт не имеет практически никакого эффекта.
Увеличенный фрагмент изображения
Теперь искажённое изображение, предварительно отфильтрованное Sub.
Если применить этот фильтр, то пиксель переписывает себя, отсылаясь к рядом стоящему пикселю. Вот почему проявляется уклон в правую сторону.
Увеличенный фрагмент изображения
Далее искажённое изображение, предварительно отфильтрованное Up.
Эффект аналогичен Sub, только направлен по вертикали.
Увеличенный фрагмент изображения
Искажённое изображение, предварительно отфильтрованное Average.
Фильтр Average отвечает за диагональное направление. Он генерирует метеороподобные тени, которые начинаются с повреждённого пикселя. Эффект мягкого перехода — также одно из последствий. Cамый красивый глюк.
Увеличенный фрагмент изображения
Искажённое изображение, предварительно отфильтрованное Paeth.
В фильтре Paeth реализован самый сложный алгоритм, по сравнению со всеми остальными фильтрами. Эффект затрагивает обширные области изображения даже при небольшом количестве искажённых пикселей. Оригинальное изображение сохраняется, но при этом интенсивно уничтожается.
Увеличенный фрагмент изображения
PNG – относительно простой формат, в сравнении с JPEG и более современными форматами. Алгоритмы фильтров как игрушки, а метод сжатия тоже довольно простой. Тем не менее, он проявляет довольно интересное разнообразие глюков.
Японский программист выложил Ruby-библиотеку PNGlitch, которая помогает внедрять глюки и перезаписывать контрольную сумму. На его странице можно посмотреть каталог работ и получить инструкции, как пользоваться библиотекой.