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 być wydajniejsze niż starsze formaty, takie jak JPEG, GIF i PNG. Jest zoptymalizowany pod kątem szybkiego przesyłania obrazu przez sieć (na np. witryn). Format WebP ma te same funkcje (profil kolorów, metadane, animacja itp.) co inne formaty. Ten dokument opisuje określa strukturę pliku WebP.
Kontener WebP (czyli kontener RIFF dla WebP) umożliwia obsługę funkcji ponad podstawowy przypadek użycia WebP (czyli plik zawierający obraz zakodowany jako ramka klucza VP8). Kontener WebP zapewnia dodatkową obsługę:
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ć 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
W odniesieniu do WebP zalecamy korzystanie z następujących typów container:
Nazwa formatu kontenera | WebP |
Rozszerzenie nazwy pliku | .webp |
MIME-type | image/webp |
Jednolity identyfikator typu | org.webmproject.webp |
Terminologia Podstawy
słowa kluczowe „MUSISZ”, „NIE MOŻE”, „WYMAGANE”, „MUSZĄ”, „NIE POWINNY”, „POWINNO”, „NIE POWINNO”, „ZALECANE”, „NIEZALECANA”, „MOŻE” i „OPCJONALNIE” tego procesu dokument należy interpretować zgodnie z opisem w BCP 14 RFC 2119 RFC 8174. kiedy i tylko gdy są pisane wielkimi literami, jak pokazano tutaj.
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. Macierz pikseli nazywamy płótno 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 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 uint32 utworzony przez złączenie 4 znaków ASCII w porządku little-endian. To znaczy „aaaa”. (0x61616161) i „AAAA” (0x41414141) są traktowane jako różne FourCCs.
- na podstawie 1,
- Pole liczby całkowitej bez znaku przechowujące wartości przesunięte o
-1
, na przykład takie pole przechowuje wartość 25 jako 24. - ChunkHeader('ABCD')
- Używane do opisania nagłówków 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. Oto 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 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 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.
- Dane 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 przypadku bloków są standardowymi kodami bloków, które dotyczą dowolnego formatu pliku RIFF, a kody FourCC specyficzne dla formatu pliku są w całości małymi literami. WebP nie przestrzega tej konwencji.
Nagłówek pliku WebP
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'R' | 'I' | 'F' | 'F' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| File Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'W' | 'E' | 'B' | 'P' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 'RIFF': 32 bity
- Znaki ASCII 'R', 'I', 'F', 'F'.
- Rozmiar pliku: 32 bity (uint32)
- Rozmiar pliku w bajtach, 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-bitowy
- 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. Czytelnicy MOGĄ przeanalizować takie pliki, ignorując zakończenie
i skalowalnych danych. 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 (strata)
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 są obsługiwane przez starsze oprogramowanie.
Prosty format pliku (stratny): 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 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
„VP8” Fragment:
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 bitowego VP8.
Pamiętaj, że czwarty znak w polu „VP8 ” FourCC jest spacją ASCII (0x20).
Specyfikacja formatu strumienia bitowego VP8 została opisana w sekcji Format danych VP8 i Przewodnik po dekodowaniu. 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, jak zdekodować obraz do formatu Y'CbCr. Aby przekonwertować obraz na RGB, NALEŻY użyć rekomendacji BT.601. Zgłoszenia – MAJ innej metody konwersji, ale wyniki wizualne mogą się różnić w zależności od dekoderów.
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 (bezstratny) 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) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: '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)
- Strumieniowe przesyłanie danych 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ść 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:
„VP8X” Fragment z informacjami o funkcjach używanych w pliku.
Opcjonalny fragment „ICCP” z profilem kolorów.
Opcjonalny tag „ANIM” Fragment z danymi kontrolnymi animacji.
Dane obrazu.
Opcjonalny plik „EXIF” Fragment z metadanymi Exif.
Opcjonalny „XMP ” Fragment z metadanymi XMP.
Opcjonalna lista nieznanych fragmentów.
W przypadku zdjęcia dane zdjęcia składają się z pojedynczej klatki, do:
Opcjonalny fragment alfa.
W przypadku animowanego obrazu 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. Czytniki powinny się nie udać, gdy fragmenty potrzebne do rekonstrukcji i korekty kolorów są nieprawidłowe.
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 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, 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.
- Ustaw, 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”.
- Zarezerwowana (R): 1 bit
- MUSI być
0
. Czytelnicy MUSZĄ zignorować to pole. - Zarezerwowane: 24 bity
- MUSI być
0
. Czytelnicy MUSZĄ zignorować to pole. - Szerokość obszaru roboczego minus jeden: 24 bity
- Szerokość od 1 do obszaru roboczego w pikselach.
Rzeczywista szerokość płótna to
1 + Canvas Width Minus One
. - Wysokość obrazu: 24 bity
- Od 1 do wysokości obszaru roboczego 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łości możemy dodać więcej pól. Nieznane pola MUSZĄ być ignorowane.
Animacja
Animacją zarządza „ANIM” i „ANMF” Kawałki.
Blok danych „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żywany do wypełnienia nieużywanego miejsca na płótnie
wokół ramek, a także przezroczyste piksele pierwszej klatki.
Kolor tła jest też używany, gdy metoda usuwania jest
1
.
Uwaga:
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 pętli: 16 bitów (uint16)
- Liczba zapętleń animacji. Jeśli jest to
0
, oznacza to 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 pojedynczej 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)
- 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ść klatki, obliczana od 1.
Szerokość ramki wynosi
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 Frame Duration 0 (i często <= 10) jest więc jest definiowana przez implementację. Wiele narzędzi i przeglądarek przypisuje minimalny czas trwania podobny do GIF.
- Zarezerwowane: 6 bitów
- MUSI być
0
. Czytelnicy MUSZĄ ignorować to pole. - Metoda łączenia (B): 1 bit
Wskazuje, jak mają być łączone przezroczyste piksele bieżącej ramki z odpowiednimi pikselami poprzedniego kanału:
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 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 wyrzucaj. Pozostaw obszar roboczy bez zmian.1
: wybierz kolor tła. Wypełnij prostokąt na kanwie, który jest pokryty przez bieżący kadr, kolorem tła określonym w elementzie 'ANIM'.
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 ono obejmować cały obszar roboczy, ale nie musi.
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 NALEŻY wykonać w przestrzeni barw liniowych, biorąc pod uwagę profil kolorów obrazu. Jeśli profil kolorów to nie ma, należy przyjąć standardową paletę RGB (sRGB). (Pamiętaj, że sRGB też musi być linearna z powodu gamma około 2,2).
- Dane ramki: Rozmiar fragmentu w bajtach –
16
Składa się z:
Opcjonalny podelement alfa dla ramki.
Podfragment strumienia bitów dla klatki.
Opcjonalna lista nieznanych fragmentów.
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Ą ignorować to pole. - Wstępne przetwarzanie (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. rozpraszanie wartości lub wygładzanie gradientów przed wyświetleniem.
0
: bez wstępnego przetwarzania.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 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 |
Chcemy obliczyć wartość alfa w pozycji X
. Po pierwsze:
w zależności od metody filtrowania:
- Metoda
0
: predictor = 0 - Metoda
1
: prognoza = 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
- W przeciwnym razie
Ostateczną wartość uzyskuje się przez dodanie wartości zdekompresowanej X
do
prognozy i użycie arytmetyki modulo-256 do obcięcia 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. Dla: na przykład wartość w lewym górnym rogu lokalizacji (0, 0) używa 0 jako wartości prognozy. W innym przypadku:
- W przypadku metod filtrowania poziomego lub gradientowego piksele po lewej stronie w miejscu (0, y) są przewidywane na podstawie miejsca (0, y-1) tuż powyżej.
- W przypadku metod filtrowania pionowego lub gradientowego najwyższy piksel w lokalizacja (x, 0) jest prognozowana na podstawie lokalizacji (x-1, 0) po lewej stronie.
- Metoda kompresji (C): 2 bity
Używana metoda kompresji:
0
: brak 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 tej ramki. 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 dane nieprzetworzone (gdy metoda kompresji to „0”) lub skompresowane w formacie bezstratnym (gdy metoda kompresji to „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 image-stream 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 kroki przetwarzania w przypadku zielonego kanału (w odróżnieniu od innych kanałów), co może poprawić kompresję.
Strumień bitów (VP8/VP8L)
Ten fragment zawiera skompresowane dane strumienia bitowego dla pojedynczej 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ą takie, jak 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 pliku „EXIF” lub „XMP ” Kawałki.
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 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.
„XMP” Fragment:
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 na temat obsługi metadanych znajdziesz w „Wytyczne dotyczące obsługi metadanych” w grupie roboczej ds. metadanych.
Nieznane fragmenty
Fragment RIFF (opisany w sekcji Format pliku RIFF) którego FourCC różni się od któregokolwiek z fragmentów opisanych w tym dokumencie, uznaliśmy za nieznany fragment.
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 je zignorować. Autorzy powinni zachować w swoich w pierwotnej kolejności (chyba że rzeczywiście chcą 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 „VP8X” (Canvas Width Minus One + 1
pikseli szerokości i Canvas Height Minus
One + 1
pikseli wysokości). Pole Loop Count
z tabeli „ANIM” Kawałek kontroluje sposób
wiele razy proces 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 w pętli obszar roboczy jest wypełniany za pomocą atrybutu kolor tła z obrazu „ANIM” Kawałek lub kolor zdefiniowany przez aplikację.
Fragmenty „ANMF” zawierają poszczególne klatki w kolejności wyświetlania. Przed renderowaniem każdej klatki Disposal method
jest stosowana w poprzedniej klatce.
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.
Frame Width Minus One + 1
piks. szerokości na Frame Height Minus One + 1
piks.
są renderowane na obszarze roboczym za pomocą Blending method
.
Płótno jest wyświetlane przez Frame Duration
milisekund. Ten proces będzie trwać, dopóki nie zostaną wyświetlone wszystkie ramki z elementów „ANMF”. 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. Notacja VP8X.pole 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)
Obraz w formacie bezstratnym z profilem ICC i metadanymi XMP może wyglądają 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)