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 kontenera | WebP |
Rozszerzenie nazwy pliku | .webp |
Typ MIME | obraz/webp |
Jednolity identyfikator typu | org.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:
Opcjonalny podfragment alfa.
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 fragmentu –
16
B Elementy składowe:
Opcjonalna podfragment alfa ramki.
Podfragment strumienia bitów klatki.
Opcjonalna lista nieznanych fragmentów.
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 fragmentu –
1
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:
- na końcu pliku, jak opisano w sekcji Rozszerzony nagłówek pliku WebP, lub
- na końcu fragmentów „ANMF”, zgodnie z opisem w sekcji Animacja.
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)