Specyfikacja kontenera WebP

Wstęp

WebP to format obrazu wykorzystujący (i) kodowanie klatki kluczowej VP8 do skompresowania danych obrazu stratnego lub (ii) bezstratne kodowanie WebP. Te schematy kodowania powinny zwiększyć wydajność niż starsze formaty, takie jak JPEG, GIF i PNG. Jest optymalizowana pod kątem szybkiego przesyłania obrazów przez sieć (np. w witrynach). Format WebP ma również te same funkcje (profil kolorów, metadane, animacje itp.) z innymi formatami. Ten dokument opisuje strukturę pliku WebP.

Kontener WebP (czyli kontener RIFF dla WebP) umożliwia obsługę funkcji na poziomie wyższym niż podstawowy przypadek użycia WebP (czyli plik zawierający pojedynczy obraz zakodowany jako ramka klucza VP8). Kontener WebP zapewnia dodatkową obsługę:

  • Kompresja bezstratna: obraz można kompresować bezstratnie za pomocą formatu WebP bezstratnego.

  • Metadane: obraz może mieć metadane zapisane w formacie Exif (Exif) lub Extensible Metadata Platform (XMP).

  • Przezroczystość: obraz może mieć przezroczystość, czyli kanał alfa.

  • Profil kolorów: obraz może mieć osadzony profil ICC zgodnie z opisem International Color Consortium (International Color Consortium).

  • Animacja: obraz może zawierać wiele klatek z przerwami między nimi, co sprawia, że jest animacją.

Nazwa

W odniesieniu do kontenera WebP ZALECAMY używać tych typów:

Nazwa formatu konteneraWebP
Rozszerzenie nazwy pliku.webp
Typ MIMEobraz/webp
Jednolity identyfikator typuorg.webmproject.webp

Terminologia i podstawy

Słowa kluczowe „MUST”, „MUST NOT”, „REQUIRED”, „SHALL”, „SHALL NOT”, „SHOULD”, „POWINNO”, „RECOMMENDED”, „NIEZALECANE”, „MAY” i „OPCJONALNIE” w tym dokumencie należy interpretować w sposób opisany w BCP 14 w sposób opisany w dokumencie BCP 14 RFC 2117, przy wykorzystaniu wielkich liter w dokumencie RFC 2117, RFC 2117 RFC 81.

Plik WebP zawiera nieruchomy obraz (czyli zakodowaną macierz pikseli) lub animację. Opcjonalnie może zawierać informacje o przejrzystości, profil kolorów i metadane. Macierz pikseli nazywamy kanwą obrazu.

Numeracja bitów na diagramach fragmentów rozpoczyna się od 0 dla najbardziej istotnego bitu („MSB 0”), zgodnie z opisem w RFC 1166.

Poniżej znajdziesz dodatkowe terminy używane w tym dokumencie:

Odczytujący/Zapisujący
Kod, który odczytuje pliki WebP, jest nazywany czytnikiem, a kod, który je zapisuje, nazywamy się programem zapisującym.
uint16
16-bitowa, typu little-endian liczba całkowita bez znaku.
uint24
24-bitowa, typu little-endian liczba całkowita bez znaku.
uint32
32-bitowa, typu little-endian liczba całkowita bez znaku.
FourCC
Czteroznakowy kod (FourCC) to uint32 utworzony przez połączenie 4 znaków ASCII w kolejności little-endian. Oznacza to, że wartości „aaaa” (0x61616161) i „AAAA” (0x41414141) są traktowane jak różne wartości FourCCs.
na podstawie 1,
Na przykład pole bez znaku liczby całkowitej, w którym są przechowywane wartości przesunięcia o wartość -1, na przykład zapisane w nim wartość 25 to 24.
ChunkHeader('ABCD')
Służy do opisywania nagłówków FourCC i Chunk size poszczególnych fragmentów, gdzie „ABCD” to „4CC” danego fragmentu. Rozmiar tego elementu wynosi 8 bajtów.

Format pliku RIFF

Format pliku WebP bazuje na formacie dokumentu RIFF (Resource Interchange File Format).

Podstawowym elementem pliku RIFF jest fragment. Elementy składowe:

 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                         :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Fragment FourCC: 32 bity
Czteroznakowy kod ASCII używany do identyfikacji fragmentów.
Rozmiar fragmentu: 32 bity (uint32)
Rozmiar fragmentu w bajtach, bez tego pola, identyfikatora fragmentu i dopełnienia.
Ładunek fragmentu: rozmiar fragmentu w bajtach
Ładunek danych. Jeśli Rozmiar fragmentu jest nieparzysty, dodawany jest pojedynczy bajt dopełnienia, który MUSI mieć wartość 0, aby uzyskać zgodność z RIFF.

Uwaga: w RIFF stosuje się konwencję polegającą na tym, że kody FourCC zawierające wyłącznie wielkie litery są standardowymi fragmentami mającymi zastosowanie do każdego formatu pliku RIFF. Natomiast znaki FourCC specyficzne dla danego formatu pliku pisane są małymi literami. WebP nie przestrzega tej konwencji.

Nagłówek pliku 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'      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
„RIFF”: 32 bity
Znaki ASCII: „R”, „I”, „F”, „F”.
Rozmiar pliku: 32 bity (uint32)
Rozmiar pliku w bajtach, zaczynając od przesunięcia 8. Maksymalna wartość tego pola to 2^32 minus 10 bajtów, więc rozmiar całego pliku wynosi maksymalnie 4 GiB minus 2 bajty.
„WEBP”: 32 bity
Znaki ASCII: „W”, „E”, „B”, „P”.

Plik WebP MUSI zaczynać się od nagłówka RIFF ciągiem znaków FourCC „WEBP”. Rozmiar pliku w nagłówku to łączny rozmiar następujących po nim fragmentów plus 4 B dla FourCC „WEBP”. Plik NIE POWINIEN zawierać żadnych danych po danych określonych przez Rozmiar pliku. Czytelnicy MOGĄ analizować takie pliki, ignorując dane na końcu. Ponieważ każdy fragment jest taki sam, rozmiar podany w nagłówku RIFF również jest równy. Zawartość poszczególnych fragmentów opisano w kolejnych sekcjach.

Prosty format pliku (stracony)

Tego układu POWINNO używać, jeśli obraz wymaga sformatowania i nie wymaga przezroczystości ani innych zaawansowanych funkcji zapewnianych w formacie rozszerzonym. Pliki z tym układem są mniejsze i obsługiwane przez starsze oprogramowanie.

Prosty format pliku WebP (stratny):

 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                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fragment „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                            :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Dane VP8: rozmiar fragmentu w bajtach
Strumień danych VP8.

Czwarty znak w „VP8 ” FourCC to spacja ASCII (0x20).

Specyfikacja formatu strumienia bitów VP8 jest opisana w artykule Przewodnik po formacie danych VP8 i jego dekodowaniu. Zwróć uwagę, że nagłówek ramki VP8 zawiera szerokość i wysokość klatki VP8. Przyjmuje się, że jest to szerokość i wysokość obszaru roboczego.

Specyfikacja VP8 opisuje, jak zdekodować obraz do formatu Y'CbCr. Aby dokonać konwersji na RGB, musisz użyć rekomendacji BT.601. Aplikacje MOGĄ korzystać z innej metody konwersji, ale w zależności od dekodera wyniki wizualne mogą się różnić.

Prosty format pliku (bezstratna)

Uwaga: starsze czytniki mogą nie obsługiwać plików w formacie bezstratnym.

Ten układ POWINNO używać, jeśli obraz wymaga bezstratnego kodowania (z opcjonalnym kanałem przezroczystości) i nie wymaga zaawansowanych funkcji dostępnych w formacie rozszerzonym.

Prosty format pliku WebP (bezstratny):

 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                          :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fragment „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                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Dane VP8L: rozmiar fragmentu w bajtach
Strumień danych VP8L.

Aktualną specyfikację strumienia bitowego VP8L można znaleźć w WebP Lossless Bitstream Format. Zwróć uwagę, że nagłówek VP8L zawiera szerokość i wysokość obrazu VP8L. Przyjmujemy, że chodzi o szerokość i wysokość obszaru roboczego.

Rozszerzony format pliku

Uwaga: starsi czytelnicy mogą nie obsługiwać plików w formacie rozszerzonym.

Plik w formacie rozszerzonym składa się z tych elementów:

  • Fragment „VP8X” z informacjami o funkcjach używanych w pliku.

  • Opcjonalny fragment „ICCP” z profilem kolorów.

  • Opcjonalny fragment „ANIM” z danymi do sterowania animacją.

  • Dane obrazu.

  • Opcjonalny fragment „EXIF” z metadanymi Exif.

  • Opcjonalny fragment „XMP” z metadanymi XMP.

  • Opcjonalna lista nieznanych fragmentów.

W przypadku nieruchomego zdjęcia dane obrazu składają się z jednej klatki z tych elementów:

W przypadku obrazu animowanego dane obrazu składają się z wielu klatek. Więcej informacji na temat ramek znajdziesz w sekcji Animacja.

Wszystkie fragmenty MUSZĄ zostać umieszczone w tej samej kolejności, która została podana powyżej. Jeśli fragment pojawi się w niewłaściwym miejscu, plik jest nieprawidłowy, ale czytelnicy MOGĄ go przeanalizować, ignorując nieprawidłowe fragmenty.

Uzasadnienie: ustawienie kolejności fragmentów powinien przyspieszyć analizę plików. Jeśli na przykład fragment „ALFA” nie pojawi się w wymaganej pozycji, dekoder może przerwać jego wyszukiwanie. Reguła ignorowania późnych fragmentów powinna sprawić, że programy, które muszą przeprowadzić pełne wyszukiwanie, dadzą takie same wyniki jak te, które przerywają wyszukiwanie za wcześnie.

Rozszerzony nagłówek pliku 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    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Zarezerwowana (RSV): 2 bity
MUSI mieć wartość 0. Czytelnicy MUSZĄ ignorować to pole.
Profil ICC (I): 1-bitowy
Ustaw, czy plik zawiera fragment „ICCP”.
alfa (L): 1 bit
Ustaw, jeśli którakolwiek z ramek obrazu zawiera informacje o przezroczystości („alfa”).
Metadane Exif (E): 1 bit
Określ, czy plik zawiera metadane Exif.
Metadane XMP (X): 1-bitowa
Określ, czy plik zawiera metadane XMP.
Animacja (A): 1-bitowa
Określ, czy jest to obraz animowany. Do sterowania animacją powinny być używane dane zawarte w fragmentach „ANIM” i „ANMF”.
Zarezerwowana (R): 1 bit
MUSI mieć wartość 0. Czytelnicy MUSZĄ ignorować to pole.
Zarezerwowane: 24 bity
MUSI mieć wartość 0. Czytelnicy MUSZĄ ignorować to pole.
Szerokość odbitki na płótnie minus jeden: 24 bity
Szerokość od 1 obszaru roboczego w pikselach. Rzeczywista szerokość odbitki na płótnie to 1 + Canvas Width Minus One.
Wysokość odbitki na płótnie minus jeden: 24 bity
Wysokość w odniesieniu do 1 obszaru roboczego w pikselach. Rzeczywista wysokość odbitki na płótnie to 1 + Canvas Height Minus One.

Iloczyn wartości opcji Szerokość płótna i Wysokość płótna MUSI wynosić maksymalnie 2^32 - 1.

Przyszłe specyfikacje mogą dodać więcej pól. Nieznane pola MUSZĄ zostać zignorowane.

Animacja

Animację sterują fragmenty „ANIM” i „ANMF”.

Fragment 'ANIM':

W przypadku animowanego obrazu ten fragment zawiera parametry globalne animacji.

 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           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Kolor tła: 32 bity (uint32)
Domyślny kolor tła odbitki na płótnie w kolejności bajtów: [niebieski, zielony, czerwony, alfa]. Ten kolor MOŻE wykorzystać do wypełnienia nieużywanej przestrzeni wokół ramek, a także przezroczystych pikseli pierwszej klatki. Kolor tła jest też używany, gdy metoda usuwania ma wartość 1.

Uwaga:

  • Kolor tła MOŻE zawierać nieprzezroczystą wartość alfa, nawet jeśli flaga alfa w fragmentie „VP8X” jest nieskonfigurowana.

  • Aplikacje przeglądające powinny traktować wartość koloru tła jako wskazówkę i nie muszą jej używać.

  • Obszar roboczy jest czyszczony na początku każdej pętli. MOŻNA w tym celu użyć koloru tła.

Liczba pętli: 16 bitów (uint16)
Liczba zapętlenia animacji. Jeśli ustawiona jest wartość 0, oznacza to bez ograniczeń.

Ten fragment MUSI pojawić się, jeśli we fragmencie „VP8X” jest ustawiona flaga Animacja. Jeśli flaga Animacja nie jest ustawiona i ten fragment jest obecny, MUSI być ignorowany.

Fragment „ANMF”:

W przypadku animowanych obrazów ten fragment zawiera informacje o pojedynczej klatce. Jeśli opcja Flaga animacji nie jest ustawiona, ten fragment NIE POWINNO być dostępny.

 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                            :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Ramka X: 24 bity (uint24)
Współrzędna X lewego górnego rogu klatki to Frame X * 2.
Ramka Y: 24 bity (uint24)
Współrzędna Y lewego górnego rogu klatki to Frame Y * 2.
Szerokość ramki minus jeden: 24 bity (uint24)
Szerokość klatki w od 1. Szerokość klatki to 1 + Frame Width Minus One.
Wysokość ramki minus One: 24 bity (uint24)
Wysokość klatki w przypadku 1. Wysokość klatki to 1 + Frame Height Minus One.
Czas trwania klatki: 24 bity (uint24)
Czas oczekiwania przed wyświetleniem następnej klatki, podany w jednostkach 1-milisekundowych. Pamiętaj, że interpretacja czasu trwania klatki wynosząca 0 (i często <= 10) jest określana przez implementację. Wiele narzędzi i przeglądarek przypisuje minimalny czas trwania podobny do GIF-ów.
Zarezerwowano: 6 bitów
MUSI mieć wartość 0. Czytelnicy MUSZĄ ignorować to pole.
Metoda mieszania (B): 1 bit

Wskazuje, jak przezroczyste piksele bieżącej klatki mają zostać zmieszane z odpowiednimi pikselami poprzedniej ramki:

  • 0: użyj mieszania alfa. Po usunięciu poprzedniej klatki wyrenderuj bieżącą klatkę w obszarze roboczym, korzystając z mieszania alfa (patrz poniżej). Jeśli bieżąca ramka nie ma kanału alfa, załóżmy, że wartość alfa to 255, zastępując prostokąt.

  • 1: nie mieszaj. Po usunięciu poprzedniej klatki wyrenderuj bieżącą klatkę w obszarze roboczym, zastępując prostokąt zasłaniający bieżącą ramkę.

Metoda utylizacji (D): 1-bitowa

Wskazuje, jak traktować bieżącą klatkę po jej wyświetleniu (przed wyrenderowaniem następnej klatki) w obszarze roboczym:

  • 0: nie wyrzucaj. Pozostaw obszar roboczy bez zmian.

  • 1: powoduje zmianę koloru tła. Wypełnij prostokąt obszaru roboczego pokrytego bieżącą ramką kolorem tła określonym w fragmentie „ANIM”.

Uwagi:

  • Usunięcie ramki dotyczy tylko prostokąta ramki, czyli prostokąta zdefiniowanego za pomocą atrybutów Ramka X, Ramka Y, szerokość ramki i wysokość ramki. Może zasłaniać całą przestrzeń roboczą, ale nie musi.

  • Mieszanie alfa:

    Biorąc pod uwagę, że kanały R, G, B i A są 8-bitowe, a kanały RGB nie są wstępnie mnożone przez alfa, formuła łączenia „dst” z „src” wygląda tak:

    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
    
  • Mieszanie alfa NALEŻY wykonywać w liniowej przestrzeni kolorów, biorąc pod uwagę profil kolorów obrazu. Jeśli profil kolorów nie jest dostępny, przyjmuje się standardowe RGB (sRGB). (Pamiętaj, że sRGB musi być też linearne z powodu gamma ok.2,2).

Dane ramki: rozmiar fragmentu16 B

Składa się z:

Uwaga: ładunek „ANMF” (Frame Data) powyżej składa się z pojedynczych dopełnionych fragmentów, zgodnie z formatem pliku RIFF.

Alfa

 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...                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Zarezerwowana (RSV): 2 bity
MUSI mieć wartość 0. Czytelnicy MUSZĄ ignorować to pole.
Przetwarzanie wstępne (P): 2 bity

Te informacyjne bity służą do sygnalizowania wstępnego przetwarzania danych, które zostało przeprowadzone podczas kompresji. Dekoder może używać tych informacji np. do przyciemniania wartości lub wygładzania gradientów przed ich wyświetleniem.

  • 0: brak wstępnego przetwarzania.
  • 1: obniżenie poziomu.

Dekodery nie muszą używać tych informacji w żaden określony sposób.

Metoda filtrowania (F): 2 bity

Dostępne metody filtrowania są opisane w następujący sposób:

  • 0: brak.
  • 1: filtr poziomy.
  • 2: filtr pionowy.
  • 3: filtr gradientu.

W przypadku każdego piksela filtrowanie jest przeprowadzane według tych obliczeń. Załóżmy, że wartości alfa otaczające bieżącą pozycję X są oznaczone jako:

 C | B |
---+---+
 A | X |

Obliczamy wartość alfa w pozycji X. Po pierwsze, prognoza jest tworzona na podstawie metody filtrowania:

  • Metoda 0: prognoza = 0
  • Metoda 1: prognoza = A
  • Metoda 2: prognoza = B
  • Metoda 3: prognoza = klip(A + B - C)

gdzie clip(v) równa się:

  • 0, jeśli v < 0,
  • 255, jeśli wersja v >255 lub
  • v w przeciwnym razie

Ostateczna wartość jest uzyskiwana przez dodanie do predykcji wartości zdekompresowanej X i użycie arytmetyki modulo-256 do zawijania zakresu [256..511] do [0..255]:

alpha = (predictor + X) % 256

Istnieją specjalne przypadki umieszczania pikseli skrajnie od lewej i najwyższej. Na przykład wartość w lewym górnym rogu w lokalizacji (0, 0) jako wartości prognozy używa 0. W innym przypadku:

  • W przypadku metod filtrowania poziomego i gradientowego na podstawie lokalizacji (0, y-1) tuż powyżej prognozowane są piksele znajdujące się najbardziej od lewej strony w lokalizacji (0, y).
  • W przypadku metod filtrowania pionowego i gradientowego przewidywanie pikseli znajdujących się najwyżej w lokalizacji (x, 0) jest ustalane na podstawie lokalizacji (x-1, 0) po lewej stronie.
Metoda kompresji (C): 2 bity

Użyta metoda kompresji:

  • 0: bez kompresji.
  • 1: skompresowano za pomocą bezstratnego formatu WebP.
Strumień bitów alfa: rozmiar fragmentu1 B

Zakodowany strumień bitów w wersji alfa.

Ten opcjonalny fragment zawiera zakodowane dane alfa dla tej ramki. Ramka zawierająca fragment „VP8L” NIE POWINIEN zawierać tego fragmentu.

Uzasadnienie: informacje o przejrzystości są już częścią fragmentu „VP8L”.

Dane kanału alfa są przechowywane w postaci nieskompresowanych nieprzetworzonych danych (gdy metoda kompresji ma wartość „0”) lub skompresowana w formacie bezstratnym (gdy metoda kompresji to „1”).

  • Nieprzetworzone dane: składa się z sekwencji bajtów o długości = szerokość × wysokość, ze wszystkimi 8-bitowymi wartościami przezroczystości w kolejności skanowania.

  • Kompresja formatu bezstratnego: sekwencja bajtów to skompresowany strumień obrazów (jak opisano w sekcji „WebP Lossless Bitstream Format”) o niejawnych wymiarach (szerokość x wysokość). Oznacza to, że ten strumień obrazów NIE zawiera żadnych nagłówków opisujących wymiary obrazu.

    Uzasadnienie: wymiary są już znane z innych źródeł, więc ich ponowne przechowywanie może być zbędne i ryzyko błędów.

    Po zdekodowaniu strumienia obrazu na wartości kolorów alfa, czerwonych, zielonych i niebieskich (ARGB) zgodnie z procesem opisanym w specyfikacji formatu bezstratnego informacje przezroczystości należy wyodrębnić z zielonego kanału czworokąta ARGB.

    Uzasadnienie: w specyfikacji dozwolony jest dodatkowy etap przekształcania (w odróżnieniu od innych kanałów), który może poprawić kompresję.

Strumień bitowy (VP8/VP8L)

Ten fragment zawiera skompresowane dane strumienia bitów dla pojedynczej klatki.

Fragmentem strumienia bitów może być (i) fragment „VP8” z wartością „VP8 ” (zwróć uwagę na istotną cztery znaki odstępu) jako jej FourCC, lub (ii) fragment „VP8L” z użyciem fragmentu „VP8L”.

Formaty fragmentów „VP8” i „VP8L” są opisane w sekcjach Prosty format pliku (Lossy) i Prosty format pliku (bezstratna).

Profil kolorów

 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                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Profil kolorów: rozmiar fragmentu w bajtach
Profil ICC.

Ten fragment MUSI pojawić się przed danymi obrazu.

POWINNO być co najwyżej jeden taki fragment. Jeśli tych fragmentów będzie więcej, czytelnicy mogą zignorować wszystkie oprócz pierwszego. Szczegółowe informacje znajdziesz w specyfikacji ICC.

Jeśli tego fragmentu nie ma, należy przyjąć, że jest to sRGB.

Metadane

Metadane można przechowywać w fragmentach „EXIF” lub „XMP”.

POWINIEN istnieć maksymalnie jeden fragment każdego typu („EXIF” i „XMP”). Jeśli takich fragmentów jest więcej, czytelnicy MOGĄ zignorować wszystkie z wyjątkiem pierwszego.

Fragmenty są zdefiniowane w ten sposób:

Fragment 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                          :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Metadane Exif: rozmiar fragmentu – bajty
Metadane obrazu w formacie Exif.

Fragment „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                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Metadane XMP: rozmiar fragmentu – bajty
Metadane obrazu w formacie XMP.

Czwarty znak w 'XMP ' FourCC to spacja ASCII (0x20).

Dodatkowe wskazówki dotyczące obsługi metadanych można znaleźć w wytycznych dotyczących obsługi metadanych przez grupę roboczą metadanych.

Nieznane fragmenty

Fragment RIFF (opisany w sekcji Format pliku RIFF), w którym format FourCC różni się od któregokolwiek z fragmentów opisanych w tym dokumencie, jest uważany za nieznany fragment.

Uzasadnienie: zezwolenie na nieznane fragmenty zapewnia postanowienie na potrzeby przyszłego rozszerzenia formatu i umożliwia przechowywanie dowolnych danych specyficznych dla aplikacji.

Plik MOŻE zawierać nieznane fragmenty:

Czytelnicy POWINNY ignorować te fragmenty. Autorzy powinni zachować je w pierwotnej kolejności (chyba że zamierzają je zmodyfikować).

Składanie odbitek na płótnie z ramek

Poniżej opisujemy, jak czytelnik MUSI złożyć odbitki na płótnie w przypadku obrazów animowanych.

Proces zaczyna się od utworzenia odbitki na płótnie o wymiarach podanych we fragmencie „VP8X” (szerokość Canvas Width Minus One + 1 piks. na Canvas Height Minus One + 1 piks.). Pole Loop Count fragmentu „ANIM” określa, ile razy proces animacji ma być powtarzany. Jest to Loop Count - 1 w przypadku wartości Loop Count innych niż zero lub nieskończona, jeśli Loop Count wynosi 0.

Na początku każdej iteracji pętli obszar roboczy jest wypełniany kolorem tła z fragmentu „ANIM” lub kolorem określonym przez aplikację.

Fragmenty „ANMF” zawierają poszczególne klatki w kolejności wyświetlania. Przed wyrenderowaniem każdej klatki stosowany jest Disposal method z poprzedniej klatki.

Renderowanie zdekodowanej ramki rozpoczyna się od współrzędnych kartezjańskich (2 * Frame X, 2 * Frame Y), a początkiem jest lewy górny róg obszaru roboczego. Rozmiar Frame Width Minus One + 1 piks. szerokości na Frame Height Minus One + 1 piks. jest renderowany na obszarze roboczym za pomocą dodatku Blending method.

Obszar roboczy jest wyświetlany przez Frame Duration milisekundy. Dzieje się tak, dopóki nie zostaną wyświetlone wszystkie klatki określone przez fragmenty „ANMF”. Rozpoczyna się nowa pętla lub obszar roboczy pozostaje w ostatecznym stanie, jeśli wszystkie iteracje zostały zakończone.

Poniższy pseudokod ilustruje proces renderowania. Notacja VP8X.field oznacza pole we fragmencie „VP8X” o takim samym opisie.

VP8X.flags.hasAnimation MUST be TRUE
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
         background color ANIM.background_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
    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

Przykładowe układy plików

Obraz z kodowaniem stratnym z kanałem alfa może wyglądać tak:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- ALPH (alpha bitstream)
+- VP8 (bitstream)

Obraz z kodowaniem bezstratnym może wyglądać tak:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- VP8L (lossless bitstream)
+- XYZW (unknown chunk)

Obraz bezstratny z profilem ICC i metadanymi XMP może wyglądać tak:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- ICCP (color profile)
+- VP8L (lossless bitstream)
+- XMP  (metadata)

Animowany obraz z metadanymi Exif może wyglądać tak:

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)