Введение
WebP — это формат изображения, который использует либо (i) кодирование ключевого кадра VP8 для сжатия данных изображения с потерями, либо (ii) кодирование без потерь WebP. Эти схемы кодирования должны сделать его более эффективным, чем старые форматы, такие как JPEG, GIF и PNG. Он оптимизирован для быстрой передачи изображений по сети (например, для веб-сайтов). Формат WebP также имеет одинаковые функции (цветовой профиль, метаданные, анимация и т. д.) с другими форматами. В этом документе описывается структура файла WebP.
Контейнер WebP (то есть контейнер RIFF для WebP) обеспечивает поддержку функций, выходящих за рамки базового варианта использования WebP (то есть файла, содержащего одно изображение, закодированное как ключевой кадр VP8). Контейнер WebP обеспечивает дополнительную поддержку следующего:
Сжатие без потерь: изображение можно сжать без потерь, используя формат WebP Lossless.
Метаданные: метаданные изображения могут храниться в формате сменного формата файла изображения (Exif) или расширяемой платформы метаданных (XMP).
Прозрачность: изображение может иметь прозрачность, то есть альфа-канал.
Цветовой профиль: изображение может иметь встроенный профиль ICC, как описано Международным консорциумом цвета .
Анимация. Изображение может состоять из нескольких кадров с паузами между ними, что делает его анимацией.
Именование
РЕКОМЕНДУЕТСЯ использовать следующие типы при обращении к контейнеру WebP:
Имя формата контейнера | ВебП |
Расширение имени файла | .webp |
MIME-тип | изображение/веб-страница |
Единый идентификатор типа | org.webmproject.webp |
Терминология и основы
Ключевые слова «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ТРЕБУЕТСЯ», «ДОЛЖЕН», «НЕ ДОЛЖЕН», «СЛЕДУЕТ», «НЕ СЛЕДУЕТ», «РЕКОМЕНДУЕТСЯ», «НЕ РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «НЕОБЯЗАТЕЛЬНО». " в этом документе следует интерпретировать, как описано в BCP 14 RFC 2119 RFC 8174 , тогда и только тогда, когда они написаны заглавными буквами, как показано здесь.
Файл WebP содержит либо неподвижное изображение (то есть закодированную матрицу пикселей), либо анимацию . При желании он также может содержать информацию о прозрачности, цветовой профиль и метаданные. Мы называем матрицу пикселей холстом изображения.
Нумерация битов в диаграммах фрагментов начинается с 0
для самого старшего бита («MSB 0»), как описано в RFC 1166 .
Ниже приведены дополнительные термины, используемые в этом документе:
- Читатель/Писатель
- Код, который читает файлы WebP, называется читателем , а код, который их записывает, — писателем .
- uint16
- 16-битное целое число без знака с прямым порядком байтов.
- uint24
- 24-битное целое число без знака с прямым порядком байтов.
- uint32
- 32-битное целое число без знака с прямым порядком байтов.
- ЧетыреCC
- Четырехсимвольный код (FourCC) — это uint32, созданный путем объединения четырех символов ASCII в порядке с прямым порядком байтов. Это означает, что «aaaa» (0x61616161) и «AAAA» (0x41414141) рассматриваются как разные FourCC .
- 1-основанный
- Целочисленное поле без знака, хранящее значения, смещенные, например, на
-1
, такое поле будет хранить значение 25 как 24 . - Заголовок Чанка('ABCD')
- Используется для описания заголовков FourCC и Chunk Size отдельных фрагментов, где «ABCD» — это FourCC для фрагмента. Размер этого элемента составляет 8 байт.
Формат файла RIFF
Формат файла WebP основан на формате документа RIFF (формат файла обмена ресурсами).
Базовым элементом файла RIFF является фрагмент . Он состоит из:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk FourCC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Chunk Payload :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Чанк FourCC: 32 бита
- Четырехсимвольный код ASCII, используемый для идентификации фрагмента.
- Размер чанка: 32 бита ( uint32 )
- Размер фрагмента в байтах, не включая это поле, идентификатор фрагмента или дополнение.
- Полезная нагрузка фрагмента: размер фрагмента в байтах.
- Полезная нагрузка данных. Если размер блока нечетный, добавляется один байт заполнения, который ДОЛЖЕН быть
0
, чтобы соответствовать RIFF.
Примечание . В RIFF принято соглашение, согласно которому фрагменты FourCC, написанные только заглавными буквами, являются стандартными фрагментами, применимыми к любому формату файла RIFF, тогда как все символы FourCC, специфичные для формата файла, имеют нижний регистр. WebP не следует этому соглашению.
Заголовок файла WebP
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'R' | 'I' | 'F' | 'F' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| File Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'W' | 'E' | 'B' | 'P' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- «РИФФ»: 32 бита
- Символы ASCII «R», «I», «F», «F».
- Размер файла: 32 бита ( uint32 )
- Размер файла в байтах, начиная со смещения 8. Максимальное значение этого поля составляет 2^32 минус 10 байт, поэтому размер всего файла составляет не более 4 ГиБ минус 2 байта.
- «WEBP»: 32 бита
- Символы ASCII «W», «E», «B», «P».
Файл WebP ДОЛЖЕН начинаться с заголовка RIFF с именем FourCC «WEBP». Размер файла в заголовке равен общему размеру следующих фрагментов плюс 4
байта для FourCC «WEBP». Файл НЕ ДОЛЖЕН содержать никаких данных после данных, указанных в поле «Размер файла» . Читатели МОГУТ анализировать такие файлы, игнорируя конечные данные. Поскольку размер любого фрагмента четный, размер, заданный заголовком RIFF, также четный. Содержимое отдельных блоков описано в следующих разделах.
Простой формат файла (с потерями)
Этот макет СЛЕДУЕТ использовать, если изображение требует кодирования с потерями и не требует прозрачности или других дополнительных функций, предоставляемых расширенным форматом. Файлы с таким макетом меньше по размеру и поддерживаются более старыми программами.
Простой формат файла WebP (с потерями):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: 'VP8 ' Chunk :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Чанк 'VP8':
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8 ') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8 data :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Данные VP8: размер блока в байтах
- Данные битового потока VP8.
Обратите внимание, что четвертый символ в FourCC 'VP8' представляет собой пробел ASCII (0x20).
Спецификация формата битового потока VP8 описана в Руководстве по формату и декодированию данных VP8 . Обратите внимание, что заголовок кадра VP8 содержит ширину и высоту кадра VP8. Предполагается, что это ширина и высота холста.
Спецификация VP8 описывает, как декодировать изображение в формат Y'CbCr. Для преобразования в RGB СЛЕДУЕТ использовать Рекомендацию BT.601 . Приложения МОГУТ использовать другой метод преобразования, но визуальные результаты могут отличаться в зависимости от декодера.
Простой формат файла (без потерь)
Примечание . Читатели старых версий могут не поддерживать файлы в формате без потерь.
Этот макет СЛЕДУЕТ использовать, если изображение требует кодирования без потерь (с дополнительным каналом прозрачности) и не требует расширенных функций, предоставляемых расширенным форматом.
Простой формат файла WebP (без потерь):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: 'VP8L' Chunk :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Чанк 'VP8L':
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8L') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8L data :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Данные VP8L: размер фрагмента в байтах
- Данные битового потока VP8L.
Текущую спецификацию битового потока VP8L можно найти на странице WebP Lossless Bitstream Format . Обратите внимание, что заголовок VP8L содержит ширину и высоту изображения VP8L. Предполагается, что это ширина и высота холста.
Расширенный формат файла
Примечание . Читатели старых версий могут не поддерживать файлы расширенного формата.
Файл расширенного формата состоит из:
Чанк «VP8X» с информацией о функциях, используемых в файле.
Дополнительный фрагмент ICCP с цветовым профилем.
Дополнительный фрагмент «ANIM» с данными управления анимацией.
Данные изображения.
Дополнительный фрагмент EXIF с метаданными Exif.
Дополнительный фрагмент «XMP» с метаданными XMP.
Необязательный список неизвестных фрагментов .
Для неподвижного изображения данные изображения состоят из одного кадра, который состоит из:
Необязательный альфа-подраздел .
Для анимированного изображения данные изображения состоят из нескольких кадров. Более подробную информацию о кадрах можно найти в разделе Анимация .
Все фрагменты, необходимые для реконструкции и цветокоррекции, то есть «VP8X», «ICCP», «ANIM», «ANMF», «ALPH», «VP8» и «VP8L», ДОЛЖНЫ появляться в порядке, описанном ранее. Считыватели ДОЛЖНЫ давать сбой, когда фрагменты, необходимые для реконструкции и цветокоррекции, не в порядке.
Метаданные и неизвестные фрагменты МОГУТ появиться не по порядку.
Обоснование: фрагменты, необходимые для реконструкции, должны появляться в файле первыми, чтобы позволить читателю начать декодирование изображения до получения всех данных. Приложение может получить выгоду от изменения порядка метаданных и пользовательских фрагментов в соответствии с реализацией.
Расширенный заголовок файла WebP:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8X') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv|I|L|E|X|A|R| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Canvas Width Minus One | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Canvas Height Minus One |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Зарезервировано (Rsv): 2 бита
- ДОЛЖЕН быть
0
. Читатели ДОЛЖНЫ игнорировать это поле. - Профиль ICC (I): 1 бит
- Установите, если файл содержит фрагмент ICCP.
- Альфа (L): 1 бит
- Установите, если какой-либо из кадров изображения содержит информацию о прозрачности («альфа»).
- Метаданные Exif (E): 1 бит
- Установите, если файл содержит метаданные Exif.
- Метаданные XMP (X): 1 бит.
- Установите, если файл содержит метаданные XMP.
- Анимация (А): 1 бит
- Установите, если это анимированное изображение. Данные в фрагментах «ANIM» и «ANMF» следует использовать для управления анимацией.
- Зарезервировано (R): 1 бит
- ДОЛЖЕН быть
0
. Читатели ДОЛЖНЫ игнорировать это поле. - Зарезервировано: 24 бита
- ДОЛЖЕН быть
0
. Читатели ДОЛЖНЫ игнорировать это поле. - Ширина холста минус один: 24 бита
- Ширина холста в пикселях отсчитывается от 1 . Фактическая ширина холста равна
1 + Canvas Width Minus One
. - Высота холста минус один: 24 бита.
- Высота холста в пикселях отсчитывается от 1 . Фактическая высота холста равна
1 + Canvas Height Minus One
.
Произведение ширины холста и высоты холста ДОЛЖНО быть не более 2^32 - 1
.
В будущих спецификациях могут быть добавлены дополнительные поля. Неизвестные поля ДОЛЖНЫ игнорироваться.
Анимация
Анимация управляется чанками «ANIM» и «ANMF».
Чанк «ANIM»:
Для анимированного изображения этот фрагмент содержит глобальные параметры анимации.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANIM') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Background Color |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Loop Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Цвет фона: 32 бита ( uint32 )
- Цвет фона холста по умолчанию в порядке байтов [Синий, Зеленый, Красный, Альфа]. Этот цвет МОЖЕТ использоваться для заполнения неиспользуемого пространства на холсте вокруг кадров, а также прозрачных пикселей первого кадра. Цвет фона также используется, если метод Disposal равен
1
.
Примечания :
Цвет фона МОЖЕТ содержать непрозрачное значение альфа, даже если флаг альфа в блоке «VP8X» не установлен.
Приложения просмотра ДОЛЖНЫ рассматривать значение цвета фона как подсказку и не обязаны его использовать.
Холст очищается в начале каждого цикла. Для этого МОЖЕТ использоваться цвет фона.
- Число циклов: 16 бит ( uint16 )
- Количество повторов анимации. Если это
0
, это означает бесконечно.
Этот фрагмент ДОЛЖЕН появиться, если установлен флаг анимации в фрагменте «VP8X». Если флаг анимации не установлен и этот фрагмент присутствует, его ДОЛЖНО игнорироваться.
Часть «ANMF»:
Для анимированных изображений этот фрагмент содержит информацию об одном кадре. Если флаг Animation не установлен, этот фрагмент НЕ ДОЛЖЕН присутствовать.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANMF') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame X | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Frame Y | Frame Width Minus One ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... | Frame Height Minus One |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Duration | Reserved |B|D|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Frame Data :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Кадр X: 24 бита ( uint24 )
- Координата X верхнего левого угла кадра —
Frame X * 2
. - Кадр Y: 24 бита ( uint24 )
- Координата Y верхнего левого угла кадра —
Frame Y * 2
. - Ширина кадра минус один: 24 бита ( uint24 )
- Ширина рамки, отсчитываемая от 1 . Ширина кадра равна
1 + Frame Width Minus One
. - Высота кадра минус один: 24 бита ( uint24 )
- Высота кадра , отсчитываемая от 1 . Высота кадра равна
1 + Frame Height Minus One
. - Длительность кадра: 24 бита ( uint24 )
- Время ожидания перед отображением следующего кадра с шагом в 1 миллисекунду. Обратите внимание, что интерпретация длительности кадра, равной 0 (и часто <= 10), определяется реализацией. Многие инструменты и браузеры назначают минимальную продолжительность, аналогичную GIF.
- Зарезервировано: 6 бит
- ДОЛЖЕН быть
0
. Читатели ДОЛЖНЫ игнорировать это поле. - Метод смешивания (B): 1 бит
Указывает, как прозрачные пиксели текущего кадра должны смешиваться с соответствующими пикселями предыдущего холста:
0
: использовать альфа-смешение. После удаления предыдущего кадра визуализируйте текущий кадр на холсте с помощью альфа-смешивания (см. ниже). Если текущий кадр не имеет альфа-канала, предположим, что значение альфа равно 255, что фактически заменяет прямоугольник.1
: Не смешивать. После удаления предыдущего кадра визуализируйте текущий кадр на холсте, перезаписав прямоугольник, покрытый текущим кадром.
- Метод утилизации (D): 1 бит
Указывает, как следует обрабатывать текущий кадр после его отображения (перед отрисовкой следующего кадра) на холсте:
0
: Не выбрасывать. Оставьте холст как есть.1
: Удалить цвет фона. Заполните прямоугольник на холсте, покрытый текущим кадром , цветом фона, указанным в чанк «ANIM» .
Примечания :
Удаление кадров применяется только к прямоугольнику кадра , то есть к прямоугольнику, определенному Frame X , Frame Y , шириной кадра и высотой кадра . Он может покрывать или не покрывать весь холст.
Альфа-смешение:
Учитывая, что каждый из каналов R, G, B и A имеет размер 8 бит, а каналы RGB не умножаются предварительно на альфа, формула для смешивания «dst» с «src» выглядит следующим образом:
blend.A = src.A + dst.A * (1 - src.A / 255) if blend.A = 0 then blend.RGB = 0 else blend.RGB = (src.RGB * src.A + dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
Альфа-смешение СЛЕДУЕТ выполнять в линейном цветовом пространстве с учетом цветового профиля изображения. Если цветовой профиль отсутствует, предполагается стандартный RGB (sRGB). (Обратите внимание, что sRGB также необходимо линеаризовать из-за гаммы ~ 2,2.)
- Данные кадра: размер фрагмента, байт —
16
Состоит из:
Необязательный альфа-подраздел для кадра.
Подчасть битового потока для кадра.
Необязательный список неизвестных фрагментов .
Примечание . Полезная нагрузка «ANMF», Frame Data , состоит из отдельных дополненных фрагментов, как описано в формате файла RIFF .
Альфа
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ALPH') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv| P | F | C | Alpha Bitstream... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Зарезервировано (Rsv): 2 бита
- ДОЛЖЕН быть
0
. Читатели ДОЛЖНЫ игнорировать это поле. - Предварительная обработка (P): 2 бита
Эти информативные биты используются для сигнализации предварительной обработки, выполненной во время сжатия. Декодер может использовать эту информацию, например, для размытия значений или сглаживания градиентов перед отображением.
-
0
: Без предварительной обработки. -
1
: Снижение уровня.
-
Декодеры не обязаны использовать эту информацию каким-либо определенным образом.
- Метод фильтрации (F): 2 бита
Используемые методы фильтрации описаны следующим образом:
-
0
: Нет. -
1
: Горизонтальный фильтр. -
2
: Вертикальный фильтр. -
3
: Градиентный фильтр.
-
Для каждого пикселя фильтрация выполняется с использованием следующих вычислений. Предположим, что значения альфа, окружающие текущую позицию X
, помечены как:
C | B |
---+---+
A | X |
Мы пытаемся вычислить значение альфа в позиции X
Сначала делается прогноз в зависимости от метода фильтрации:
- Метод
0
: предиктор = 0 - Метод
1
: предиктор = A - Метод
2
: предиктор = B - Метод
3
: предиктор = клип (A + B – C)
где clip(v)
равен:
- 0, если v < 0,
- 255, если v > 255, или
- в противном случае
Окончательное значение получается путем добавления распакованного значения X
к предиктору и использования арифметики по модулю 256 для переноса диапазона [256..511] в диапазон [0..255]:
alpha = (predictor + X) % 256
Существуют особые случаи для положения самого левого и самого верхнего пикселя. Например, верхнее левое значение в позиции (0, 0) использует 0 в качестве значения предиктора. В противном случае:
- Для методов горизонтальной или градиентной фильтрации самые левые пиксели в местоположении (0, y) прогнозируются с использованием местоположения (0, y-1), расположенного чуть выше.
- Для методов вертикальной или градиентной фильтрации самые верхние пиксели в местоположении (x, 0) прогнозируются с использованием местоположения (x-1, 0) слева.
- Метод сжатия (C): 2 бита
Используемый метод сжатия:
-
0
: Без сжатия. -
1
: сжато в формате WebP без потерь.
-
- Альфа-поток битов: размер блока в байтах —
1
Закодированный альфа-битовый поток.
Этот необязательный фрагмент содержит закодированные альфа-данные для этого кадра. Кадр, содержащий фрагмент «VP8L», НЕ ДОЛЖЕН содержать этот фрагмент.
Обоснование : информация о прозрачности уже является частью чанка «VP8L».
Данные альфа-канала сохраняются как несжатые необработанные данные (когда метод сжатия равен «0») или сжаты с использованием формата без потерь (когда метод сжатия равен «1»).
Необработанные данные: состоят из последовательности байтов длиной = ширины * высоты, содержащей все 8-битные значения прозрачности в порядке сканирования.
Сжатие формата без потерь: последовательность байтов представляет собой сжатый поток изображений (как описано в разделе «Формат потока битов без потерь WebP» ) неявных размеров ширина x высота. То есть этот поток изображений НЕ содержит заголовков, описывающих размеры изображения.
Обоснование : размеры уже известны из других источников, поэтому их повторное сохранение будет излишним и чревато ошибками.
После того, как поток изображения декодируется в значения цвета альфа, красный, зеленый, синий (ARGB) в соответствии с процессом, описанным в спецификации формата без потерь, информация о прозрачности должна быть извлечена из зеленого канала четверки ARGB.
Обоснование : в спецификации для зеленого канала разрешены дополнительные этапы преобразования — в отличие от других каналов — которые могут улучшить сжатие.
Битовый поток (VP8/VP8L)
Этот фрагмент содержит сжатые данные битового потока для одного кадра.
Фрагмент битового потока может быть либо (i) чаном 'VP8', использующим 'VP8' (обратите внимание на значительное пространство четвертого символа) в качестве FourCC, либо (ii) чаном 'VP8L', использующим 'VP8L' в качестве FourCC.
Форматы фрагментов «VP8» и «VP8L» описаны в разделах «Простой формат файла (с потерями)» и «Простой формат файла (без потерь)» соответственно.
Цветовой профиль
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ICCP') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Color Profile :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Цветовой профиль: Размер блока в байтах
- Профиль ICC.
Этот фрагмент ДОЛЖЕН появиться перед данными изображения.
ДОЛЖЕН быть не более одного такого фрагмента. Если таких фрагментов больше, читатели МОГУТ игнорировать все, кроме первого. Подробности см. в спецификации ICC .
Если этот фрагмент отсутствует, СЛЕДУЕТ использовать sRGB.
Метаданные
Метаданные могут храниться в фрагментах EXIF или XMP.
ДОЛЖНО быть не более одного фрагмента каждого типа («EXIF» и «XMP»). Если таких фрагментов больше, читатели МОГУТ игнорировать все, кроме первого.
Фрагменты определяются следующим образом:
Чанк EXIF:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('EXIF') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Exif Metadata :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Метаданные Exif: размер фрагмента в байтах
- Метаданные изображения в формате Exif.
Чанк «XMP»:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('XMP ') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: XMP Metadata :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Метаданные XMP: размер фрагмента в байтах
- Метаданные изображения в формате XMP.
Обратите внимание, что четвертый символ в FourCC «XMP» представляет собой пробел ASCII (0x20).
Дополнительные рекомендации по работе с метаданными можно найти в «Рекомендациях по обработке метаданных» Рабочей группы по метаданным.
Неизвестные куски
Чанк RIFF (описанный в разделе «Формат файла RIFF» ), FourCC которого отличается от любого из фрагментов, описанных в этом документе, считается неизвестным чанком .
Обоснование : разрешение неизвестных фрагментов обеспечивает возможность будущего расширения формата, а также позволяет хранить любые данные, специфичные для приложения.
Файл МОЖЕТ содержать неизвестные фрагменты:
- в конце файла, как описано в разделе расширенного заголовка файла WebP , или
- в конце фрагментов «ANMF», как описано в разделе «Анимация» .
Читателям СЛЕДУЕТ игнорировать эти фрагменты. Авторы ДОЛЖНЫ сохранять их в исходном порядке (если они специально не намерены изменять эти фрагменты).
Сборка холста из рамок
Здесь мы даем обзор того, как читатель ДОЛЖЕН собрать холст в случае анимированного изображения.
Процесс начинается с создания холста с использованием размеров, указанных в фрагменте «VP8X»: Canvas Width Minus One + 1
пиксель в ширину и Canvas Height Minus One + 1
пиксель в высоту. Поле Loop Count
» блока «ANIM» определяет, сколько раз повторяется процесс анимации. Это Loop Count - 1
для ненулевых значений Loop Count
или бесконечное, если Loop Count
равно нулю.
В начале каждой итерации цикла холст заполняется цветом фона из чанка «ANIM» или цветом, определенным приложением.
Чанки «ANMF» содержат отдельные кадры, заданные в порядке отображения. Перед рендерингом каждого кадра применяется Disposal method
предыдущего кадра.
Рендеринг декодированного кадра начинается с декартовых координат ( 2 * Frame X
, 2 * Frame Y
), используя верхний левый угол холста в качестве начала координат. Frame Width Minus One + 1
пиксель в ширину и Frame Height Minus One + 1
пиксель в высоту визуализируются на холсте с использованием Blending method
.
Холст отображается в течение миллисекунд Frame Duration
. Это продолжается до тех пор, пока не будут отображены все кадры, заданные фрагментами «ANMF». Затем начинается новая итерация цикла или холст остается в конечном состоянии, если все итерации завершены.
Следующий псевдокод иллюстрирует процесс рендеринга. Обозначение VP8X.field означает поле в чане 'VP8X' с тем же описанием.
VP8X.flags.hasAnimation MUST be TRUE
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
background color ANIM.background_color or
application-defined color.
loop_count ← ANIM.loopCount
dispose_method ← Dispose to background color
if loop_count == 0:
loop_count = ∞
frame_params ← nil
next chunk in image_data is ANMF MUST be TRUE
for loop = 0..loop_count - 1
clear canvas to ANIM.background_color or application-defined color
until eof or non-ANMF chunk
frame_params.frameX = Frame X
frame_params.frameY = Frame Y
frame_params.frameWidth = Frame Width Minus One + 1
frame_params.frameHeight = Frame Height Minus One + 1
frame_params.frameDuration = Frame Duration
frame_right = frame_params.frameX + frame_params.frameWidth
frame_bottom = frame_params.frameY + frame_params.frameHeight
VP8X.canvasWidth >= frame_right MUST be TRUE
VP8X.canvasHeight >= frame_bottom MUST be TRUE
for subchunk in 'Frame Data':
if subchunk.tag == "ALPH":
alpha subchunks not found in 'Frame Data' earlier MUST be
TRUE
frame_params.alpha = alpha_data
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
bitstream subchunks not found in 'Frame Data' earlier MUST
be TRUE
frame_params.bitstream = bitstream_data
apply dispose_method.
render frame with frame_params.alpha and frame_params.bitstream
on canvas with top-left corner at (frame_params.frameX,
frame_params.frameY), using Blending method
frame_params.blendingMethod.
canvas contains the decoded image.
Show the contents of the canvas for
frame_params.frameDuration * 1 ms.
dispose_method = frame_params.disposeMethod
Примеры макетов файлов
Изображение с потерями и альфа-кодированием может выглядеть следующим образом:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ALPH (alpha bitstream)
+- VP8 (bitstream)
Изображение, закодированное без потерь, может выглядеть следующим образом:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- VP8L (lossless bitstream)
+- XYZW (unknown chunk)
Изображение без потерь с профилем ICC и метаданными XMP может выглядеть следующим образом:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ICCP (color profile)
+- VP8L (lossless bitstream)
+- XMP (metadata)
Анимированное изображение с метаданными Exif может выглядеть следующим образом:
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ANIM (global animation parameters)
+- ANMF (frame1 parameters + data)
+- ANMF (frame2 parameters + data)
+- ANMF (frame3 parameters + data)
+- ANMF (frame4 parameters + data)
+- EXIF (metadata)