С давних времен, на страницах интернета используются растровые (а ныне и векторные) изображения. Без них интернет был бы скучным и однообразным, был бы абстрактным, не понятным. Однако изображения требуют сжатия, поскольку в сыром виде имеют большой размер и их трудно передавать от сервера клиенту. Под катом — «текстовый» курс про JNG формат.
Начало начал
Сегодня мы можем использовать только три растровых формата: PNG, JPEG и GIF.
JPEG — формат для хранения фотографий. Сжимает с потерями качества, альфа-канал не поддерживает.
PNG — формат для хранения графиков. Сжимает без потерь по алгоритму DEFLATE. Поддерживает альфа-канал, но не пригоден для распечатки из-за отсутствия поддержки CMYK. Используется, как правило, только в Web-страницах. Создан как замена GIF, но при этом, не поддерживает анимацию.
GIF — формат изображений для интернета. Существовал в Web 1.0, но перекочевал в последующие из-за широкой поддержкой браузером IE и поддержки анимации. Поддерживает 256 цветов (хотя известны способы обойти). Поддерживает всего один цвет прозрачности.
SVG — формат векторных изображений. Имеет узкую поддержку, если использовать как изображение. Для более широкой поддержки нужно использовать как приложение (апплет).
Google разрабатывает формат WebP, который совмещает возможности сжатия без потерь и сжатия с потерями, поддержку альфа-канала, цветовых профилей, анимацию. Однако браузеры не смешать вводить его поддержку. Кроме того, этот формат, как и JPEG или PNG, сложен в декодировании. Вероятно, этот формат не будет так ширико популярным еще ближайшие 20 лет.
В наше время можно использовать HTML5 Canvas для отображения «кастомных» изображений, анимаций, также можно использовать в качестве «дисплея» любого веб-приложения. Но из-за отсутствия поддержки в IE, люди вынуждены искать обходные пути (например использовать Flash от Adobe).
Разработчики libpng разработали формат MNG, а вместе с ним JNG. MNG должен был добавить в Web поддержку сложной и высококачественной анимации. Однако эти форматы продержались не долго. Вскоре их заместил Flash.
JNG — это часть спецификации формата MNG. Это контейнер для одного или двух изображений (один из которых — альфа-канал). Как и PNG, имеет чанковую структуру. Отличается только тем, что хранит RGB в отдельном поток, закодированном как JPEG изображение и альфа-канал как данные PNG (серая шкала) или JPEG изображение.
JNG был бы полезен для фотографий, где необходим альфа-канал. В современном Web можно использовать Canvas или SVG, но JNG был более полезен, поскольку его можно создать при помощи плагина фотошопа или получить при помощи ImageMagick.
JNG — теория
Ссылаясь на спецификацию, JNG состоит из сигнатуры (8 байт) и чанков (chunks). Его основные чанки:
JHDR — заголовок изображения
JDAT — закодированное JPEG изображение
IDAT — PNG данные (альфа-канал)
JDAA — JPEG изображение (альфа-канал)
IEND — конец файла
Каждый чанк состоит из:
Длина — 4 байта
Имя — 4 байта (ANSII)
Данные — Длина байт
CRC32 — 4 байта
JHDR данные содержит следующие байты:
4 байта ширина,
4 байта высота,
1 байт цветовой тип,
1 байт глубина основного потока,
1 байт компрессия JPEG,
1 байт чересстрочность,
1 байт глубина альфа-канала,
1 байт сжатия альфа-канала (JPEG или PNG),
1 байт фильтрация альфа-канала (только если PNG),
1 байт чересстрочность альфа-канала.
Наша основная задача — разобрать JNG изображение на два или один файл.
Разбираем альфа-канал, закодированный в PNG
Самое сложное — собрать альфа-канал, закодированный в PNG. Ведь PNG состоит следующим образом:
IHDR, IDAT, IEND
Где IHDR:
4 байта ширина,
4 байта высота,
1 байт глубина цвета
1 байт цветовой тип
1 байт сжатие
1 байт фильтр
1 байт чересстрочность
Чтобы собрать PNG альфа-канал, нужно действовать по пунктам
0. Написать сигнатуру PNG (читать в спецификации PNG).
1. Собрать данные IHDR следующим образом: перенести байты ширины и высота, цветовой тип назначить как ноль (0), а все остальное перенести с JHDR байтов, отвечающий за альфа-канал соответственно с PNG байтами.
2. Перенести все IDAT чанки.
3. Записать IEND чанк.
Разбираем JPEG потоки
Что альфа-канал, что основной поток, можно действовать по одному принципу: «склеить» содержимое всех чанков поочередно (не сами чанки, а их данные).
Для чего все это нужно?
Это нужно для того, чтобы браузер мог прочитать данные как PNG и JPEG
Как отрисовать альфа-канал и основное изображение?
В этой статье я не дам описание, как это сделать. Будет время — напишу в следующий раз
Где найти спецификации?
www.libpng.org/pub/mng/spec/jng.html — JNG
www.w3.org/TR/PNG/ — PNG
Подскажите 8 байтовые сигнатуры
139 74 78 71 13 10 26 10 - JNG
137 80 78 71 13 10 26 10 - PNG
Сигнатуры в десятичной системе счислений.
Есть ли примеры?
Я раньше экспериментировал на JavaScript. Сейчас у меня нету ни копий, ни самой работы и результатов экспериментов. Единственное что я могу сказать — работало отлично при всех JNG изображениях. Все зависит от того, как разрабатывать.
Что вы можете посоветовать?
1. Использовать XHR2, причем советую выбирать responseType как «arraybuffer».
2. Вместо кодирования в Base64 советую использовать объект Blob и функцию URL.createObjectURL к объекту Blob.
3. Не пренебрегать типизированными массивами, а также DataView API.
4. FileReader лучше использовать только при приеме с формы (input).
5. Ну и конечно же больше работать над файлами.
Что такое CRC32?
Из Википедии: «Циклический избыточный код (англ. Cyclic redundancy code, CRC[1]) — алгоритм вычисления контрольной суммы, предназначенный для проверки целостности передаваемых данных. Алгоритм CRC обнаруживает все одиночные ошибки, двойные ошибки и ошибки в нечетном числе битов.»
Можете прочитать здесь.
Заключение
Мы детально рассмотрели формат JNG. Мы рассказали, как разобрать его на файлы, а также познакомились получили некоторые знания о программировании.
Я буду дальше работать над темой изображений, в том числе про JNG.
Автор: Alexei03a