Структура файла png – PNG — not GIF! / Хабр

PNG — not GIF! / Хабр

Доброго времени суток!
Вам когда-нибудь хотелось узнать как устроены файлы PNG? Нет? А я все равно расскажу.
Формат PNG(Portable Network Graphics) был изобретен в 1995 году, чтобы стать заменой GIF, а уже в 1996, с выходом версии 1.0, он был рекомендован W3C, в качестве полноправного сетевого формата. На сегодняшний день PNG является одним из основных форматов веб-графики.

Под катом вы найдете общее описание строения PNG-файла, некоторое количество картинок-схем, препарирование в hex-редакторе, и, конечно, ссылку на спецификацию.
Общее строение

Структура PNG в самом общем виде представлена на следующем рисунке.

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

Подпись PNG-файла всегда одинакова, состоит из 8 байт, и представляет собой (в hex-записи)
89 50 4E 47 0D 0A 1A 0A

Что же это означает?
  • 89 — non-ASCII символ. Препятствует распознаванию PNG, как текстового файла, и наоборот.
  • 50 4E 47 — PNG в ASCII записи.
  • 0D 0A — CRLF (Carriage-return, Line-feed), DOS-style перевод строки.
  • 1A — останавливает вывод файла в DOS режиме (end-of-file), чтобы вам не вываливалось многокилобайтное изображение в текстовом виде.
  • 0A — LF, Unix-style перевод строки.
Chunks

Чанки — это блоки данных, из которых состоит файл. Каждый чанк состоит из 4 секций.

Разберем эти секции по порядку.
Длина

Ну, с длиной вроде все ясно. Просто числовое значение длины блока данных.
Тип (имя)

С типом немного поинтересней. Тип представляет собой 4 чувствительных к регистру ASCII-символа. Регистры символов (пятый бит в числовой записи символа) в имени чанка различаются неспроста — это флаги, которые сообщают декодеру некоторую дополнительную информацию.
  • Регистр первого символа определяет является ли данный чанк критическим(верхний регистр) или вспомогательным(нижний регистр). Критические чанки должны распознаваться каждым декодером. Если декодер встречает критический чанк, тип которого не может распознать, он обязан завершить выполнение с ошибкой.
  • Регистр второго символа задает «публичность»(верхний регистр) или «приватность»(нижний регистр) чанка. «Публичные» чанки — официальные, задокументированные, распознаваемые большинством декодеров. Но если вдруг вам для каких-то своих нужд понадобится кодировать специфическую информацию, то просто в имени чанка сделайте второй символ маленьким.
  • Регистр третьего символа оставлен для будущих свершений. Предполагается, что он будет использоваться для дифференциации различных версий стандарта. Для версий 1.0 и 1.1 третий символ должен быть большим. Если он (внезапно!) оказался маленьким, все нынешние декодеры должны поступать с чанком, так же как и с любым другим не распознанным (то есть выходить с ошибкой если чанк критический, или пропускать в противном случае).
  • Регистр же четвертого символа означает возможность копирования данного чанка редакторами, которые не могут его распознать. Если регистр нижний, чанк может быть скопирован, вне зависимости от степени модификации файла, иначе (верхний регистр) он копируется только в случае, когда при модификации не были затронуты никакие критические чанки.

Для лучшего понимания, давайте разберем флаги на примере чанка, содержащего текст.

Ниже приведен список типов чанков с краткими пояснениями.
Критические чанки

  • IHDR — заголовок файла, содержит основную информацию о изображении. Обязан быть первым чанком.
  • PLTE — палитра, список цветов.
  • IDAT — содержит, собственно, изображение. Рисунок можно разбить на несколько IDAT чанков, для потоковой передачи. В каждом файле должен быть хотя бы один IDAT чанк.
  • IEND — завершающий чанк, обязан быть последним в файле.

Вспомогательные чанки

  • bKGD — этот чанк задает основной фоновый цвет.
  • cHRM используется для задания CIE 1931 цветового пространства.
  • gAMA — определяет гамму.
  • hIST — в этом чанке может храниться гистограмма или общее содержание каждого цвета в изображении.
  • iCCP — цветовой профиль ICC
  • iTXt — содержит текст в UTF-8, возможно сжатый, с необязательной языковой меткой. iTXt чанк с ключевым словом ‘XML:com.adobe.xmp’ может содержать Extensible Metadata Platform (XMP).
  • pHYs — содержит предполагаемый размер пикселя и/или отношение сторон изображения.
  • sBIT (significant bits) — определяет «цветовую точность» (color-accuracy) изображения (черно-белое, полный цвет, черно-белое с прозрачностью и т.д.), для более простого декодирования.
  • sPLT — предлагает палитру для использования, если полный спектр цветов недоступен.
  • sRGB — свидетельствует о использовании стандартной sRGB схемы.
  • sTER — индикатор стереоскопических изображений.
  • tEXt — может содержать текст в ISO/IEC 8859-1 формате, с одной name=value парой для каждого чанка.
  • tIME — хранит дату последнего изменения изображения.
  • tRNS — содержит информацию о прозрачности.
  • zTXt — сжатый текст, с теми же ограничениям, что и tEXt.

Более подробную информацию можно найти в спецификации.
CRC

Контрольная сумма CRC-32. Кстати на днях был топик о ее подсчете в Windows.
Минимальный PNG

С общей структурой разобрались. Теперь разберем содержание обязательных чанков. Но какие из них обязательные (не критические, критические обязаны распознаваться декодером, а не присутствовать в каждом файле), и как выглядит минимальный PNG-файл? А вот как:
IHDR

Блок данных в IHDR содержит следующие поля:
  • Ширина, 4 байта
  • Высота, 4 байта
  • Битовая глубина (bit depth), определяет количество бит на каждый сэмпл(не пиксель), 1 байт
  • Тип цвета, состоит из 3 флагов 1 (используется палитра), 2 (используется цвет, не монохромное изображение), and 4 (присутствует альфа-канал), 1 байт
  • Метод сжатия. На данный момент доступно только значение 0 — сжатие по алгоритму deflate. Если значение отлично от 0, чанк считается нераспознанным, и декодер рапортует об ошибке. 1 байт
  • Метод фильтрации. Так же, как и в случае сжатия, на данный момент может быть только нулем. 1 байт
  • Interlace(переплетение) метод. Определяет порядок передачи данных. На данный момент доступно 2 значения: 0 (no interlace) и 1 (Adam7 interlace). 1 байт

Adam7 interlacing прекрасно демонстрирует картинка из википедии (да-да, GIF в статье про PNG):
IEND

Сигнализирует о конце файла, блок данных этого чанка не содержит ничего.
IDAT

Содержит данные, закодированные, в соответствии с полем метода сжатия в заголовке. Алгоритм декодирования выходит за рамки данной статьи (однако если будут желающие, может появиться в следующей), но в довольно хорошо (и по-русски) описан здесь.

Таким образом, простейший PNG-файл (на примере ) выглядит следующим образом.

Заключение

При написании данной статьи я ставил своей задачей дать читателю общие знания о строении PNG-файла, для более глубокого понимания рекомендуется читать спецификации.

Топик на хабре про строение JPEG: habrahabr.ru/blogs/algorithm/102521
Топик на хабре про строение GIF: habrahabr.ru/blogs/algorithm/127083

Спасибо за внимание, буду рад любой критике!

habr.com

«Черновое восстановление» (Часть 2: Анализ форматов)

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

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

Формат BMP

Описание формата можно найти, например, на сайте Microsoft или в Wikipedia (русская и английская). Если оставить только значимые для нас подробности, то файл BMP выглядит следующим образом:

Упрощенная структура файл BMP

Где Bitmap File Header – это структура следующего вида:

Здесь важно, что

  • поле bfType должно всегда иметь значение «BM» — это та самая сигнатура на основе которой мы задавали шаблон GREP в прошлой статье;
  • bfSize содержит полный размер файла;
  • bfReserved1 и bfReserved2 должны содержать нули в текущих версиях формата;
  • bfOffBits — содержит смещение к данным изображения.

Благодаря заголовку мы можем:

  • определить начало BMP файла, проверив значение bfType, bfReserved1 и bfReserved2;
  • узнать полный размер файла из поля bfSize;

Далее идет DIB Header. В зависимости от версии формата это могут быть разные структуры, но все они достаточно похожи, рассмотрим BITMAPINFOHEADER:


С помощью полей этой структуры можно выполнить дополнительные проверки, которые снизят шанс ложного срабатывания:

  • biSize — содержит точный размер структуры BITMAPINFOHEADER;
  • biBitCount – количество бит используемых для хранения одного пикселя, не может быть произвольным, а только из множества [0, 1, 4, 8, 16, 24, 32];

и так далее.

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

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

Формат PNG

PNG – еще один формат хранения растровых изображений, но уже со сжатием (но без потери качества как в jpeg). Его спецификацию можно найти на сайте W3C. Она занимает не один десяток печатных страниц. Однако, для восстановления данных достаточно знать совсем немного.

Любой файл PNG начинается с последовательности из 8 байт: 89 50 4E 47 0D 0A 1A 0A.

Затем идет последовательность chunk’ов — кусочков на которые разбит весь png файл.

Упрощенная структура файла PNG

Структура chunk’а:

Структура PNG Chunk

То есть, для каждого chunk’а указаны:

  • размер данных chunk, если пустой, то это 0;
  • тип – 4 ASCII символа;
  • собственно данные chunk’а, если есть;
  • контрольная сумма, которая рассчитывается для Chunk Type и Chunk Data.

И последнее, что нужно знать —последовательность chunk’ов не может быть произвольной. В спецификации приведены 2 схемы следования chunk’ов друг за другом:

Последовательность chunk’ов с PLTE

Последовательность chunk’ов без PLTE

Внутри прямоугольника записан тип chunk’а. Черта «|» означает, что должен быть или один или другой chunk. А символы сверху обозначают сколько раз он может встречаться:
А символы имеют следующие значения:

  • + – один или несколько раз;
  • 1 – только один раз;
  • ? – ноль или один раз;
  • * – ноль или несколько раз.

Такой формат очень удобен для поиска и проверки файла:

  • легко определить начало файла по первым 8 байтам;
  • файл целый, если собралась корректная последовательность chunk’ов с корректными контрольными суммами, иначе файл поврежден;
  • если файл целый, то мы знаем его размер — от начала до IEND включительно;
  • если последовательность не собралась – файл поврежден, но размер его валидной части больше или равен смещению до конца последнего валидного chunk’а.

В отличии же от формата BMP, для поврежденного файла нельзя узнать его полный размер.

С каким размером сохранять найденные файлы?

Мы разобрались с тем, какие возможности для восстановления данных заложены в форматах BMP и PNG. Рассмотрим теперь различные случаи с целыми и поврежденными файлами. Это поможет нам правильно интерпретировать результаты поиска.

При поиске по шаблону GREP мы выставляли размер до следующего найденного заголовка, другого способа узнать размер у нас не было. Анализ структуры может дать больше информации, но и логика принятия решения здесь сложнее.

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

Файл BMP

Нельзя ручаться за данные, которые находятся после проверенного размера. Если файл, например, фрагментирован, то следующий заголовок может быть найден уже внутри «полного размера»:

Поврежденный файл BMP

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

Если внутри «полного размера» других заголовков не найдено, то он и будет использован, т.к. сохранять больше данных нет смысла. Возможно это целый файл, для которого схема будет выглядеть уже так:

Целый файл BMP

Если мы нашли целый PNG файл, то все очень просто. Мы проверили его от начала до конца, знаем его размер и уверены, что он целый.

Целый файл PNG

Более сложная ситуация, если PNG файл поврежден.

Поврежденный файл PNG

Нам не удалось проверить очередной chunk, поэтому известно, что файл поврежден. Проверенный размер будет покрывать все целые chunk’и. Целая часть может оказаться больше. Файл будет сохранен до следующего заголовка, т. к. полный размер неизвестен (его можно получить только проверив успешно файл до конца).

Форма «чернового восстановления»

Форма режима «черновое восстановление»

С помощью анализа структуры мы можем получить значительно больше информации чем при простом поиске по шаблонам GREP. Рассмотрим как она отображается на форме чернового восстановления.

Панель категорий

В «черновом восстановлении» файлы ищутся как с помощью шаблонов GREP, так и с помощью анализа структуры. Поле GREP на панели с категориями заполнено только у первых.

Панель с результатами

Записи на панели с результатами тоже отличаются.

  • Если мы можем ответить целый файл или нет, то возле него будет отображена цветная отметка: зеленая — для целых, красная — для поврежденных.
  • В поле Size хранится размер, с которым файл будет сохранятся («размер при сохранении»). Выше мы рассмотрели как он выбирается для разных случаев.
  • Поле Checked Size содержит «проверенный размер». В дальнейшем мы рассмотрим где можно применять эту информацию.
  • Поле Comment содержит комментарий, содержание которого зависит от конкретного формата файла. Для изображений BMP и JPG отображается высота и ширина картинки, а для загрузочного сектора NTFS (Boot NTFS) размер раздела и кластера.

Панель метаданных

В режиме есть панель «метаданные», в нее попадает различная полезная информация, полученная при анализе файла по структуре. Например, для Boot NTFS (на скриншоте) можно узнать размер раздела, размер кластера, кластер с MFT0 и его копией.

Пример с картой памяти из фотоаппарата

В прошлой статье был пример с отформатированной картой памяти. Тогда мы не использовали анализ внутренней структуры файлов. Теперь выполним поиск с параметрами по-умолчанию.

Результаты выполнения «чернового восстановления»

Мы нашли такое же количество файлов JPEG. Однако результата стал намного более наглядным и точным:

  • у файлов появилась отметка целостности; с помощью фильтра можно отобрать и сохранить только целые файлы;
  • у целых jpeg’ов размер определен с точный размер до байта, а не до следующего заголовка как при поиске GREP;
  • заполнено поле comment и появились «Метаданные», из них можно узнать размер изображения, модель камеры, дату съемки и пр.

Заключение

На примере форматов BMP и PNG мы разобрали как в «черновом восстановлении» ищутся файлы на основе знаний о структуре. Очевидно, что такой подход дает намного более качественный результат, чем поиск с помощью регулярных выражений. Но алгоритмы проверки — это часть комплекса, и их нельзя добавить также легко как очередной шаблон GREP.

Изначально, режим «черновое восстановление» разрабатывался как последний рубеж при восстановлении данных. Он применялся лишь в тех случаях, когда остальные методы не дали удовлетворительных результатов. Но с развитием комплекса режим стал находить все больше применений при решении самых разных задач. О них мы обязательно напишем в следующих статьях.

Леоненко Александр
Разработчик Data Extractor

blog.acelab.ru

Простое введение в особенности формата

Greg Roelofs, <[email protected]> http://pobox.com/~newt

Иван Зенков, <[email protected]>

Dimok Busheff, <[email protected]>

Данный документ предназначен для разъяснения некоторых особенностей формата PNG обычным пользователям, по этому здесь вы не увидите акцентирования внимания на таких вещах как свобода PNG от патентов, поскольку они в первую очередь касаются лишь программистов. Встречающаяся техническая информация призвана объяснить пользователю почему различные приложения не работают так как он от них этого ожидает. В случае тестов с производительностью (особенно в сравнении с другими графическими форматами) предполагается, что используемая реализация находится PNG на уровне лучших реализации freeware-кодеров. Обратите внимание, что в настоящие время возможны проблемы даже при использовании некоторых популярных (и дорогих) графических редакторов.

Вот ещё несколько страниц сторонних авторов, с различными взглядами на PNG:

Примечание:

Прошу вас особенно обратить внимание на то, что весь нижеприведённый текст это по сути перевод A Basic Introduction to PNG Features (ни о каком GFDL здесь и речи быть не может). По ходу дела я буду высказывать своё скромное мнение на счёт PNG в частности и графики вообще (и вот это мнение уже может распространяться под GFDL).

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


Область применения

Формат PNG (Portable Network Graphics) спроектирован для замены устаревшего и более простого формата GIF, а также в некоторой степени для замены значительно более комплексного формата TIFF (см. официальный сайт PNG или хронологическую страницу для дополнительной информации). В данном документе мы сосредоточимся на двух основных направлениях в использовании формата. Первое, использование во всемирной паутине (WWW) и второе, графическое редактирование.

Для вэб PNG действительно имеет три основных преимущества перед GIF: альфа-каналы (переходная прозрачность), гамма-коррекция (межплатформенное управление яркостью изображения), двумерная чересстрочность (метод прогрессивной развёртики). Он обладает превосходным уровнем сжатия по сравнению с GIF, но различия колеблются около 5-25%, что не так уж и много для того, чтобы подвигнуть людей использовать только этот формат. Существует одна особенность GIF которую PNG не пытается воспроизвести, это поддержка множественного изображения, особенно мультипликации, PNG был предназначен лишь для одного изображения. Существует очень схожий с PNG расширенный формат называемый MNG, завершён в середине 1999 года и уже поддерживается в различных приложениях, но MNG и PNG имеют различные расширения и различные цели.

Для редактирования изображения, как профессионального так и не очень, PNG предоставляет отличный формат, даже для хранения промежуточных стадий редактирования. Поскольку сжатие происходит полностью без потерь и поскольку формат поддерживает 48-битный «truecolor» или 16-битный «grayscale«, сохранение, восстановление и пересохранение изображения проходят без потерь в качестве в отличии например от стандартного JPEG (даже с максимально высоким уровнем качества). В отличие от TIFF PNG спецификация не позволяет авторам реализаций привередничать выбирая какие возможности они собираются реализовать; как результат, любое сохранённое PNG изображение в одном приложении, может быть прочитано в любом другом приложении поддерживающим PNG.

За перечислением плюсов PNG, прошу обратить ваше внимание, что часто для обмена целостными «truecolor» изображениями (особенно фотографическими) JPEG — почти всегда лучший выбор. Хотя сжатие JPEG производиться с потерями при которых могут появляться артефакты, их всё же можно минимизировать, а вот размер файла даже на высококачественном уровне значительно меньше, чем в случае с форматами сжатия без потерь, вроде того же PNG. Также например для чёрно-белого изображения, особенно текста или рисунков, сжатие TIFF Group 4 или формат JBIG часто значительно лучше подходит, чем 1-битный «greyscale» PNG.

Примечание:

В последнем случае я с автором всё таки не согласен. Да действительно часто предпочтительней использовать JPEG, особенно для фотографий. Но это лишь в том случае, когда изображение не имеет для вас первичного приоритета, то есть второстепенно. Отправляя же например свою фотографию девушке, я бы не рискнул сохранить её в JPEG. Не говоря уже о таких случаях, когда я девушке отправляю не свою фотографию, а изображение своего рабочего стола. В последнем случае все эти артефакты всё равно проявятся и испортят общее впечатление от моих огромных SVG иконок. В случае же с чёрно-белыми изображениями из выше перечисленного я бы вообще ничего использовать не стал. По мне дак, для таких задач (а подразумевались отсканированная документация) я бы вообще использовал замечательный формат DjVu, о котором уже как-то писал.


Сжатие

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

PNG поддерживает три основных типа изображения, это: «truecolor«, «grayscale» и индексированное на основе палитры (8-битный). JPEG поддерживает только два первых, а GIF лишь третий (хотя при использовании серой палитры может фальсифицироваться и «grayscale«). Плотность сжатия происходит из способности смешивать различные типы изображения в одном PNG файле. Заставляя приложение сохранить 8-битное изображение как 24-битный «truecolor» (или RGB), в результате вы не получите маленького файла. Это может быть неизбежно в случае когда оригинал был изменён с добавлением более 256 цветов (например если в качестве фона был добавлен сплошной градиент), но многие изображения преднозначеные для сети, состоят из 256 цветов, а иногда и всего из нескольких (например из десяти).

Основная ошибка, это включение слишком большого количества данных палитры в PNG изображение. Эта ошибка наиболее заметна при конвертировании небольших GIF изображений (маркеров, кнопок и др.) в формат PNG. Эти изображения занимают в среднем 1000 байт и содержат 256 вводных в палитру данных из которых необходимы лишь 50, что приводит более чем к 600 байтам потраченного впустую пространства.

Примечание:

Имеется введу сохранение индексированного изображения в RGB, RGBA или просто с лишними данными в палитре, то есть лишними цветами.

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

Под конец ещё несколько слов о сжатии. Механизм сжатия может быть установлен на быстрый или качественный уровень. Часто «качественное сжатие» предпочтительнее, но иногда может быть выбран промежуточный уровень, например для повышения интерактивной производительности. Обычно (независимо от настроек) различия в размере файлов минимальны, но порой они бывают просто огромны.

Примечание:

Обратите внимание, что какой бы уровень сжатия вы не выбрали, качество изображения абсолютно не изменится измениться лишь время его загрузки.

Для дополнительной информации относительно механизма сжатия PNG и алгоритма CRC-32 посетите официальный сайт zlib. Для альтернативной реализации алгоритма сжатия посетите официальный сайт 7-Zip и почитайте «Введение в компрессию» для описания сжатия вообще. Для инструментария оптимизации и сжатия PNG изображений, посетите страницу со списком конвертеров (особое внимание обратите на pngcrush и SmartSaver).

Примечание:

Автор не упомянул наверное одну из лучших программ в своём роде, называется она OptiPNG (542KB) и доступна «as-is» под несколько операционных систем (существует ещё версия OptiPNG Plus, но у неё с «public-domain» проблемы).

Лучшей OptiPNG я посчитал из-за простоты использования хотя бы по сравнению с тем же pngcrush, о котором упоминалось выше.

Итак, за собственно сам уровень сжатия в OptiPNG отвечают следующие ключики:

  • -i: тип чересстрочности (0-1)
  • -zc: уровни сжатия zlib (1-9), по умолчанию 9
  • -zm: уровни памяти zlib (1-9), по умолчанию 8
  • -zs: стратегии сжатия zlib (0-2)
  • -f: дельта-фильтры PNG (0-5)

Справку по остальным ключам программы можно получить набрав optipng —help, впрочем нам они всё равно не понадобиться, как не понадобятся и выше перечисленные ключики. Разработчик OptiPNG позаботился о пользователях, снабдив программу специальным ключом оптимизации -o (0-7), по умолчанию 2. По сути ключ -o это определённая комбинация из вышеперечисленных ключей. Так -o2 будет -zc9 -zm8 -zs0-2 -f0,5, а -o3 будет -zc9 -zm8-9 -zs0-2 -f0,5, самым же эффективным является -o7 тест с которым я и покажу.

Для теста было выбрано олигархическое полотно замечательного художника Владимира Куша, предварительно обработанное GIMP’ом (стабильная версия 1.2) и сохранённое в RGBA как PNG с отключёнными параметрами и степенью сжатия 9. В результате было получено изображение в 135168 байт, если верить моему кривому du. Сжатие производилось OptiPNG версии 0.4.3, осуществлялось командой optipng -k -o7, ключ -k нужен, чтобы при оптимизации не был удалён оригинальный файл. В результате файл с оптимизированным изображением весил 118784 байт полагаясь на тот же du.

Как видите, оптимизация налицо, и всё это без каких-нибудь потерь в качестве (да в случае с PNG их и не могло быть). Так первое изображение (слева) это оригинал сохранённый в GIMP‘е (помните максимальный уровень сжатия?), второе — оптимизированный вариант.

«Чудо» — скажете вы и будете в корне неправы, ведь чудеса если и бывают, то явно не в данном случае. Нет это действительно было не чудо, это была ещё одна распространённая ошибка. Некоторые люди создавая новое изображение в GIMP‘е (да и других редакторах) выбирают прозрачный фон в качестве заливки (в диалоге «Новое изображение» GIMP‘а даже раздел «Тип заливки» имеется), и, почему-то, им кажется, что раз прозрачный, то и на размере это не отразиться. Разумеется, на размере это отражается, и отражается в большую сторону, поскольку добавляется альфа-канал (помните, что изображение я сохранил в RGBA?). OptiPNG, как программа умная, всё это замечает и удаляет, предоставляя нашему вниманию нормальное изображение. GIMP за сим же процессом ещё при сохранении не следит полагаясь на благоразумность пользователя. Бороться с ошибкой можно выбирая в качестве заливки какой-нибудь цвет ещё при создании изображения (в GIMP‘е начиная с версии 1.3, можно вообще на задавать заливку, получив весьма странный нулевой фон). А OptiPNG действительно замечательная программка, она позволяет избавить PNG файл не только от программных ошибок, но и от людских тоже. Советую, особенно для оптимизации больших коллекций, Бог знает кем и как созданных изображений.


Фильтры сжатия

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

Посредством примера (по общему признанию критический и нереалистичный случай), 512 x 32,768 изображение содержит все 16,777,216 возможные в 24-бита цвета, сжимается более чем в 300 раз лучше с фильтрацией, чем без. Несжатое изображение весило 48MB, сжатое, но без фильтров 36MB, а версия с фильтрами всего 115,989 байт (0.1 MB). Более того, Paul Schmidt создал 4096 x 4096 версию размером 59,852 байт, с общим коэффициентом сжатия 841:1, что более чем в 600 раз лучше версии без фильтров. Ted Samuels пропустил всё это через утилиту Ken‘а Silverman‘а PNGOUT (ссылки на другие конвертеры ищите на специальной странице) и урезал до 57,549 байт, добившись тем самым коэффициента в 875:1 (см. эту страницу для загрузочной версии и дополнительной информации).

Более реалистичный пример с океанографическими данными NASA на сайте Ocean ESIP. Цифровые карты отображающие различные физические измерения, могут быть динамически сгенерированы в GIF или PNG. PNG версии неизменно равны одной-пятой версии GIF, благодаря фильтрам сжатия. Для примера, карта показывающая высоту поверхности северо-восточного Тихого океана 1 Августа 1997 года (во время El Niño) занимает 70,090 байт в GIF, и всего 13,880 байт в PNG (см. главу Алгоритмы фильтров из PNG спецификации).

Как измерение, всё это просто кажется нереалистичным, однако заметьте, что эти, с виду гиперсжатые, PNG могут самостоятельно быть сжаты с дополнительным коэффициентом где-нибудь приблизительно от 21 до 97 (в зависимости от изображения) простым применением gzip. Конечно, gzip PNG не так ужасно полезны в большинстве случаев, а вот MNG хорош для всего, сокращая размер на 456 байт.


Альфа-каналы

Также известный как маска-канал, альфа-канал это просто способ объединить переходную прозрачность с изображением. Принимая во внимание, что GIF поддерживает простую бинарную прозрачность (это когда любой пиксель может быть либо полностью прозрачным, либо абсолютно непрозрачным), PNG позволяет 254 уровня частичной прозрачности между нормальным изображением (или 65,534 уровня прозрачности для специальных «очень безумных» форматов, но здесь мы больше концентрируемся на изображениях, используемых в интернете).

Все три типа PNG изображений («truecolor«, «grayscale» и индексированная палитра) могут содержать альфа-информацию, хотя обычно она применяется лишь с «truecolor» изображениями. Вместо того, чтобы сохранять три байта для каждого пикселя (красный, зелёный и синий), сохраняются четыре: красный, зелёный, синий и альфа, таким образом получается RGBA. Вся эта переходная прозрачность позволяет вам создавать замечательные «спецэффекты», хорошо выглядящие на любом фоне. Например эффекта фотовиньетки, для портрета, можно добиться путём установки полностью непрозрачной центральной области (то есть для лица и плеч), прозрачной остальной обстановки и с созданием плавного перехода между двумя этими различными областями. Рассматривая изображение в браузере типа Arena, портрет будет плавно осветляться на белом фоне, и затемняться на чёрном. Ещё один идеальный спецэффект с альфа-прозрачностью, это отбрасывание тени. Так на изображениях ниже показан тукан, в первом случае отбрасывающий тень на красочный фон, во втором на свою копию.

Эта особенность с прозрачность наиболее важна для маленьких изображений, обычно используемых на вэб-страницах, вроде цветных (круглых) маркеров или причудливого текста.

Альфа-смешивание позволяет использовать другой эффект, а именно сглаживание (anti-aliasing) создавая иллюзию гладких кривых на сетке прямоугольных пикселей плавно изменяя их цвета, что позволяет добиться округлых и кривых изображений, хорошо отображаемых как на белом (к примеру), так и на любом другом фоне. Таким образом одно и тоже изображение может быть многократно использовано в нескольких местах без «призрачного» эффекта, свойственного GIF изображениям.

Примечание:

Я не очень-то понял, в чём заключается этот «призрачный эффект». Было несколько вариантов, среди которых наибольшую проблему в GIF у меня вызывали изображения созданные для одного фона, но наложенные на другой, приблизительно так же, как я сделал со знаменитым зверьком O’Reilly Network, только ещё хуже.

Конечно эффективная замена GIF-кнопкам и иконкам должна быть сравнима по размеру, и часто приходится исключать «truecolor» RGBA изображения. Впрочем точно также PNG поддерживает альфа-информацию и в случае с индексированными изображениями, просто это намного труднее осуществить. Изображение в PNG с альфа-индексацией — это изображение, чья палитра обладает альфа-информацией, связанной с ней, а не индексированное изображение с полной альфа-маской. Другими словами каждый пиксель соответствует данным из палитры с красными, зелёными, синими и альфа компонентами. Так, если вы хотите получить яркие красные пиксели с четырьмя различными уровнями прозрачности, вам потребуется использовать четыре отдельных ячейки в палитре, чтобы их индексировать (все четыре ячейки обладают идентичными RGB компонентами, но альфа значения различаются). Если вы хотите чтобы все ваши цвета имели четыре уровня прозрачности, вам проще сократить общее количество доступных цветов с 256, до 64. В основном только некоторые цвета нуждаются более чем в одном уровне прозрачности, и выяснение какие именно, процесс требующий определённой мудрости. Можно взглянуть на программу pngquant, которая конвертирует 32-битные RGBA PNG в 8-битные изображения с RGBA-палитрой. Для программистов доступен исходный код программы.

Для более лучшего объяснения с красивыми примерами, смотрите главу «Прозрачность и сглаживание» замечательной WWW4 статьи Chris‘а Lilley‘я Не просто декорация: Качественная графика для вэб.

Примечание:

К стати, поразительная вещь, но GIMP, кажется, об этом не в курсе. Сколько раз я не пытался сохранить в нём прозрачное индексированное PNG изображение, мои попытки оканчивались неудачей. То есть RGBA пожалуйста, «grayscale» на здоровье, а вот чтоб индексированное с прозрачностью, ни в какую. Что же всё таки делать, если понадобилось небольшое прозрачное изображение? Ну, выход, как всегда, есть, и о нём уже говорилось выше, нужно просто использовать pngquant (24KB).

В начале я создал обычное RGBA изображение, взяв за основу уже индексированную когда-то картинку (не очень сильно) с персонажем замечательной игры DROD. Затем командой pngquant 64 rgba.png получил нужное мне индексированное изображение с прозрачностью. Там где 64, я установил количество необходимых мне цветов, а rgba.png это файл первого изображения. Думаю несложно догадаться, что первое изображение это и есть мой первоначальный вариант (весил он 12288 байт), а второе это индексированный вариант с прозрачностью (занимал всего 8192 байт).

Индексированное подобным образом изображение, успешно отобразили GQview (не создав иконки в предварительном просмотре), Opera и Mozilla. Проблемы были разумеется с GIMP‘ом (версии 1.2, 1.3) и Konqueror’ом (версии 3.1.4).

Впрочем, несмотря на все минусы, единственным способом уменьшить размер PNG файла, помимо сжатия, остаётся индексирование. А в случае когда с индексированием необходим ещё и альфа-канал, pngquant становиться практические незаменимым инструментом. И очень жаль, что свободное ПО таких масштабов как GIMP не знает всех возможностей формата PNG, да ещё и при том, что исходники того же pngquant доступны «as-is«.


Гамма-коррекция

Гамма-коррекция существует для исправления различий того, как компьютеры (а особенно мониторы) интерпретируют цветовые значения. Вэб-дизайнеры, вероятно, знают случаи, когда созданные на Macintosh изображения выглядят слишком тёмными на PC, или созданные на выглядят слишком светлыми на Mac‘ах. Изображение, которое хорошо смотрится на SGI Workstation, не хочет отображаться на Macintosh или PC. Изображение созданное на одном PC неверно отображается на всех остальных.

Гамма-информация — частичное решение. Это способ связи некоего числа с компьютерной системой отображения, в попытке характеризовать хитрую физику, скрывающуюся в пределах цифро-аналогового конвертера графической карты (RAMDAC) и в высоковольтной электронной пушке монитора.

Параметр гамма — это только приближение к действительности. Лучшей аппроксимацией является использование так называемых значений цветности (chromaticity values — также поддерживаемых в PNG), в качестве той же гаммы, но даже это лишь приближение. Самое лучше решение, доступное на данный момент, это использование системы управления цветом (которая опять же поддерживается PNG через расширение фрагментом sRGB). Стоит, однако, сказать, что для большинства людей достаточно лишь установить гамму изображения и настроить гамму системного монитора.

Для дополнительной информации смотрите руководства Chris‘а Lilley: гамма, цветность и управление цветом, или почитайте «Гамма-руководство» в дополнении к спецификации PNG. Для более детальной технической информации смотрите «FAQ: Гамма и цвет» Charles‘а Poynton‘а, официальный сайт Интернационального Цветового Консорциума, домашнюю страницу sRGB или главу «Гамма-коррекция» в статье Chris‘а Lilley Не просто декорация: Качественная графика для вэб.


Чересстрочность

Чересстрочность или прогрессивная развёртка, была известна на протяжении долгого времени. GIF стал поддерживать её с 1989-го, TIFF приблизительно в тоже время (хотя не стандартизированным путём), JPEG с начала 90-ых (хотя это не было широко распространено до 1996-го). Метод чересстрочности PNG концептуально схож с GIF и визуально подобен прогрессивному JPEG (то есть, двухмерен).

Вот GIF анимация (автор Willem van Schaik), показывающая преимущества двухмерной чересстрочной схемы PNG, по сравнению с одномерной версией GIF.

Первое, на что следует обратить внимание, так это на то, что пока видна приблизительно одна восьмая изображения в GIF, PNG изображение уже становиться видимым сразу же после выполнения первого прохода. Первый проход PNG это только 1/64-ая часть данных изображения. Первый проход GIF 1/8-ая. К тому времени, когда первый проход GIF завершился, уже были отображены четыре прохода PNG, и в отличие от GIF-пикселей, растянутых с коэффициентом 8:1, пиксели PNG были растянуты лишь на 2:1. Более того, на самом деле в нечётных проходах никакого растяжения нет вообще и только чётные растягиваются вертикально на 2:1. Это означает, что, например, внедрённый в изображение текст будет доступен для чтения в два раза быстрее, в PNG изображении.

Смотрите чересстрочную демонстрацию PNG для «увеличенного» взгляда на то, как PNG отображает чересстрочные пиксели, или читайте главу «Представление данных» из PNG спецификации для деталей относительно чересстрочной схемы формата PNG.


Проверка целостности файла

PNG поддерживает три основных типа проверки целостности, для помощи программам в работе с файлами. Первый и самый простой — 8-байтная магическая сигнатура в начале любого PNG изображения. Позволяет обнаружить наиболее основное повреждение файла — передачу бинарного файла в текстовом (или ASCII) режиме. На большинстве систем, окончание строки в текстовых файлах отмечается символом возврата каретки (CR), символом перевода строки (LF), либо и тем и другим сразу. Macintosh используют CR, UNIX системы используют LF, все остальные не UNIX системы на PC (DOS, Windows 3.x/95/NT, OS/2) используют CR/LF. Магическая сигнатура PNG грамотно включает как CR/LF, так и LF. Так, для теста передадим в текстовом режиме изображение, на DOS-машину, к LF будет добавлен CR. На UNIX-системах, CR/LF будут преобразованы в обычный LF. На Macintosh и CR/LF, и LF будут преобразованы в CR. Для того, чтобы узнать произошло ли текстовое искажение, достаточно взглянуть на первые восемь, девять байт файла (команда file в UNIX спроектирована специально для таких вещей). Имейте введу, что проблема не в испорченной сигнатуре, реальная проблема состоит в том, что символы CR и LF в данных изображения могут быть опознаны не как конец строки или текст, а как значения пикселей или более абстрактные лексемы компрессора, и все эти символы будут также преобразованы, таким образом разрушая изображение.

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

Третий тип проверки целостности применим лишь к кусочку/кусочкам данных изображения и схож с CRC-значениями. Так где CRC-значения кусочков изображения обращается к фильтрованным, сжатым данным в кусочке, контрольная сумма Adler-32 обращается к завершённому потоку распакованных данных (независимо от того, сколько кусочков изображения могли быть охвачены). В действительности это используется лишь в библиотеках сжатия самого нижнего уровня как средство проверки плохо кодирующего/декодирующего программного обеспечения.

Для более подробной информации смотрите главу «Структура файла» из спецификации PNG.


Произношение

Нет второстепенных вопросов для авторов почти совершенного формата! Да, действительно, даже акроним и произношение были главными темами обсуждения. Причина этому конечно GIF. Кто-то произносит с мягким «G», как «джемпер», кто-то с жёстким, как «гараж» и никто в действительности не знает почему. Но, чтоб вы знали в данном случае правильным будет мягкое «G», поскольку так говорят сами авторы.

PNG всегда пишется по буквам «PNG» (или Portable Network Graphics) и произносится как «пинг», а не «пинджи» или «пэ эн гэ» (впрочем вполне нормально, что люди не говорящие на английском произносят PNG по буквам).

Для более чётких инструкций относительно данного вопроса, смотрите введение в PNG спецификации.

Примечание:

Под конец пара слов относительно использования данного формата в вэб, а точнее относительно связанных с этим проблем. Первая из них, и о ней уже много говорили, это патент на LZW (замечательный алгоритм сжатия применяющийся в GIF, не хочу сказать лишнего, но мне кажется, что он сжимает лучше, чем все эти zlib, используемые в PNG) принадлежащий Unisys. Хорошая новость в том, что патент на территории США истёк 20 Июня, 2003 года. Плохая в том, что он всё ещё действует на территории таких стран как Италия, Франция, Канада, Германия, Англия и Япония. Понятно, что Россия всегда в стороне от подобных вопросов, и каждый что-то решает для себя.

Удивительно то, что альтернатива-то в лице PNG, да и не альтернатива даже, а нечто большее, уже существует давно. То есть действительно PNG большее, ведь он используется во всех современных desktop-системах, его альфа-прозрачность это просто праздник какой-то и для рабочих столов, и для интернета. Здесь другая проблема, Internet Explorer его не поддерживает, точней не поддерживает прозрачность. С этим есть несколько способов борьбы, в определённой мере они действенны. Вообще в подобные вопросы я бы даже вникать не стал. То, что Microsoft не поддерживает формат, проблемы Microsoft, а не формата.

Огорчает не только Microsoft (и я об этом уже говорил), огорчает свободное программное обеспечение. Все эти странные проблемы с тем же Konqueror‘ом… Я уже не говорю о GIMP‘е. Не говорю хотя бы потому, что не использовал все эти новые версии 2.0. Просто надеюсь, там всё исправили.

Copyright 2004, Иван Зенков

Данный документ (кроме отдельно указанных частей, переводного текста и др.) распространяется в соответствии с GNU Free Documentation License опубликованной Free Software Foundation и изготовлен в полном соответствии со стандартами w3 консорциума.

Все торговые марки, названия и логотипы использованные или упомянутые в этом документе, принадлежат своим владельцам.

Остальные мои статьи можно найти на моей страничке на сайте Rus-Linux.net

Если вам понравилась статья, поделитесь ею с друзьями:


rus-linux.net

Структура PNG-файла: основные и вспомогательные фрагменты (chunks)

После написания PNGRepack у меня появился спортивный интерес — просмотреть все файлы PNG на своём компьютере и выяснить, чего интересненького в них напихано кроме непосредственно изображений?

Впрочем, интерес не только спортивный — до сих пор PNGRepack относилась к не относящимся к делу фрагментам очень лояльно — записывала их в преобразованный файл, как ни в чем не бывало, хотя от многих из них вполне можно избавиться, а другие, напротив надо нежить, холить и лелеять, и вообще при обработке изображений обращать на них пристальное внимание.

Сегодня про общую структуру и про фрагменты tEXt, zTXt, iTXt, tIME, pHYs и gAMA.

До сих пор не знаю, как слово chunk правильно перевести на русский, пущай будет фрагмент. Каждый фрагмент начинается с 4-х байт длины, затем название из 4-х латинских букв, затем непосредственно данные, а в конце — 4-байтная контрольная сумма CRC. Из того, как построено название, уже можно много почерпнуть.

Если первая буква заглавная, значит фрагмент «критический», т.е считается, что без него изображение не удастся посмотреть ни в каком виде, и если хоть один из критических фрагментов отсутствует, декодер должен грязно выругаться. Критических фрагментов сейчас 4: IHDR (Image Header), PLTE (Palette), IDAT (Image Data) и IEND (Image End). Уже здесь возникает неоднозначность — палитра критически важна только для изображений, у которых ColorType = COLOR_PALETTE, для остальных она допустима (правильный декодер должен попытаться ей воспользоваться, если монитор может отображать одновременно лишь ограниченное число цветов), но как правило отсутствует.

Соответственно, строчная буква означает, что фрагмент «вспомогательный» (Ancillary), т.е что-то похожее отобразится и если их проигнорировать, но зачем-то их все-таки запихнули, наверное, не зря.

Если последняя буква у вспомогательного фрагмента заглавная, значит, что при изменении самого изображения они тоже, возможно, должны определенным образом измениться, поскольку зависят от этого изображения, например, tRNS (transparency) отвечает за «простую прозрачность» (cheap transparency), когда либо один из цветов назначается прозрачным, он-то и записан в tRNS, либо нескольким первым цветам палитры приписываются значения прозрачности. Если какое-то приложение открыло tRNS, ничего не зная о том, что это за зверь, а потом после работы с изображением перемешало палитру, то ничего хорошего не выйдет, и считается лучшим выходом либо вообще выкинуть tRNS после такого издевательства, либо и вовсе не браться за редактирование изображения, если в нем есть такие вспомогательные фрагменты с заглавной последней буквой. Впрочем, это правило мало кто соблюдает, да и расплывчатое оно. Почему gAMA (значение гамма-коррекции) так уж зависит от самой картинки — мне непонятно. Собственно, строчная последняя буква есть только у текстовых фрагментов и у pHYs (pHysical size), хранящего разрешение картинки при сканировании, скажем, 600 dpi.

И наконец, вторая буква названия фрагмента заглавная, если он «публичный», т.е утвержден высочайшим советом и входит в спецификацию, и строчная, если он «частный», таковые тоже существуют, но известно о них немного. Скажем, Adobe Fireworks использовала формат PNG в качестве базового, но добавила туда свои собственные фрагменты mkBS, mkTS, mkBF, prVW и др., чтобы хранить что-то вроде слоёв и векторов, чтобы можно было сохранить проект в PNG, а позже открыть его и продолжить работать как ни в чем ни бывало. О том, как они устроены, Adobe не распространяется. На эти штуки я натыкался, они могут занимать приличные объемы, и если мы не собираемся редактировать эту картинку в Fireworks, их следует удалить.

(что такое FACECAFE — не знаю. Похоже на рекламный слоган: «Хороший mkBT начинается с FACECAFE»)

Теперь рассмотрим, наконец, фрагмент каждого типа подробнее.

Текстовые фрагменты (tEXt, zTXt, iTXt)
Произвольный текст, добавленный к изображению. Например, таким образом можно записать EXIF, хотя фотографии обычно все-таки хранятся в JPG. tEXt — самый простой, несжатый текст, каждый фрагмент содержит название (keyword) и непосредственно текст. zTXt (zipped text) — то же самое, только текст сжат тем же самым zlib (оставлена возможность под другие форматы сжатия, но пока доступен только CompressionMethod=0, что означает zlib), а iTXt (international text) имеет кодировку не Latin-1, как два предыдущих, а UTF-8, причем текст может быть сжатым, а может и нет, а кроме Keyword добавляются еще поля Language и Translated keyword.

(Пожалуй, самое нетривиальное, что встретилось мне в текстовых полях)

Для Keyword определены стандартные значения Title, Author, Description, Copyright, Creation Time, Software, Disclaimer, Warning, Source, Comment, но можно использовать и любые другие.

Ничего особенно интересного в этих полях я не находил, чаще других попадается Software — многие графические редакторы заполняют его своим названием, это продукты Adobe, Gimp, Paint.net и другие. Чрезвычайно бесят пустые поля, когда у изображения целый набор этих текстовых фрагментов — Title, Author, Description, но текст у них вообще отсутствует. В PNGRepack добавлена галочка удалять такие пустые поля без лишних вопросов.

Метка времени tIME
В стандарте сказано, что это должно быть время последнего изменения изображения, оттого последняя буква заглавная (отредактировал изображение — будь добр и время переписать!). Довольно скучная вещь, но может пригодиться.

Физические размеры пикселя (разрешение) pHYs
Совсем короткий фрагмент, но очень важный при обработке сканов — многие программы этого толка отталкиваются не от размера изображения в пикселях, а от физического размера бумаги, чтобы обложка в 600 dpi и последующие страницы в 300 dpi в итоге отображались бы в одном масштабе. Как правило, в pHYs записывается горизонтальное и вертикальное разрешение в пикселях на метр, которые легко пересчитать в пиксели на дюйм.

Возможен вариант, когда единица измерения не указана, тогда узнать реальное разрешение нельзя, только «соотношение сторон пикселя» — такой информацией было бы полезно снабдить кадр анаморфного видео, чтобы можно было корректно отобразить его на экране. Создатели формата рекомендуют проверять, являются ли пиксели «квадратными» у изображения и растягивать его в нужную сторону, если нет, чтобы не получить вытянутые морды. Пока ни одного изображения с «безразмерным» разрешением мне не встретилось.

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

Гамма-коррекция gAMA
Самый неоднозначный фрагмент. Задумка была хорошая — на разных операционных системах свои соглашения, с какой гаммой показывать изображения, соответственно, (128,128,128) может означать немножко разный цвет, и почти никогда это не будет 50% серый, который ближе к (192,192,192), в общем, хотелось авторам навести некоторый порядок, но почему-то, вместо того, чтобы обозначить, как закодирована яркость в изображении (1 означало бы, что линейно, а число отличное от 1 — наличие степенной зависимости), они постановили, что гамма будет говорить просмотрщику, в какой мере надо еще преобразовать эти пиксели, прежде чем в линейном виде подать на монитор! Это привело к большой путанице, и я не уверен, что хоть где-то её обработка сделана корректно. Вот те немногие гаммы, что я находил в изображениях:


Кажется, вот оно, корректное применение — мы предупреждаем просмотрщик, что вместо стандартной для sRGB гаммы в 2.2 мы задаем 2.4, и просмотрщик теперь чуть-чуть подкорректирует значения и получит качественную картинку. НЕ ТУТ-ТО БЫЛО!!! Согласно спецификации, в gAMA должно заносится значение, обратное гамме, в данном случае 1/2.4 = 0.42. То, что программы продолжают беспалевно сохранять сюда саму гамму вместо обратной величины, и никто этого не заметил — дурной признак.

Продолжение следует.

nabbla1.livejournal.com

Оптимизация без потери качества: PNG

Последние несколько месяцев в Айри прошли в напряженном поиске и отборе лучших решений для уменьшения размера файлов. Размер веб-страниц постоянно увеличивается, и изображения занимают существенную часть в суммарном объеме загружаемых данных.

Чтобы понимать, как именно изображения для веб-страниц могут быть оптимизированы, нужно разобраться в структуре файлов изображений. Мы начнем с PNG.

Структура PNG файлов

PNG-файл, в первом приближении, состоит из заголовков (чанков), содержащих служебную информацию (в том числе, и информацию о цветовой схеме), палитре (в случае использования индексированных цветов), фильтров и цветовых данных (преобразуемых через фильтры). Это накладывает следующие ограничения на возможности оптимизации файла:

  • Можно удалить неиспользуемые для отображения файла на веб-страницах чанки.
  • Можно уменьшить или преобразовать палитру файла для лучшего сжатия.
  • Можно использовать другую комбинацию фильтров, позволяющих записать цветовую информацию, используя меньшее количество байт.
  • Можно использовать другие алгоритмы сжатия информации в заголовках, палитре, фильтрах и цветовых данных.

В связи с этим все инструменты оптимизации PNG разбиваются на 4 группы:

  • Для удаления ненужных чанков из файла.
  • Для квантования / кластеризации / упорядочивания палитры (как реализовать кластеризацию палитры). Любое уменьшение палитры относится к техникам с потерями качества изображения, но визуально изображение может быть почти неотличимо от оригинала. Упорядочивание палитры улучшает ее последующее сжатие, на качество изображения не влияет. Также для оптимизации может быть применено перевод неиндексируемого изображения (с небольшим количеством цветов) в индексируемое.
  • Для подбора наиболее оптимальных фильтров для изображения.
  • Для максимального сжатия всех частей файла.

Если ориентироваться на достаточно подробный разбор инструментов оптимизации PNG, то можно выделить наиболее эффективные утилиты для выполнения тех или иных операций с PNG-файлами:

Утилиты для оптимизации PNG

Удаление чанков из изображения поддерживают почти все утилиты, для этой цели в равной мере подойдут pngout или TruePNG. Также хорошая утилита для работы с чанками в графических файлах — это exiftool.

Для квантования/постеризации лучше всего подойдут pngquant, pngnq-s9 или TruePNG. Преобразования палитры без потери качества выполняют pngoptimizer, pngrewrite и TruePNG.

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

Наконец, для максимального сжатия изображения лучше всего использовать PNGZopfli или ZopfliPNG.

Подводя итог, лучшей комбинацией инструментов для комплексной оптимизации PNG-файлов на текущий момент является TruePNG, pngwolf и ZopfliPNG.

Для Мака можно использовать связку ImageAlpha и ImageOptim.

Все-в-одном

Для использования в рабочем процессе указанных утилит лучше всего подойдет пакет Image Catalyst — он автоматизирует почти все описанные техники оптимизаций для работы над группой файлов.

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

В среднем, уменьшение размера изображений позволяет сократить размер изображений на 35-50%, это очень значительное достижение для скорости сайта, и может быть выполнено полностью автоматически при подключении сайта к Айри.

xn--80aqc2a.xn--p1ai

Про PNG. Часть первая

Общаясь со своими коллегами на различных семинарах и в студии, я пришел к выводу, что для многих единственным преимуществом формата PNG является наличие честной полупрозрачности. Если поискать в интернете информацию об этом формате, несложно заметить, что веб-разработчики разделились на два лагеря. Первые пишут о том, какой этот формат замечательный, оперируя чисто техническими данными, непонятными обычным кодерам и дизайнерам (к примеру, о превосходстве deflate-алгоритмов сжатия над LZW), другие же оставляют комментарии разной степени глупости о бесполезности PNG, не потрудившись даже вникнуть в суть вещей, описанных в спецификации.

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

Начнем с терминологии. Предполагаю, что большинство читателей пользуются фотошопом и встречали там названия PNG-8 и PNG-24. Это не два разных формата, а всего лишь вариации одного и того же PNG. Формат позволяет хранить три типа изображений: greyscale (для описания изображения используется один канал — белый), indexed-colour (используется палитра цветов, как в GIF) и truecolor (используется три канала — RGB).

Самое главное преимущество формата PNG — это, конечно же, новые алгоритмы сжатия. Все помнят, что GIF эффективно сжимает только горизонтальные одноцветные области? Про это ограничение теперь можно забыть:

GIF, 2568 байт PNG-24, 372 байта

Вторым важным преимуществом является фильтрация строк (scanline filtering, или delta filters), благодаря которой PNG-упаковщик может получить гораздо более удобные данные для сжатия.

Рассмотрим на примере, как они работают. Возьмем изображение 5×5 пикселей с горизонтальным градиентом и схематично отобразим, как оно может быть сохранено в файле (каждое число — уникальный цвет).

Хозяйке на заметку

Считаю своим долгом отметить, что цвет в формате RGB хранится в виде одного числа, а не трех (на каждый канал). Например, цвет R: 253, G: 93, B: 69 хранится как число 16604485 в десятичной системе счисления или как #fd5d45 — в шестнадцатеричной.


Как видно из примера, GIF-кодировщик отдал бы на сжатие строки, которые плохо упаковываются по горизонтали (потому что одинаковые цвета распространяются по вертикали). А вот как может преобразовать эти данные PNG-кодировщик:

Перед каждой строкой появилась цифра 2. Это — фильтр, который был применен к строке. В данном случае это фильтр Up, который говорит декодеру: «Для текущего пикселя возьми значение пикселя выше и прибавь к нему текущее значение». В нашем случае это 0, потому что цвета текущего и верхнего пикселей не отличаются. А эти данные можно эффективней упаковать, если у нас достаточно большое изображение.

Почему я написал может? Потому что в нашем идеализированном случае более эффективной была бы такая схема:

Тут применен фильтр 1 под названием Sub, который говорит декодеру: «Возьми значение пикселя левее текущего и прибавь ему текущее значение». В данном случае 1.

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

Хозяйке на заметку

Всего существует 5 фильтров: None (никакой фильтрации), Sub (от текущего значения отнять значение левого пикселя), Up (отнять верхний пиксель), Average (отнять среднее значение левого и верхнего пикселей) и Paeth (подставить значение верхнего, левого или верхнего левого пикселя, назван в честь Алана Паэта).


Проверим работу фильтров:

PNG-24, фильтр None
56084 байта
PNG-24, фильтр Up
23585 байт

Внимательный читатель может заметить, что фильтры применяются не ко всему файлу целиком, а к строкам. Это значит, что каждая строка может иметь свой фильтр. Получается, что способов фильтрации одного изображения может быть 5высота картинки. В общем-то, задача хорошего кодировщика как раз заключается в том, чтобы подобрать такие значения фильтров, при которых объем файла будет минимальным. К сожалению, фотошоп не всегда хорошо справляется со своей работой, поэтому на помощь приходят различные утилиты вроде OptiPNG и PNGCrush, которые в большое количество проходов подбирают разные способы фильтрации и стратегии сжатия данных, значительно сокращая тем самым объем некоторых сложных изображений. Однако стоит помнить, что эти программы не гарантируют уменьшение объема для каждого файла, они всего лишь пытаются найти оптимальный способ кодирования данных.

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

PNG-24 (фотошоп → truecolor),
8167 байт
PNG-24 (фотошоп + OptiPNG → greyscale),
6132 байта

Преимущества greyscale над truecolor очевидны: к примеру, белый цвет в первом случае записывается (в десятичной системе счисления) числом 255, а во втором — 16777215.

Теперь, вооружившись знаниями о хранении данных в формате PNG, мы можем применять их в подготовке изображений для веба. Об этом — в следующих статьях.

www.artlebedev.ru

image — В чем разница между изображениями «JPG» / «JPEG» / «PNG» / «BMP» / «GIF» / «TIFF»?

Вы должны знать о нескольких ключевых факторах…

Во-первых, есть два типа сжатия: Lossless и Lossy.

Lossless означает, что изображение уменьшено, но не ухудшает качество. Lossy означает, что изображение сделано (даже) меньше, но в ущерб качеству. Если вы сохранили изображение в формате Lossy снова и снова, качество изображения будет становиться все хуже и хуже.

Существуют также различные глубины цвета (палитры): Указанный цвет и Прямой цвет.

С индексированным это означает, что изображение может хранить только ограниченное количество цветов (обычно 256), которые выбраны автором изображения, с Прямой, это означает, что вы может хранить много тысяч цветов, которые не были выбраны автором.


BMP — Lossless/Indexed и Direct

Это старый формат. Это Lossless (данные об изображении не теряются при сохранении), но также практически никакого сжатия, что означает сохранение, поскольку BMP приводит к ОЧЕНЬ большим размерам файлов. Он может иметь палитры как Indexed, так и Direct, но это небольшое утешение. Размеры файлов настолько неоправданны, что никто никогда не использует этот формат.

Хорошо: ничего действительно. Существует не что-то, что BMP превосходит или не улучшается другими форматами.


GIF — Без потерь/Только индексирование

GIF использует сжатие без потерь, что означает, что вы можете сохранять изображение снова и снова и никогда не теряете никаких данных. Размеры файлов намного меньше, чем BMP, потому что хорошее сжатие фактически используется, но оно может хранить только индексированную палитру. Это означает, что в файле может быть только 256 различных цветов. Это звучит довольно мало, и это так.

Изображения GIF также могут быть анимированы и иметь прозрачность.

Хорошо для: Логотипы, чертежи линий и другие простые изображения, которые должны быть небольшими. Только на самом деле используется для веб-сайтов.


JPEG — Lossy/Direct

Изображения JPEG были предназначены для того, чтобы сделать как можно более подробные фотографические изображения, удалив информацию, которую человеческий глаз не заметит. В результате формат Lossy и сохранение одного и того же файла снова и снова будут приводить к тому, что с течением времени будет потеряно больше данных. У него есть палитра тысяч цветов, и это отлично подходит для фотографий, но сжатие с потерями означает, что это плохо для логотипов и линейных рисунков: они не только выглядят нечеткими, но и такие изображения также будут иметь больший размер файла по сравнению с GIF!

Хорошо для: Фотографии. Кроме того, градиенты.


PNG-8 — Lossless/Indexed

PNG — более новый формат, а PNG-8 (индексированная версия PNG) — действительно хорошая замена для GIF. Однако, к сожалению, у него есть несколько недостатков: во-первых, он не может поддерживать анимацию, как GIF (может, она может, но только Firefox, похоже, поддерживает ее, в отличие от анимации GIF, которая поддерживается каждым браузером). Во-вторых, он имеет некоторые проблемы с поддержкой старых браузеров, таких как IE6. В-третьих, важное программное обеспечение, такое как Photoshop, имеет очень плохую реализацию формата. (Черт вас, Adobe!) PNG-8 может хранить только 256 цветов, например GIF.

Хорошо для: Главное, что PNG-8 работает лучше, чем GIF, поддерживает Alpha Transparency.

Важное примечание: Photoshop не поддерживает Alpha Transparency для файлов PNG-8. (Черт вас, Photoshop!) Есть способы конвертировать PNG-24 в PNG-8 файлы, сохраняя при этом свою прозрачность. Один из методов — PNGQuant, другой — сохранение ваших файлов с помощью Fireworks.


PNG-24 — Lossless/Direct

PNG-24 — отличный формат, который сочетает кодировку Lossless с прямым цветом (тысячи цветов, как JPEG). Это очень похоже на BMP в этом отношении, за исключением того, что PNG фактически сжимает изображения, поэтому это приводит к значительно меньшим файлам. К сожалению, файлы PNG-24 по-прежнему будут намного больше, чем JPEG, GIF и PNG-8, поэтому вам все равно нужно подумать, хотите ли вы его использовать.

Несмотря на то, что PNG-24 позволяют тысячи цветов при сжатии, они не предназначены для замены изображений JPEG. Фотография, сохраненная как PNG-24, скорее всего будет по меньшей мере в 5 раз больше, чем эквивалентное изображение в формате JPEG, что очень мало улучшает видимое качество. (Конечно, это может быть желательным результатом, если вас не интересует размер файла и вы хотите получить изображение лучшего качества, которое вы можете.)

Как и PNG-8, PNG-24 поддерживает альфа-прозрачность.

Я надеюсь, что это поможет!

qaru.site

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *