Specyfikacja kontenera WebP

Wprowadzenie

WebP to format obrazu wykorzystujący (i) kodowanie klatek kluczowych VP8 do kompresji danych obrazu w sposób stratny lub (ii) kodowanie bezstratne WebP. Te schematy kodowania powinny być wydajniejsze niż starsze formaty, takie jak JPEG, GIF i PNG. Jest zoptymalizowana pod kątem szybkiego przesyłania obrazów przez sieć (na przykład w przypadku witryn). Format WebP ma te same funkcje (profil kolorów, metadane, animacja itp.) co inne formaty. Ten dokument opisuje strukturę pliku WebP.

Kontener WebP (czyli kontener RIFF dla WebP) umożliwia obsługę funkcji ponad podstawowy przypadek użycia (czyli plik zawierający pojedynczy obraz zakodowany jako ramka klucza VP8). Kontener WebP zapewnia dodatkową obsługę następujących danych:

  • Kompresja bezstratna: obraz można skompresować bezstratnie, używając formatu WebP Lossless.

  • Metadane: obraz może zawierać metadane zapisane w formacie Exif lub XMP.

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

  • Profil kolorów: obraz może mieć wbudowany profil ICC zgodnie z opisem Międzynarodowego Konsorcjum Kolorów.

  • Animacja: obraz może składać się z kilku klatek z przerwam między nimi, co tworzy animację.

Nazwa

Zalecamy używanie tych typów w odniesieniu do kontenera WebP:

Nazwa formatu konteneraWebP
Rozszerzenie nazwy pliku.webp
Typ MIMEobraz/sieć
Ujednolicony identyfikator typuorg.webmproject.webp

Terminologia i podstawy

Słowa kluczowe „MUST”, „MUST NOT”, „REQUIRED”, „SHALL”, „SHALL NOT”, „WOLNE”, „NIE POWINNY”, „NIE ZALECANE”, „MOŻE” i „OPCJONALNIE” należy interpretować w sposób opisany w BCP 14 RFC 2117 RFC 2117, gdy używają wielkich liter zgodnie z opisem w BCP 14 RFC 2117. RFC 8

Plik WebP zawiera albo obraz statyczny (czyli zakodowaną matrycę pikseli), albo animację. Opcjonalnie może zawierać informacje o przezroczystości, profil kolorów i metadane. Nazywamy tę matrycę pikseli płótnem obrazu.

Numeracja bitów w diagramach fragmentów zaczyna się od 0 dla najbardziej znaczącego bitu („MSB 0”), zgodnie z opisem w dokumencie 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 tworzy, – zapisem.
uint16
16-bitowa liczba całkowita bez znaku w systemie little-endian.
uint24
24-bitowa liczba całkowita bez znaku w systemie little-endian.
uint32
32-bitowa liczba całkowita bez znaku, little-endian.
FourCC
Czteroznakowy kod (FourCC) to uint32 utworzony przez złączenie 4 znaków ASCII w porządku little-endian. Oznacza to, że „aaaa” (0x61616161) i „AAAA” (0x41414141) są traktowane jako różne FourCCs.
na podstawie 1,
Pole z niepodpisaną liczbą całkowitą, w którym przechowywane jest wartości przesunięcia o wartość -1. Na przykład takie pole będzie przechowywać wartość 25 jako 24.
ChunkHeader('ABCD')
Używane do opisania nagłówków FourCC i Chunk Size poszczególnych fragmentów, przy czym „ABCD” to wskaźnik FourCC dla danego fragmentu. 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. Składa się z:

 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
4-znakowy kod ASCII używany do identyfikacji fragmentów.
Rozmiar fragmentu: 32 bity (uint32)
Rozmiar fragmentu w bajtach (bez tego pola, identyfikatora fragmentu i wypełniacza).
Dane ładunku w pakiecie: Rozmiar pakietu w bajtach
Ładunek danych. Jeśli Rozmiar fragmentu jest nieparzysty, dodawany jest pojedynczy bajt wypełniający, który MUSI być 0, aby zachować zgodność z RIFF.

Uwaga: w przypadku RIFF obowiązuje zasada, że kody FourCC w całości pisane wielkimi literami są standardowymi elementami, które dotyczą dowolnego formatu pliku RIFF, a kody FourCC specyficzne dla formatu pliku są pisane małymi literami. Format WebP nie stosuje się do 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-bitowy
Znaki ASCII 'W', 'E', 'B', 'P'.

Plik WebP MUSI zaczynać się nagłówkiem RIFF z czterym kodom stałym „WEBP”. Rozmiar pliku w nagłówku to łączny rozmiar kolejnych fragmentów plus 4 bajtów dla kodowania FourCC „WEBP”. Plik NIE powinien zawierać żadnych danych po danych określonych przez Rozmiar pliku. Czytniki MOGĄ analizować takie pliki, ignorując dane końcowe. Ponieważ rozmiar dowolnego fragmentu jest parzysty, również rozmiar podany w nagłówku RIFF również jest taki sam. Treści poszczególnych fragmentów są opisane w następnych sekcjach.

Prosty format pliku (strata)

Tego układu należy używać, jeśli obraz wymaga kodowania stratnego i nie wymaga przezroczystości ani innych zaawansowanych funkcji dostępnych w formacie rozszerzonym. Pliki z tym układem są mniejsze i obsługiwane przez starsze oprogramowanie.

Prosty format pliku WebP (z kompresją stratną):

 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 kodzie FourCC „VP8” to spacja ASCII (0x20).

Specyfikacja formatu bitowego VP8 jest opisana w przewodniku po formacie danych i dekodowaniu VP8. Zwróć uwagę, że nagłówek ramki VP8 zawiera szerokość i wysokość ramki VP8. Zakładamy, że jest to szerokość i wysokość obszaru roboczego.

Specyfikacja VP8 opisuje sposób dekodowania obrazu do formatu Y'CbCr. Aby przekonwertować obraz na RGB, NALEŻY użyć rekomendacji BT.601. Aplikacje MOGĄ używać innej metody konwersji, ale wizualne wyniki mogą się różnić w zależności od dekodera.

Prosty format pliku (bezstratny)

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

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

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
Dane strumienia bitów VP8L.

Aktualną specyfikację bitowego strumienia VP8L można znaleźć na stronie WebP Lossless Bitstream Format. Pamiętaj, że nagłówek VP8L zawiera szerokość i wysokość obrazu VP8L. Zakładamy, że jest to szerokość i wysokość obszaru roboczego.

Rozszerzony format pliku

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

Plik w rozszerzonym formacie zawiera:

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

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

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

  • Dane obrazu.

  • Opcjonalny fragment „EXIF” z metadanymi EXIF.

  • Opcjonalny fragment „XMP” z metadanymi XMP.

  • Opcjonalna lista nieznanych fragmentów.

W przypadku obrazu stałego dane obrazu składają się z pojedynczej klatki, która zawiera:

W przypadku animowanego zdjęcia dane obrazu składają się z wielu klatek. Więcej informacji o ramkach znajdziesz w sekcji Animacja.

Wszystkie fragmenty potrzebne do rekonstrukcji i korekcji kolorów, czyli 'VP8X', 'ICCP', 'ANIM', 'ANMF', 'ALPH', 'VP8 ' i 'VP8L', MUSZĄ pojawiać się w kolejności opisanej wcześniej. Czytniki powinny się nie udać, gdy fragmenty potrzebne do rekonstrukcji i korekty kolorów są nieprawidłowe.

Metadane i nieznane fragmenty MOGĄ pojawić się w niewłaściwej kolejności.

Uzasadnienie: fragmenty potrzebne do odtworzenia powinny pojawiać się w pliku jako pierwsze, aby umożliwić czytnikowi rozpoczęcie dekodowania obrazu przed otrzymaniem wszystkich danych. Aplikacja może korzystać z różnej kolejności metadanych i elementów niestandardowych, aby dostosować je do 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 być 0. Czytelnicy MUSZĄ zignorować to pole.
Profil ICC (I): 1 bit
Ustaw, jeśli plik zawiera fragment „ICCP”.
Alpha (L): 1 bit
Ustaw, jeśli którykolwiek z ramek obrazu zawiera informacje o przezroczystości („alfa”).
Metadane EXIF (E): 1 bit
Zaznacz, jeśli plik zawiera metadane Exif.
Metadane XMP (X): 1 bit
Ustaw, czy plik zawiera metadane XMP.
Animacja (A): 1 bit
Ustaw, czy jest to animowany obraz. Do sterowania animacją należy używać danych w elementach „ANIM” i „ANMF”.
Zarezerwowane (R): 1 bit
MUSI być 0. Czytelnicy MUSZĄ zignorować to pole.
Zarezerwowane: 24 bity
MUSI być 0. Czytelnicy MUSZĄ ignorować to pole.
Szerokość obszaru roboczego minus jeden: 24 bity
Szerokość kanwy w pikselach (liczona od 1). Rzeczywista szerokość płótna to 1 + Canvas Width Minus One.
Wysokość obrazu: 24 bity
Wysokość
liczona od 1 w pikselach. Rzeczywista wysokość obszaru roboczego to 1 + Canvas Height Minus One.

Iloczyn szerokości obrazu i wysokości obrazu MUSI wynosić co najwyżej 2^32 - 1.

W przyszłych specyfikacjach może zostać dodanych więcej pól. Nieznane pola MUSZĄ być ignorowane.

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 w układance w kolejności [niebieski, zielony, czerwony, alfa]. Ten kolor MOŻE być użyty do wypełnienia niewykorzystanego miejsca na kanwie wokół klatek oraz przezroczystych pikseli pierwszej klatki. Kolor tła jest też używany, gdy metoda usuwania jest 1.

Uwagi:

  • Kolor tła MOŻE zawierać nieprzezroczystą wartość alfa, nawet jeśli flaga Alpha w kawałku VP8X nie jest ustawiona.

  • Aplikacje wyświetlające OBRAZ MOGĄ traktować wartość koloru tła jako podpowiedź, ale nie muszą jej używać.

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

Liczba iteracji pętli: 16 bitów (uint16)
Liczba zapętleń animacji. Jeśli ma wartość 0, oznacza to, że bez końca.

Ten fragment MUSI się pojawić, jeśli w fragmentach „VP8X” jest ustawiona flaga Animation. Jeśli flaga Animacja nie jest ustawiona, a ten fragment jest obecny, należy go zignorować.

Blok danych „ANMF”:

W przypadku animowanych obrazów ten fragment zawiera informacje o pojedynczym klatce. Jeśli flaga animacji nie jest ustawiona, ten fragment NIE POWINIEN się pojawiać.

 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)
Szerokość lewego górnego rogu kadru to Frame X * 2.
Ramka Y: 24 bity (uint24)
Pionowa współrzędna lewego górnego rogu kadru to Frame Y * 2.
Szerokość ramki minus 1: 24 bity (uint24)
Szerokość z liczbnikiem 1 klatki. Szerokość ramki wynosi 1 + Frame Width Minus One.
Wysokość ramki minus jeden: 24 bity (uint24)
Wysokość ramki (w wersji 1). Wysokość klatki to 1 + Frame Height Minus One.
Czas trwania klatki: 24 bity (uint24)
Czas oczekiwania przed wyświetleniem następnej klatki w jednostkach 1 milisekundy. Pamiętaj, że interpretacja wartości 0 (i często <= 10) w przypadku Duration (Czas trwania) jest zdefiniowana przez implementację. Wiele narzędzi i przeglądarek przypisuje minimalny czas trwania podobny do GIF.
Zarezerwowane: 6 bitów
MUSI być 0. Czytelnicy MUSZĄ zignorować to pole.
Metoda mieszania (B): 1 bit

Wskazuje, jak przezroczyste piksele bieżącej ramki mają zostać zmieszane z odpowiednimi pikselami poprzedniego obszaru roboczego:

  • 0: użyj mieszania alfa. Po usunięciu poprzedniego obrazu zrenderuj bieżący obraz na płótnie za pomocą mieszania alfa (patrz poniżej). Jeśli bieżąca ramka nie ma kanału alfa, przyjmuje się, że jego wartość to 255, co powoduje zastąpienie prostokąta.

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

Metoda utylizacji (D): 1 bit

Wskazuje, jak ma być traktowana bieżąca klatka po wyświetleniu (przed wyrenderowaniem następnej klatki) na płótnie:

  • 0: nie wyrzucać. Pozostaw obszar roboczy bez zmian.

  • 1: Dispose to the background color. Wypełnij prostokąt obszaru roboczego pokrytego bieżącą klatką kolorem tła określonym we fragmencie ANIM.

Uwagi:

  • Usuwanie klatki ma zastosowanie tylko do prostokąta klatki, czyli prostokąta zdefiniowanego przez wartości X klatki, Y klatki, szerokość klatki i wysokość klatki. Może ono obejmować cały obszar roboczy, ale nie musi.

  • Mieszanie alfa:

    Biorąc pod uwagę, że każdy z kanałów R, G, B i A jest 8-bitowy, a kanały RGB nie są wstępnie mnożone przez kanał 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 wykonać w przestrzeni barw liniowych, biorąc pod uwagę profil kolorów obrazu. Jeśli profil kolorów jest nieobecny, przyjmuje się standard RGB (sRGB). (Pamiętaj, że przestrzeń sRGB również musi zostać zlinearyzowana ze względu na wartość krzywej gamma wynoszącą około 2,2).

Dane ramki: Rozmiar fragmentu w bajtach – 16

Składa się z:

Uwaga: ładunek 'ANMF', dane ramki, składa się z pojedynczych wypeł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 być 0. Czytelnicy MUSZĄ zignorować to pole.
Wstępne przetwarzanie (P): 2 bity

Te informacyjne bity służą do sygnalizowania wstępnej obróbki, która została wykonana podczas kompresji. Na podstawie tych informacji dekoder może np. zróżnicować wartości lub wygładzić gradienty przed wyświetleniem.

  • 0: brak wstępnej obróbki.
  • 1: obniżenie poziomu.

Dekoder nie musi używać tych informacji w żaden określony sposób.

Metoda filtrowania (F): 2 bity

Zastosowane metody filtrowania:

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

W przypadku każdego piksela filtr wykonuje się według poniższych obliczeń. Załóżmy, że wartości alfa wokół bieżącej pozycji X są oznaczone jako:

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

Chcemy obliczyć wartość alfa w pozycji X. Najpierw tworzona jest prognoza w zależności od metody filtrowania:

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

gdzie clip(v) jest równe:

  • 0 jeśli v < 0,
  • 255, jeśli v > 255, lub
  • v w innym przypadku

Ostateczna wartość jest uzyskiwana przez dodanie odkodowanej wartości X do predyktora i zastosowanie arytmetyki modulo 256 w celu zawężenia zakresu [256..511] do [0..255]:

alpha = (predictor + X) % 256

Szczególnie zdarza się, że piksel znajduje się skrajnie od lewej lub od góry. Na przykład wartość w lewym górnym rogu w miejscu (0, 0) używa 0 jako wartości predyktora. W innym przypadku:

  • W przypadku metod filtrowania w poziomie lub gradientu piksele znajdujące się skrajnie po lewej stronie w lokalizacji (0, y) są przewidywane na podstawie lokalizacji (0, y–1) znajdującej się tuż powyżej.
  • W przypadku metod filtrowania pionowego lub gradientowego najwyższe piksele w danej lokalizacji (x, 0) są przewidywane na podstawie lokalizacji (x-1, 0) po lewej stronie.
Metoda kompresji (C): 2 bity

Używana metoda kompresji:

  • 0: brak kompresji.
  • 1: skompresowany w bezstratnym formacie WebP.
Strumień bitów alfa: Rozmiar fragmentu w bajtach – 1

zakodowany bitstream alfa;

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

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

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

  • Dane nieprzetworzone: składa się z sekwencji bajtów o długości = szerokość * wysokość, zawierającej wszystkie 8-bitowe wartości przezroczystości w kolejności skanowania.

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

    Uzasadnienie: wymiary są już znane z innych źródeł, więc ich ponowne przechowywanie byłoby zbędne i mogłoby powodować błędy.

    Po dekodowaniu strumienia obrazu na wartości kolorów alfa, czerwony, zielony i niebieski (ARGB) zgodnie z procesem opisanym w specyfikacji formatu bezstratnego informacje o przezroczystości należy wyodrębnić z kanału zielonego kwadrupletu ARGB.

    Uzasadnienie: kanał zielony dopuszcza dodatkowe etapy przekształcenia w specyfikacji – w przeciwieństwie do pozostałych kanałów – które mogą poprawić kompresję.

Bitstream (VP8/VP8L)

Ten fragment zawiera skompresowane dane strumienia bitowego dla pojedynczej klatki.

Fragment bitstream może być (i) fragmentem „VP8” zawierającym ciąg „VP8” (zwróć uwagę na znaczącą spację w czwartym znaku) jako jego FourCC lub (ii) fragmentem „VP8L”, używając „VP8L” jako jego FourCC.

Formaty fragmentów „VP8” i „VP8L” są opisane odpowiednio w sekcjach Format pliku prosty (stratny) i Format pliku prosty (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.

Powinien być tylko jeden taki fragment. Jeśli jest więcej takich fragmentów, czytniki mogą zignorować wszystkie oprócz pierwszego. Szczegółowe informacje znajdziesz w specyfikacji ICC.

Jeśli ten fragment jest nieobecny, NALEŻY przyjąć, że jest to przestrzeń sRGB.

Metadane

Metadane mogą być przechowywane w elementach „EXIF” lub „XMP”.

Powinien być tylko jeden fragment każdego typu (EXIF i XMP). Jeśli jest ich więcej, czytniki mogą zignorować wszystkie oprócz 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 (w bajtach)
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 w bajtach
Metadane obrazu w formacie XMP.

Pamiętaj, że czwarty znak w linijce „XMP ” FourCC jest spacją ASCII (0x20).

Dodatkowe wskazówki dotyczące obsługi metadanych można znaleźć w dokumencie „Guidelines for Processing Metadata” (Wytyczne dotyczące obsługi metadanych) w grupie roboczej ds. metadanych.

Nieznane fragmenty

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

Uzasadnienie: zezwolenie na nieznane fragmenty zapewnia możliwość rozszerzenia formatu w przyszłości i przechowywanie dowolnych danych związanych z aplikacją.

Plik MOŻE zawierać nieznane fragmenty:

Czytelnicy powinni je zignorować. Autorzy powinni zachować je w pierwotnym porządku (chyba że zamierzają zmodyfikować te fragmenty).

Montaż w Canvas z ramek

Poniżej przedstawiamy, jak użytkownik MUSI złożyć płótno w przypadku animowanego obrazu.

Proces rozpoczyna się od utworzenia obrazu na płótnie o wymiarach podanych w bloku danych 'VP8X': Canvas Width Minus One + 1 pikseli szerokości i Canvas Height Minus One + 1 pikseli wysokości. Pole Loop Count z fragmentu „ANIM” określa liczbę powtórzeń procesu animacji. Jest to Loop Count - 1 w przypadku wartości innych niż zero Loop Count lub nieskończoność, jeśli Loop Count jest równa zero.

Na początku każdej iteracji pętli kanwa jest wypełniana za pomocą koloru tła z elementu „ANIM” lub koloru zdefiniowanego przez aplikację.

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

Renderowanie zdekodowanej klatki rozpoczyna się od współrzędnych kartezjańskich (2 * Frame X, 2 * Frame Y), a punktem początkowym jest lewy górny róg obszaru roboczego. Szerokość Frame Width Minus One + 1 piks. i wysokość Frame Height Minus One + 1 piks. są renderowane w obszarze roboczym za pomocą Blending method.

Obszar roboczy jest wyświetlany przez Frame Duration ms. Ten proces będzie trwać, dopóki nie zostaną wyświetlone wszystkie ramki z elementów „ANMF”. Rozpoczyna się wtedy nowa iteracja pętli lub obszar roboczy pozostaje w stanie końcowym, jeśli wszystkie iteracje zostały ukończone.

Proces renderowania przedstawia pseudokod. Notacja VP8X.field oznacza pole w fragmentie „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 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

Przykładowe układy plików

Obraz zakodowany z utratą jakości z kanałem alfa może wyglądać tak:

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

Obraz zakodowany bezstratnie może wyglądać tak:

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

Bezstratny obraz 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)