Wprowadzenie
WebP to format obrazu wykorzystujący (i) kodowanie klatki klucza VP8 do kompresować dane obrazów w sposób stratny lub (ii) za pomocą bezstratnego kodowania WebP. Te schematy kodowania powinny sprawić, że będzie wydajniejszy niż starsze formaty, takie jak JPEG GIF i PNG. Jest ona zoptymalizowana pod kątem szybkiego przesyłania obrazów przez sieć (np. do witryn internetowych). Format WebP charakteryzuje się parzystością cech (profil kolorów, metadanych, animacji itp.) oraz innymi formatami. Ten dokument opisuje określa strukturę pliku WebP.
Kontener WebP (czyli kontener RIFF dla WebP) umożliwia obsługę funkcji wykraczającą poza podstawowy przypadek użycia WebP (czyli plik zawierający pojedynczy obraz zakodowany jako kluczowy obraz VP8). Kontener WebP zapewnia dodatkową obsługę:
Kompresja bezstratna: obraz można kompresować bezstratnie za pomocą Format bezstratny WebP.
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ć osadzony profil ICC zgodnie z opisem przez International Color Consortium.
Animacja: obraz może mieć wiele klatek z przerwami między nimi, w animację.
Nazwa
Zalecamy używanie tych typów w odniesieniu do kontenera WebP:
Nazwa formatu kontenera | WebP |
Rozszerzenie nazwy pliku | .webp |
Typ MIME | obraz/sieć |
Ujednolicony identyfikator typu | org.webmproject.webp |
Terminologia i podstawy
Słowa kluczowe „MUST” (NALEŻY), „MUST NOT” (NIE NALEŻY), „REQUIRED” (WYMAGANE), „SHALL” (NALEŻY), „SHALL NOT” (NIE NALEŻY), „SHOULD” (NALEŻY), „SHOULD NOT” (NIE NALEŻY), „RECOMMENDED” (ZALECANE), „NOT RECOMMENDED” (NIE ZALECANE), „MAY” (MOŻNA) i „OPTIONAL” (OPCJONALNE) w tym dokumencie należy interpretować zgodnie z dokumentem BCP 14 RFC 2119 RFC 8174, gdy tylko występują w wersji z dużymi literami, jak pokazano tutaj.
Plik WebP zawiera nieruchomy obraz (zakodowaną macierz pikseli). lub animację. Opcjonalnie może też zawierać przezroczystość. informacje, profil kolorów i metadane. Nazywamy tę matrycę pikseli płótnem obrazu.
Numerowanie bitów na diagramach fragmentów rozpoczyna się od 0
dla najbardziej istotnego bitu
(„MSB 0”), zgodnie z opisem w RFC 1166.
Poniżej przedstawiono dodatkowe terminy używane w niniejszym dokumencie:
- Tylko do odczytu
- Kod, który odczytuje pliki WebP, jest nazywany czytnikiem, a kod, który je zapisuje, jest nazywany pisarzem.
- uint16
- 16-bitowa liczba całkowita bez znaku w systemie little-endian.
- uint24
- 24-bitowa liczba całkowita bez znaku.
- uint32
- 32-bitowa liczba całkowita bez znaku w postaci little-endian.
- FourCC
- Czteroznakowy kod (FourCC) to ciąg uint32 utworzony przez połączenie czterech znaków Znaki ASCII w kolejności little-endian. To znaczy „aaaa”. (0x61616161) i „AAAA” (0x41414141) są traktowane jako różne FourCCs.
- oparty na 1
- Pole liczby całkowitej bez znaku, które przechowuje wartości przesunięte o
-1
. Na przykład takie pole przechowuje wartość 25 jako 24. - ChunkHeader('ABCD')
- Używane do opisania nagłówka FourCC i Chunk Size (Rozmiar fragmentu) poszczególnych fragmentów, gdzie „ABCD” to FourCC dla fragmentu. Rozmiar tego elementu to 8 bajtów.
Format pliku RIFF
Format pliku WebP jest oparty na 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 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Chunk FourCC: 32 bity
- 4-znakowy kod ASCII używany do identyfikacji fragmentów.
- Rozmiar fragmentu: 32 bity (uint32)
- Rozmiar fragmentu w bajtach bez uwzględnienia tego pola (fragmentu). identyfikatora lub dopełnienia.
- Ładunek fragmentu: rozmiar fragmentu w bajtach
- Dane. Jeśli Rozmiar fragmentu jest nieparzysty, pojedynczy bajt dopełnienia, który MUSI
wynosi
0
, aby dostosować ją do RIFF – został dodany.
Uwaga: w przypadku RIFF obowiązuje zasada, że kody FourCC w przypadku bloków są standardowymi kodami, które dotyczą dowolnego formatu pliku RIFF, a kody FourCC specyficzne dla formatu pliku są w całości 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, począwszy od przesunięcia 8. Maksymalna wartość tego pola to 2^32 minus 10 bajtów, a więc rozmiar całego pliku to maksymalnie 4 GiB minus 2 bajty.
- „WEBP”: 32 bity
- Znaki ASCII: „W”, „E”, „B” i „P”.
Plik WebP MUSI zaczynać się od nagłówka RIFF z nagłówkiem „WEBP” FourCC. Rozmiar pliku
w nagłówku to łączny rozmiar kolejnych fragmentów plus 4
bajtów dla
„WEBP” FourCC. 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, rozmiar podany w nagłówku RIFF jest również parzysty. Treść poszczególnych fragmentów jest opisana w następnych sekcjach.
Prosty format pliku (z kompresją stratną)
Tego układu NALEŻY użyć, jeśli obraz wymaga kodowania stratnego i nie wymagają przejrzystości lub innych zaawansowanych funkcji udostępnianych przez format rozszerzony. 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)
- Dane strumienia bitów 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. Pamiętaj, że nagłówek ramki VP8 zawiera szerokość i wysokość tej ramki. Zakłada się, że jest to szerokość i wysokość płótna.
Specyfikacja VP8 opisuje sposób dekodowania obrazu do formatu Y'CbCr. Aby przekonwertować 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 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Blok danych '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 bitowego VP8L.
Aktualną specyfikację strumienia bitowego VP8L można znaleźć na stronie Bezstratny format transmisji bitów WebP. Pamiętaj, że nagłówek VP8L zawiera szerokość i wysokość obrazu VP8L. Zakłada się, że jest to szerokość i wysokość płótna.
Rozszerzony format pliku
Uwaga: starsze wersje czytników mogą nie obsługiwać plików w formacie rozszerzonym.
Plik w rozszerzonym formacie 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 sterowania animacją.
Dane obrazu.
Opcjonalny plik „EXIF” Fragment z metadanymi Exif.
Opcjonalny fragment „XMP” z metadanymi XMP.
Opcjonalna lista nieznanych fragmentów.
W przypadku zdjęcia dane zdjęcia składają się z pojedynczej klatki, do:
Opcjonalny podfragment alfa.
W przypadku animowanego zdjęcia dane obrazu składają się z wielu klatek. Więcej szczegółowe informacje o klatkach można znaleźć w sekcji Animacje.
Wszystkie fragmenty niezbędne do rekonstrukcji i korekcji kolorów, czyli „VP8X”, „ICCP”, „ANIM”, „ANMF”, „ALPH”, „VP8” i „VP8L” MUSZĄ pojawić się w kolejności omówiono to wcześniej. Czytelnicy POWINNY BYĆ, gdy fragmenty są niezbędne do odbudowy i korekcja kolorów.
Metadane i nieznane fragmenty mogą być wyświetlane w nieporządku.
Uzasadnienie: fragmenty niezbędne do rekonstrukcji powinny pojawić się na początku który umożliwia czytelnikowi rozpoczęcie dekodowania obrazu przed otrzymaniem wszystkich dane. Aplikacja może korzystać z różnej kolejności metadanych i kawałków niestandardowych, aby dostosować implementację.
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 być
0
. Czytelnicy MUSZĄ ignorować to pole. - Profil ICC (I): 1 bit
- Ustaw, czy plik zawiera fragment „ICCP”.
- Alpha (L): 1 bit
- Ustaw, czy którakolwiek z klatek obrazu zawiera informacje 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, jeśli jest to obraz animowany. Dane w pliku „ANIM” i „ANMF” Fragmenty powinny być do sterowania animacją.
- Zarezerwowane (R): 1 bit
- MUSI być
0
. Czytelnicy MUSZĄ ignorować to pole. - Zarezerwowana: 24 bity
- MUSI być
0
. Czytelnicy MUSZĄ zignorować to pole. - Szerokość obrazu pomniejszona o 1: 24 bity
- Szerokość
- wyrażona w 1 w pikselach. Rzeczywista szerokość płótna to
1 + Canvas Width Minus One
. - wyrażona w 1 w pikselach. Rzeczywista szerokość płótna to
- Wysokość obszaru roboczego minus One: 24 bity
- Wysokość
- liczona od 1 w pikselach. Rzeczywista wysokość płótna to
1 + Canvas Height Minus One
. - liczona od 1 w pikselach. Rzeczywista wysokość płótna to
Iloczyn szerokości i wysokości musi być mniejszy niż 2^32 - 1
.
W przyszłych specyfikacjach może zostać dodanych więcej pól. Nieznane pola MUSZĄ być ignorowane.
Animacja
Animacją zarządza „ANIM” i „ANMF” Kawałki.
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 używany również, gdy metoda utylizacji to
1
.
Uwagi:
Kolor tła MOŻE zawierać nieprzezroczystą wartość alfa, nawet jeśli Flaga alfa w VP8X Fragment nie jest ustawiony.
Aplikacje przeglądające POWINNY traktować wartość koloru tła jako wskazówkę nie są wymagane.
Na początku każdej pętli płótno jest czyszczone. Do tego celu MOŻNA użyć koloru tła.
- Liczba pętli: 16 bitów (uint16)
- Liczba zapętleń animacji. Jeśli to
0
, oznacza to, że bez końca.
Ten fragment MUSI być widoczny, jeśli w „VP8X” flaga Animacja Fragment został ustawiony. Jeśli flaga Animacja nie jest ustawiona, a ten fragment jest obecny, MUSI być zignorowano.
„ANMF” Fragment:
W przypadku animowanych obrazów ten fragment zawiera informacje o pojedynczym klatce. Jeśli flaga animacji nie jest ustawiona, ten fragment NIE POWINNO być obecny.
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)
- Pionowa współrzędna lewego górnego rogu kadru to
Frame Y * 2
. - Szerokość ramki minus jeden: 24 bity (uint24)
- Szerokość z liczbnikiem 1 klatki.
Szerokość ramki to
1 + Frame Width Minus One
. - Wysokość ramki minus 1: 24 bity (uint24)
- Wysokość klatki, obliczana na podstawie 1.
Wysokość klatki to
1 + Frame Height Minus One
. - Czas trwania ramki: 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
Określa sposób mieszania przezroczystych pikseli bieżącego kadru z odpowiednimi pikselami poprzedniego obrazu:
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, załóżmy, że wartość alfa wynosi 255, skutecznie zastępując prostokąt.1
: nie mieszaj. Po usunięciu poprzedniej klatki wyrenderuj tag bieżącej ramki na obszarze roboczym przez zastąpienie prostokąta pokrytego w bieżącej ramce.
- Metoda utylizacji (D): 1 bit
Wskazuje, jak ma być traktowana bieżąca klatka po jej wyświetleniu. wyświetlone (przed wyrenderowaniem następnej klatki) w obszarze roboczym:
0
: nie wyrzucać. Pozostaw obszar roboczy bez zmian.1
: Dispose to the background color. Wypełnij prostokąt na obszarze roboczym. jest zasłonięta bieżącą klatką, której kolor tła jest określony w tagu „ANIM” Kawałek.
Uwagi:
Usuwanie ramki ma zastosowanie tylko do prostokąta ramki, czyli prostokąt zdefiniowany przez wymiary klatka X, klatka Y, szerokość ramki i ramka wysokość. Może, ale nie musi, zajmować całą powierzchnię płótna.
Mieszanie alfa:
Biorąc pod uwagę, że każdy kanał R, G, B i A jest 8-bitowy, a kanał RGB kanały nie są wstępnie mnożone przez kanał alfa, czyli wzór mieszania „dst” na „src” to:
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 POWINNY być przeprowadzane w liniowej przestrzeni kolorów, 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:
Opcjonalny fragment alfa dla ramki.
Podfragment strumienia bitów dla klatki.
Opcjonalna lista nieznanych fragmentów.
Uwaga: plik „ANMF” ładunek, Frame Data, składa się z osobnych dodane fragmenty 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 być
0
. Czytelnicy MUSZĄ zignorować to pole. - Przetwarzanie wstępne (P): 2 bity
Te informacyjne bity są używane do sygnalizowania wstępnego przetwarzania danych, które podczas kompresji. Dekoder może używać tych informacji do takich działań, jak np. ditherowanie wartości lub wygładzanie gradientów przed wyświetleniem.
0
: bez wstępnego przetwarzania.1
: obniżenie poziomu.
Dekodery nie muszą używać tych informacji w żaden 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 filtrowanie jest wykonywane za pomocą tych obliczeń.
Załóżmy, że wartości alfa wokół bieżącej pozycji X
są oznaczone jako:
C | B |
---+---+
A | X |
Staramy się obliczyć wartość alfa dla pozycji X
. Najpierw tworzona jest prognoza w zależności od metody filtrowania:
- Metoda
0
: predictor = 0 - Metoda
1
: prognoza = A - Metoda
2
: prognoza = 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
- W przeciwnym razie
Ostateczna wartość jest uzyskiwana przez dodanie do predyktora wartości dekompresji X
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 poziomego lub gradientowego piksele po lewej stronie w jest prognozowana lokalizacja (0, y) na podstawie lokalizacji (0, y-1) tuż powyżej.
- W przypadku metod filtrowania pionowego lub gradientowego najwyższe piksele w miejscu (x, 0) są przewidywane na podstawie położenia (x-1, 0) po lewej stronie.
- Metoda kompresji (C): 2 bity
Zastosowana metoda kompresji:
0
: bez kompresji.1
: skompresowany w formacie bezstratnym WebP.
- Strumień bitów alfa: Rozmiar fragmentu w bajtach –
1
Zakodowany strumień bitowy w wersji alfa.
Ten opcjonalny fragment zawiera zakodowane dane alfa dla tego klatki. Ramka zawiera ciąg „VP8L” Fragment NIE POWINIEN zawierać tego fragmentu.
Uzasadnienie: informacje o przejrzystości są już uwzględnione w „VP8L”. Kawałek.
Dane kanału alfa są przechowywane jako nieskompresowane nieprzetworzone dane (gdy metoda kompresji „0”) lub skompresowana przy użyciu formatu bezstratnego (gdy metoda kompresji ma wartość „1”).
Nieprzetworzone dane: składają się z sekwencji bajtów o długości = szerokość * wysokość, zawierający 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ł, dlatego ich ponowne przechowywanie byłoby zbędne i zwiększyło się ryzyko błędów.
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: specyfikacja pozwala na dodatkowe przekształcenia kanału zielonego (w odróżnieniu od innych kanałów), które mogą poprawić kompresję.
Strumień bitów (VP8/VP8L)
Ten fragment zawiera skompresowane dane bitowe dotyczące pojedynczego klatki.
Fragment bitowego strumienia może być (i) fragmentem „VP8”, który używa „VP8” (zwróć uwagę na istotną czwartą pozycję) jako kodu FourCC, lub (ii) fragmentem „VP8L”, który używa „VP8L” jako kodu 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 nie jest dostępny, należy założyć sRGB.
Metadane
Metadane mogą być przechowywane w elementach „EXIF” lub „XMP”.
Może istnieć tylko jeden fragment każdego typu („EXIF” i „XMP ”). Jeśli tam więcej takich fragmentów, czytelnicy MOGĄ zignorować wszystkie z wyjątkiem pierwszego.
Fragmenty są zdefiniowane w ten sposób:
Fragment danych 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 polu „XMP ” FourCC jest spacją ASCII (0x20).
Dodatkowe wskazówki dotyczące obsługi metadanych znajdziesz w wytycznych dotyczących obsługi metadanych przygotowanych przez grupę roboczą ds. metadanych.
Nieznane fragmenty
Element RIFF (opisany w sekcji Format pliku RIFF), którego kod FourCC różni się od dowolnego z elementów opisanych w tym dokumencie, jest uważany za nieznany element.
Uzasadnienie: zezwolenie na nieznane fragmenty umożliwia rozszerzenie formatu w przyszłości i zapisywanie dowolnych danych dotyczących aplikacji.
Plik MOŻE zawierać nieznane fragmenty:
- na końcu pliku, zgodnie z opisem w sekcji Rozszerzony nagłówek pliku WebP, lub
- na końcu „ANMF” Fragmenty, zgodnie z opisem w Animacja.
Czytelnicy powinni ignorować te fragmenty. Autorzy powinni zachować je w pierwotnym porządku (chyba że zamierzają zmodyfikować te fragmenty).
Montaż odbitek na płótnie z ramek
Tutaj dowiesz się, jak czytelnik MUSI złożyć odbitkę na płótnie w takim 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
w bloku „ANIM” określa, ile razy ma być powtarzany proces animacji. To jest Loop Count - 1
dla
niezerowe wartości Loop Count
lub nieskończona, jeśli Loop Count
wynosi 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ę.
„ANMF” Fragmenty zawierają pojedyncze klatki podane w kolejności wyświetlania. Przed wyrenderowaniem
w przypadku każdej klatki stosowany jest atrybut Disposal method
poprzedniej klatki.
Renderowanie odkodowanego kadru rozpoczyna się od współrzędnych kartezjańskich (2 *
Frame X
, 2 * Frame Y
), przy czym za początek układu współrzędnych przyjmuje się lewy górny róg kanwy.
Frame Width Minus One + 1
pikseli szerokości i Frame Height Minus One + 1
pikseli wysokości są renderowane na płótnie za pomocą Blending method
.
Obszar roboczy jest wyświetlany przez Frame Duration
ms. Proces ten trwa do
wszystkie klatki podane przez „ANMF” Fragmenty zostały wyświetlone. Nowa iteracja w pętli to
lub obszar roboczy pozostaje w stanie końcowym, jeśli wszystkie iteracje zostały
.
Poniższy pseudokod ilustruje proces renderowania. Zapis VP8X.field oznacza pole w ciągu „VP8X” Fragment z tym samym opisem.
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)