Specyfikacja kontenera WebP

Wstęp

WebP to format obrazu, który wykorzystuje (i) kodowanie klatki kluczowej VP8 do kompresowania danych obrazu w sposób stratny lub (ii) bezstratne kodowanie WebP. Ten schemat kodowania powinien zwiększyć wydajność tego formatu niż starsze formaty, takie jak JPEG, GIF i PNG. Jest zoptymalizowana pod kątem szybkiego przesyłania obrazów przez sieć (np. na potrzeby witryn). Format WebP ma również takie 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 ponad podstawowy przypadek użycia WebP (czyli pliku zawierającego pojedynczy obraz zakodowany jako ramka klucza VP8). Kontener WebP zapewnia dodatkową obsługę:

  • Kompresja bezstratna: obraz można kompresować bezstratnie w formacie bezstratnym WebP.

  • 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: zdjęcie może mieć osadzony profil ICC zgodnie z opisem organizacji International Color Consortium.

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

Nazwa

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

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

Terminologia i podstawy

Słowa kluczowe „MUSZ”, „MUSZ NIE”, „WYMAGANE”, „SHALL”, „NIE POWINNY”, „POWINNY”, „NIE POWINNY”, „RECOMMENDED”, „NOT RECOMMENDED”, „MAY” i „OPCJONALNIE” w tym dokumencie należy interpretować w sposób opisany w BCP 14 RFC 2117 w dokumencie RFC 2117, w przypadku użycia wielkich liter.RFC 8

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

Numeracja bitów w diagramach fragmentów zaczyna 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, nazywany jest kodem zapisującym.
uint16
16-bitowa, typu little-endian, nieoznaczona liczba całkowita.
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 ciąg uint32 utworzony przez połączenie 4 znaków ASCII w kolejności little-endian. Oznacza to, że „aaaa” (0x61616161) i „AAAA” (0x41414141) są traktowane jak różne FourCCs.
Na podstawie 1
Na przykład pole z liczbą całkowitą bez znaku, w której są przechowywane wartości przesunięcia o wartość -1, np. zapisywałoby ono wartość 25 jako 24.
ChunkHeader('ABCD')
Używane do opisania nagłówków FourCC i Chunk size poszczególnych fragmentów, gdzie „ABCD” to ciąg FourCC. Rozmiar tego elementu to 8 bajtów.

Format pliku RIFF

Format pliku WebP opiera się 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 ani dopełnienia.
Ładunek fragmentu: rozmiar fragmentu – bajty
Ładunek danych. Jeśli Rozmiar fragmentu jest nieparzysty, dodawany jest pojedynczy bajt dopełnienia, który MUSI 0, aby zapewnić zgodność z RIFF.

Uwaga: w RIFF stosuje się konwencję polegającą na tym, że zapisane wielkimi literami fragmenty kodu FourCC są standardowymi fragmentami mającymi zastosowanie do dowolnego formatu plików RIFF. Natomiast nazwy FourCC charakterystyczne dla danego formatu plików stosuje się małymi literami. WebP nie jest zgodny z tą konwencją.

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 z ciągiem FourCC „WEBP”. Rozmiar pliku w nagłówku to łączny rozmiar następujących po nim fragmentów plus 4 B w przypadku FourCC „WEBP” Plik NIE POWINIEN zawierać żadnych danych następujących po danych określonej przez Rozmiar pliku. Czytniki MOGĄ analizować takie pliki, ignorując dane końcowe. Wielkość fragmentu jest równa, więc rozmiar podany w nagłówku RIFF również jest równomierny. Zawartość poszczególnych fragmentów opisano w kolejnych sekcjach.

Prosty format pliku (stratny)

Tego układu NALEŻY użyć, jeśli obraz wymaga kodowania strasznego i nie wymaga przezroczystości ani innych zaawansowanych funkcji zapewnianych w formacie rozszerzonym. Pliki o tym układzie są mniejsze i obsługiwane przez starsze oprogramowanie.

Prosty format 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)                |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                        '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 – bajty
Strumień danych VP8.

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

Specyfikacja formatu strumienia bitów VP8 jest opisana w Przewodniku po formacie danych i dekodowaniu formatu VP8. Pamiętaj, że nagłówek ramki VP8 zawiera szerokość i wysokość ramki 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Ą wykorzystywać inną metodę konwersji, ale w przypadku różnych dekoderów wyniki wizualne mogą się różnić.

Prosty format pliku (bezstratny)

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

Tego układu NALEŻY używać, jeśli obraz wymaga kodowania bezstratnego (z opcjonalnym kanałem przezroczystości) i nie wymaga zaawansowanych funkcji zapewnianych przez format rozszerzony.

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 – bajty
Strumień danych bitowych VP8L.

Aktualną specyfikację strumienia bitów VP8L można znaleźć w formacie bezstratnego strumienia bitów WebP. Zwróć uwagę, że nagłówek VP8L zawiera szerokość i wysokość obrazu VP8L. Przyjmujemy, że jest to 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:

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

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

  • Opcjonalny fragment „ANIM” z danymi sterującymi 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, która składa się z:

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

Wszystkie fragmenty niezbędne do rekonstrukcji i korekcji kolorów, tj. „VP8X”, „ICCP”, „ANIM”, „ANMF”, „ALPH”, „VP8” i „VP8L”, MUSZĄ pojawić się w kolejności opisanej wcześniej. Jeśli fragmenty tekstu niezbędne do rekonstrukcji i korekcji kolorów nie są uporządkowane, czytelnicy POWINNY zakończyć błąd.

Metadane i nieznane fragmenty MOGĄ wyświetlać się w złej kolejności.

Uzasadnienie: fragmenty niezbędne do zrekonstruowania powinny występować w pliku jako pierwsze, aby czytelnik mógł rozpocząć dekodowanie obrazu przed odebraniem wszystkich danych. W aplikacji może pomóc zmiana kolejności metadanych i niestandardowych fragmentów w zależności od implementacji.

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    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Zarezerwowane (Rsv): 2 bity
MUSI mieć wartość 0. Czytelnicy MUSZĄ ignorować to pole.
Profil ICC (I): 1-bitowy
Ustaw, jeśli plik zawiera fragment „ICCP”.
Alfa (L): 1 bit
Ustaw, jeśli któraś z ramek obrazu zawiera informacje przezroczystości („alfa”).
Metadane Exif (E): 1 bit
Określa, czy plik zawiera metadane Exif.
Metadane XMP (X): 1-bitowe
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”.
Zarezerwowane (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ść obszaru roboczego minus jeden: 24 bity
Szerokość obszaru roboczego w pikselach od 1. Rzeczywista szerokość odbitki na płótnie to 1 + Canvas Width Minus One.
Wysokość odbitki na płótnie minus jeden: 24 bity
Wysokość obszaru roboczego w pikselach (o: 1). Rzeczywista wysokość obszaru roboczego to 1 + Canvas Height Minus One.

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

Przyszła specyfikacja może zawierać więcej pól. Nieznane pola MUSZĄ zostać zignorowane.

Animacja

Animacja jest kontrolowana przez 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 obszaru roboczego w kolejności bajtów: [niebieski, zielony, czerwony, alfa]. Ten kolor MOŻE zostać użyty 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 we fragmencie „VP8X” nie jest skonfigurowana.

  • Aplikacje gogli 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ŻE W tym celu można użyć koloru tła.

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

Ten fragment MUSI pojawić się, jeśli we fragmencie „VP8X” jest ustawiona flaga Animation. Jeśli flaga Animacja nie jest ustawiona, a ten fragment występuje, MUSI zostać zignorowana.

Fragment „ANMF”:

W przypadku animowanych obrazów ten fragment zawiera informacje o pojedynczej ramce. Jeśli 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 kadru to Frame X * 2.
Ramka Y: 24 bity (uint24)
Współrzędna Y lewego górnego rogu kadru to Frame Y * 2.
Szerokość ramki minus jeden: 24 bity (uint24)
Szerokość klatki, w oparciu o 1. Szerokość ramki to 1 + Frame Width Minus One.
Wysokość ramki minus jeden: 24 bity (uint24)
Wysokość klatki w oparciu o 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 wartość czasu trwania klatki równa 0 (i często jest to <= 10) zależy od implementacji. Wiele narzędzi i przeglądarek przypisuje minimalny czas trwania podobny do GIF-ów.
Zarezerwowane: 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 przestrzeni roboczej:

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

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

Metoda utylizacji (D): 1 bit

Wskazuje sposób traktowania bieżącej klatki po jej wyświetleniu (przed wyrenderowaniem następnej klatki) w obszarze roboczym:

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

  • 1: usuń z kolorem tła. Wypełnij prostokąt obszaru roboczego pokrytego bieżącą ramką kolorem tła określonym w fragmentie „ANIM”.

Uwagi:

  • Usuwanie ramki dotyczy tylko prostokąta ramki, czyli prostokąta zdefiniowanego za pomocą właściwości Ramka X, Ramka Y, szerokość ramki i wysokość ramki. Może zasłaniać całą powierzchnię, ale nie musi.

  • Mieszanie alfa:

    Biorąc pod uwagę, że każdy z kanałów R, G, B i A ma 8 bitów, a kanały RGB nie są wstępnie mnożone przez alfa, formuła do łą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 powinno być wykonywane w liniowej przestrzeni kolorów z uwzględnieniem profilu kolorów zdjęcia. Jeśli nie ma profilu kolorów, należy przyjąć standardowe RGB (sRGB). (Pamiętaj, że jasność sRGB musi zostać liniowa z powodu gamma ok.2,2).

Dane ramki: rozmiar fragmentu16 B

Elementy składowe:

Uwaga: ładunek „ANMF” – Frame Data (Dane ramki) – składa się z pojedynczych dopełnionych fragmentów zgodnie z opisem w formacie 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...                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Zarezerwowane (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, które zostało wykonane podczas kompresji. Na podstawie tych informacji dekoder może na przykład skorygować wartości lub wygładzić gradienty przed ich wyświetleniem.

  • 0: brak wstępnego przetwarzania.
  • 1: zmniejszenie poziomu.

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

Metoda filtrowania (F): 2 bity

Używane metody filtrowania są opisane w następujący sposób:

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

Dla każdego piksela filtrowanie jest wykonywane przy użyciu następujących obliczeń. Załóżmy, że wartości alfa otaczające bieżącą pozycję X są oznaczone jako:

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

Obliczamy wartość alfa na pozycji X. Po pierwsze, prognoza jest tworzona w zależności od metody filtrowania:

  • Metoda 0: prognozator = 0
  • Metoda 1: prognozator = A
  • Metoda 2: prognozator = B
  • Metoda 3: prognozator = clip(A + B – C)

gdzie clip(v) ma wartość równą:

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

Ostateczną wartość uzyskuje się przez dodanie zdekompresowanej wartości X do prognozy i użycie funkcji arytmetycznej modulo-256 w celu zawijania zakresu [256..511] do wartości [0..255]:

alpha = (predictor + X) % 256

Istnieją specjalne przypadki określania położenia pikseli na górze i od lewej. Na przykład wartość w lewym górnym rogu w lokalizacji (0, 0) ma wartość 0. W innym przypadku:

  • W przypadku metod filtrowania poziomego i gradientowego na podstawie lokalizacji (0, y–1) znajdującej się najbardziej po lewej stronie są prognozowane piksele w lokalizacji (0, y).
  • W przypadku metod filtrowania pionowego lub gradientowego na podstawie lokalizacji (x-1, 0) po lewej stronie przewidywano piksele znajdujące się najwyżej w lokalizacji (x, 0).
Metoda kompresji (C): 2 bity

Użyta metoda kompresji:

  • 0: bez kompresji.
  • 1: skompresowany w bezstratnym formacie WebP.
Strumień bitów alfa: rozmiar fragmentu1 B

Zakodowany strumień bitów alfa.

Ten opcjonalny fragment zawiera dane w wersji alfa zakodowane na potrzeby tej ramki. Ramka zawierająca fragment „VP8L” NIE POWINNO go zawierać.

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

Dane kanału alfa są przechowywane jako nieskompresowane nieprzetworzone dane (gdy metoda kompresji ma wartość „0”) lub skompresowane w formacie bezstratnym (gdy metoda kompresji ma wartość „1”).

  • Nieprzetworzone dane: składa się z sekwencji bajtów o długości = szerokość × wysokość, która zawiera wszystkie 8-bitowe wartości przezroczystości w kolejności skanowania.

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

    Uzasadnienie: te wymiary są już znane z innych źródeł, więc ponowne ich przechowywanie może być zbędne i obciążać nimi błędy.

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

    Uzasadnienie: w specyfikacji są dostępne dodatkowe etapy przekształcania – w przeciwieństwie do innych kanałów – które mogą 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ą czwartą spację jako cztery znaki) jako wartość FourCC lub (ii) fragment „VP8L” z użyciem „VP8L” jako jej FourCC.

Formaty fragmentów „VP8” i „VP8L” zostały opisane w sekcjach Prosty format pliku (Lossy) i Prosty format pliku (bezstratny).

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 istnieć maksymalnie jeden taki fragment. Jeśli będzie więcej takich fragmentów, czytelnicy mogą zignorować wszystkie z wyjątkiem pierwszego. Szczegółowe informacje znajdziesz w specyfikacji ICC.

Jeśli ten fragment nie jest dostępny, POWINIEN zostać zatrzymana funkcja sRGB.

Metadane

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

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

Fragmenty są zdefiniowane w następujący 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 nazwie „XMP ” FourCC to spacja ASCII (0x20).

Dodatkowe wskazówki na temat postępowania z metadanymi można znaleźć w wytycznych dotyczących postępowania z metadanymi w grupie roboczej metadanych.

Nieznane fragmenty

Fragment RIFF (opisany w sekcji Format pliku RIFF), w którym 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 daje możliwość późniejszego rozszerzenia formatu i pozwala na przechowywanie dowolnych danych specyficznych dla aplikacji.

Plik MOŻE zawierać nieznane fragmenty:

Czytelnicy POWINNY ignorować te fragmenty. Autorzy powinni zachować je w oryginalnej kolejności (chyba że wyraźnie chcą je modyfikować).

Składanie płótna z ramek

Poniżej opisujemy, jak czytelnik MUSI utworzyć płótno w przypadku animowanego obrazu.

Proces rozpoczyna się od utworzenia obszaru roboczego 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 niezerowych wartości Loop Count lub nieskończony, 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ą pojedyncze klatki podane w kolejności wyświetlania. Przed wyrenderowaniem każdej klatki stosowany jest Disposal method z poprzedniej ramki.

Renderowanie zdekodowanej ramki rozpoczyna się od współrzędnych kartezjańskich (2 * Frame X, 2 * Frame Y), gdzie punktem początkowym jest lewy górny róg obszaru roboczego. Za pomocą komponentu Blending method renderujemy w obszarze roboczym Frame Width Minus One + 1 piks. szerokości na Frame Height Minus One + 1 piks.

Obszar roboczy jest wyświetlany przez Frame Duration milisekund. Działa to, dopóki nie zostaną wyświetlone wszystkie klatki pochodzące z fragmentów „ANMF”. Rozpoczyna się nowa iteracja pętli lub po zakończeniu wszystkich iteracji obszar roboczy pozostaje w ostatecznym stanie.

Poniższy pseudokod ilustruje proces renderowania. Zapis VP8X.field oznacza pole we fragmencie „VP8X” o tym 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 kodem alfa może wyglądać tak:

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

Obraz z kodowaniem w formacie 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)