WebP Kayıpsız Bit Akışı spesifikasyonu

Jyrki Alakuijala, PhD, Google, Inc., 09.03.2023

Soyut

WebP kayıpsız, ARGB resimlerinin kayıpsız sıkıştırılması için kullanılan bir resim biçimidir. İlgili içeriği oluşturmak için kullanılan kayıpsız biçim, şunlar da dahil olmak üzere piksel değerlerini tam olarak depolar ve geri yükler: renk değerlerini kullanmanızı öneririz. Ardışık düzen için evrensel bir algoritma Veri sıkıştırma (LZ77), önek kodlaması ve renk önbelleği, sıkıştırılmış verilerdir. Kod çözme hızları PNG'den daha hızlı elde edilene kıyasla% 25 daha yoğun bir sıkıştırma bugünkü PNG biçiminde sunulur.

1 Giriş

Bu belgede, kayıpsız bir WebP'nin sıkıştırılmış veri temsili açıklanmaktadır görüntüsüdür. WebP kayıpsız kodlayıcısı için ayrıntılı bir referans olması amacıyla tasarlanmıştır ve kod çözücü uygulaması.

Bu belgede, C programlama dili söz dizimini kullanarak ve bitleri okumak için bir fonksiyonun mevcut olduğunu varsaymak, ReadBits(n) Baytlar, veri feed'i içeren akışın sırasına göre ve her baytın bitleri en az anlamlı bit-ilk sıraya göre okunur. Zaman birden çok bit aynı anda okunursa tam sayı, orijinal sırasına göre düzenleyebilirsiniz. Döndürülen tamsayılar da orijinal verilerin en önemli bitleridir. Dolayısıyla, ifade

b = ReadBits(2);

aşağıdaki iki ifadeye eşdeğerdir:

b = ReadBits(1);
b |= ReadBits(1) << 1;

Alfa, kırmızı, mavi ve yeşil olmak üzere her bir renk bileşeninin, 8 bitlik bayt kullanılarak temsil edilir. Karşılık gelen türü uint8 olarak tanımlarız. CEVAP ARGB pikselinin tamamı, uint32 adında bir türle temsil edilir. 32 bitten oluşan tam sayı. Davranışı gösteren kodda, bu değerler, bit cinsinden şu bitlere kodlanır: bit cinsinden alfa 31..24, 23..16 bitlerinde kırmızı, 15..8 bitlerinde yeşil ve 7..0 bitlerinde mavi; ancak, biçimin uygulanmasında, şirket içinde başka bir temsil kullanmak serbesttir.

Genel olarak WebP kayıpsız resmi, başlık verilerini, dönüştürme bilgilerini ve gerçek resim verileridir. Başlıklar, resmin genişliğini ve yüksekliğini içerir. WebP kayıpsız resim, silinmeden önce dört farklı dönüşüm türünde geçebilir entropi kodlanmıştır. Bit akışındaki dönüşüm bilgileri, ilgili ters dönüşümleri uygulamak için gereklidir.

2 Nomenklatür

ARGB
Alfa, kırmızı, yeşil ve mavi değerlerinden oluşan bir piksel değeri.
ARGB resmi
ARGB pikselleri içeren iki boyutlu bir dizi.
renk önbelleği
Son kullanılan renklerin depolandığı, karma adresli küçük bir dizi: bunları daha kısa kodlarla hatırlayın.
renk dizine ekleme resmi
Küçük bir tam sayı kullanılarak dizine eklenebilen renklerin tek boyutlu görüntüsü (WebP'de kayıpsız en fazla 256).
renk dönüştürme resmi
Bu karenin korelasyonlarıyla ilgili veriler içeren iki boyutlu alt çözünürlüklü bir görüntü renk bileşenleri hakkında daha fazla bilgi edinin.
mesafe haritası
LZ77 mesafelerini, pikseller için en küçük değerlere sahip olacak şekilde değiştirir yakınlık sağlar.
entropi resmi
Entropi kodlamasının hangi iki boyutlu alt çözünürlüklü olması gerektiğini gösteren birlikte kullanılmalıdır, yani her piksel bir meta önek kodunu ekleyin.
LZ77
Sözlük tabanlı bir kayan pencere sıkıştırma algoritması için veya bunları geçmiş sembollerin dizileri olarak tarif eden içerikler üretir.
meta önek kodu
Meta ön ekteki bir öğeyi dizine ekleyen küçük bir tam sayı (16 bit'e kadar) tablosunda gösterilir.
tahmin aracı görüntüsü
Hangi mekansal tahmincinin olduğunu gösteren iki boyutlu alt çözünürlüklü bir görüntü nasıl kullanılacağını anlatacağım.
önek kodu
Daha az sayıda bitin kullanıldığı entropi kodlaması yapmanın klasik yolu bakın.
önek kodlaması
Tam sayının birkaç bitini kodlayan, daha büyük tam sayıları entropi etmenin bir yolu bitleri işlenmemiş olarak kodlar. Bu da entropi kodlarının tanımlarının ne kadar küçük olduğunu görsek bile simge aralığı geniş olduğundan emin olun.
satır tarama sırası
Piksellerden oluşan işleme sırası (soldan sağa ve yukarıdan aşağıya), pikselden uzaklaştırın. Bir satır tamamlandıktan sonra, devam etmek için diğer satırın sol sütununa girin.

3 RIFF Başlığı

Başlığın başında RIFF kapsayıcısı bulunur. Bu, (21 bayt altında):

  1. Dize 'RIFF'.
  2. Yığın uzunluğunun tam boyutu olan 32 bitlik küçük son değeri kontrol edilen parçasını görebilirsiniz. Normalde bu, yük boyutu (dosya boyutu eksi 8 bayt: 'RIFF' için 4 bayt tanımlayıcı ve değerin kendisini depolamak için 4 bayt) olmasını öneririz.
  3. Dize: "WEBP" (RIFF kapsayıcı adı).
  4. Dize: "VP8L" (Kayıpsız kodlanmış resim verileri için dört kod).
  5. Veri kümesindeki bayt sayısının 32 bitlik kayıpsız akış sağlar.
  6. 1 baytlık imza 0x2f.

Bit akışının ilk 28 biti resmin genişliğini ve yüksekliğini belirtir. Genişlik ve yüksekliğin kodu, aşağıdaki gibi 14 bitlik tam sayılar şeklinde çözülür:

int image_width = ReadBits(14) + 1;
int image_height = ReadBits(14) + 1;

Resim genişliği ve yüksekliğinin 14 bit hassasiyeti, bir resmin maksimum 16384 arttırma 16384 piksele kadar WebP kayıpsız resim.

alpha_is_used biti yalnızca bir ipucudur ve kod çözmeyi etkilememelidir. Uygulama resimde tüm alfa değerleri 255 olduğunda 0 olarak, aksi halde 1 olarak ayarlanması gerekir.

int alpha_is_used = ReadBits(1);

version_number, 0 olarak ayarlanması gereken 3 bitlik bir koddur. Diğer herhangi bir değer bir hata olarak değerlendirilecektir.

int version_number = ReadBits(3);

4 Dönüşüm

Dönüşümler, görüntü verilerinin ters çevrilebilir şekilde değiştirilmesidir. uzamsal ve renk korelasyonlarını modelleyerek kalan sembolik entropiyi gösterir. Onlar nihai sıkıştırmayı daha yoğun hale getirebilir.

Bir görüntü dört türde dönüşüme tabi tutulabilir. 1 bit, dönüşüm varlığıdır. Her dönüşümün yalnızca bir kez kullanılmasına izin verilir. İlgili içeriği oluşturmak için kullanılan Dönüşümler yalnızca ana düzey ARGB görüntüsü için kullanılır; alt çözünürlüklü resimleri (renk dönüştürme resmi, entropi resmi ve tahminci görüntüsü) dönüşüm içermez, dönüşümlerin sonunu belirten 0 bit bile yoktur.

Kodlayıcı, genellikle Shannon entropisini azaltmak için bu dönüşümleri kullanır. resim olarak ekleyin. Ayrıca, dönüşüm verilerine entropiye göre de karar verilebilir. inceleyebilirsiniz.

while (ReadBits(1)) {  // Transform present.
  // Decode transform type.
  enum TransformType transform_type = ReadBits(2);
  // Decode transform data.
  ...
}

// Decode actual image data (Section 5).

Dönüşüm varsa sonraki iki bit, dönüşüm türünü belirtir. Dört tür dönüşüm vardır.

enum TransformType {
  PREDICTOR_TRANSFORM             = 0,
  COLOR_TRANSFORM                 = 1,
  SUBTRACT_GREEN_TRANSFORM        = 2,
  COLOR_INDEXING_TRANSFORM        = 3,
};

Dönüşüm türünün ardından dönüşüm verileri gelir. Dönüşüm verileri şunları içerir: ters dönüşümü uygulamak için gereken bilgi ve dönüşüm türü. Ters dönüşümler şu sırayla uygulanır: bunlar bit akışından, yani önce sonuncudan okunur.

Daha sonra farklı türler için dönüşüm verilerini açıklayacağız.

4.1 Tahminci Dönüşümü

Gösterge dönüşümü, olgudan yararlanarak entropiyi azaltmak için kullanılabilir bu da komşu piksellerin genellikle ilişkili olduğunu gösterir. Tahminci dönüşümünde geçerli piksel değeri, kodu çözülmüş piksellerden tahmin edilir (tarama satırında sipariş) ve yalnızca artık değer (gerçek - tahmin edilen) kodlanır. Yeşil bileşeninin 14 göstergeden hangisinin kullanıldığını tanımlar. içeren bir grafik kartı seçin. Tahmin modu, belirli bir tahmindir. Resmi karelere böleriz ve bir bölümdeki tüm pikselleri aynı tahmin modunu kullanır.

Tahmin verilerinin ilk 3 biti, blok genişliği ve yüksekliğini sayı olarak tanımlar. biter.

int size_bits = ReadBits(3) + 2;
int block_width = (1 << size_bits);
int block_height = (1 << size_bits);
#define DIV_ROUND_UP(num, den) (((num) + (den) - 1) / (den))
int transform_width = DIV_ROUND_UP(image_width, 1 << size_bits);

Dönüşüm verileri, görüntünün her bir bloğu için tahmin modunu içerir. Google bir pikselin yeşil bileşeninin hangi pikselin içindeki tüm block_width * block_height pikseller için 14 tahminci kullanılır ARGB resminin belirli bir bloğunu kullanın. Bu alt çözünürlüklü resim 5. Bölüm'de açıklanan tekniklerin aynısıdır.

Blok sütunlarının sayısı (transform_width) iki boyutlu olarak kullanılır dizine ekleyin. Bir piksel (x, y) için ilgili filtre bloğu hesaplanabilir adresini gönderen:

int block_index = (y >> size_bits) * transform_width +
                  (x >> size_bits);

14 farklı tahmin modu vardır. Her tahmin modunda, piksel değeri, değerleri aynı olan bir veya daha fazla komşu pikselden tahmin edilir zaten biliniyor.

Geçerli pikselin (P) komşu piksellerini (TL, T, TR ve L) şöyle olur:

O    O    O    O    O    O    O    O    O    O    O
O    O    O    O    O    O    O    O    O    O    O
O    O    O    O    TL   T    TR   O    O    O    O
O    O    O    O    L    P    X    X    X    X    X
X    X    X    X    X    X    X    X    X    X    X
X    X    X    X    X    X    X    X    X    X    X

Burada TL sol üst, T üst ve TR sağ üst ve L sol anlamına gelir. Kuyruklu a işareti tüm O, TL, T, TR ve L pikselleri için bir değer tahmin etme zamanı ve P pikseli ile tüm X pikselleri bilinmiyor.

Önceki komşu piksellere göre farklı tahmin modları tanımlanabilir.

Mod Geçerli pikselin her kanalının tahmini değeri
0 0xff000000 (ARGB'de düz siyah rengi temsil eder)
1 L
2 S
3 TR
4 ekip lideri
5 Ortalama2(Ortalama2(L, TR), T)
6 Ortalama2(L, TL)
7 Ortalama2(L; T)
8 Ortalama2(TL; T)
9 Ortalama2(T; TR)
10 Ortalama2(Ortalama2(L; TL), Ortalama2(T, TR))
11 Seç(L, T; TL)
12 ClampAddSubtractFull(L, T, TL)
13 ClampAddSubtractHalf(Average2(L, T), TL)

Average2, her bir ARGB bileşeni için aşağıdaki gibi tanımlanır:

uint8 Average2(uint8 a, uint8 b) {
  return (a + b) / 2;
}

Tahmin aracı seç aşağıdaki şekilde tanımlanır:

uint32 Select(uint32 L, uint32 T, uint32 TL) {
  // L = left pixel, T = top pixel, TL = top-left pixel.

  // ARGB component estimates for prediction.
  int pAlpha = ALPHA(L) + ALPHA(T) - ALPHA(TL);
  int pRed = RED(L) + RED(T) - RED(TL);
  int pGreen = GREEN(L) + GREEN(T) - GREEN(TL);
  int pBlue = BLUE(L) + BLUE(T) - BLUE(TL);

  // Manhattan distances to estimates for left and top pixels.
  int pL = abs(pAlpha - ALPHA(L)) + abs(pRed - RED(L)) +
           abs(pGreen - GREEN(L)) + abs(pBlue - BLUE(L));
  int pT = abs(pAlpha - ALPHA(T)) + abs(pRed - RED(T)) +
           abs(pGreen - GREEN(T)) + abs(pBlue - BLUE(T));

  // Return either left or top, the one closer to the prediction.
  if (pL < pT) {
    return L;
  } else {
    return T;
  }
}

ClampAddSubtractFull ve ClampAddSubtractHalf işlevleri gerçekleştirilir aşağıdaki gibi her ARGB bileşeni için:

// Clamp the input value between 0 and 255.
int Clamp(int a) {
  return (a < 0) ? 0 : (a > 255) ? 255 : a;
}
int ClampAddSubtractFull(int a, int b, int c) {
  return Clamp(a + b - c);
}
int ClampAddSubtractHalf(int a, int b) {
  return Clamp(a + (a - b) / 2);
}

Bazı kenarlık pikselleri için özel işleme kuralları vardır. Bir tahminci dönüşümü, bu piksellerin modundan [0..13] bağımsız olarak resmin en soldaki pikseli için tahmini değer 0xff000000'dir. en üst satırdaki pikseller L pikseldir ve en soldaki sütundaki tüm pikseller T-piksel.

En sağdaki sütundaki pikseller için TR-pikseli olağanüstü. En sağdaki sütundaki pikseller, modlar kullanılarak tahmin edilir. [0..13], tıpkı kenarlıkta değil, banner'da en soldaki piksel gibi aynı satır bunun yerine TR-piksel olarak kullanılır.

Nihai piksel değeri, tahmin edilen değerden her bir kanal eklenerek elde edilir kodlanan artık değere eşit değildir.

void PredictorTransformOutput(uint32 residual, uint32 pred,
                              uint8* alpha, uint8* red,
                              uint8* green, uint8* blue) {
  *alpha = ALPHA(residual) + ALPHA(pred);
  *red = RED(residual) + RED(pred);
  *green = GREEN(residual) + GREEN(pred);
  *blue = BLUE(residual) + BLUE(pred);
}

4.2 Renk Dönüştürme

Renk dönüşümünün amacı, her bir öğenin R, G ve B değerlerini süslemektir. piksel. Renk dönüşümü, yeşil (G) değerini olduğu gibi korur, yeşil değeri temel alan kırmızı (R) değerini ve mavi (B) değerini üzerine gelin.

Tahminci dönüşümünde olduğu gibi, önce görüntü, ve bir bloktaki tüm pikseller için aynı dönüştürme modu kullanılır. Örneğin, üç tür renk dönüştürme öğesi vardır.

typedef struct {
  uint8 green_to_red;
  uint8 green_to_blue;
  uint8 red_to_blue;
} ColorTransformElement;

Gerçek renk dönüşümü, bir renk dönüşüm deltası tanımlanarak yapılır. İlgili içeriği oluşturmak için kullanılan renk dönüşümü delta değeri, aynı olan ColorTransformElement değerine bağlıdır her piksel için ayrı bir değerdir. Delta, sağlayabilirsiniz. Ters renk dönüşümü, yalnızca bu deltaları ekler.

Renk dönüştürme işlevi aşağıdaki gibi tanımlanır:

void ColorTransform(uint8 red, uint8 blue, uint8 green,
                    ColorTransformElement *trans,
                    uint8 *new_red, uint8 *new_blue) {
  // Transformed values of red and blue components
  int tmp_red = red;
  int tmp_blue = blue;

  // Applying the transform is just subtracting the transform deltas
  tmp_red  -= ColorTransformDelta(trans->green_to_red,  green);
  tmp_blue -= ColorTransformDelta(trans->green_to_blue, green);
  tmp_blue -= ColorTransformDelta(trans->red_to_blue, red);

  *new_red = tmp_red & 0xff;
  *new_blue = tmp_blue & 0xff;
}

ColorTransformDelta, değeri temsil eden 8 bitlik imzalı bir tam sayı kullanılarak 3,5 sabit noktalı sayı ve imzalı 8 bit RGB renk kanalı (c) [-128..127] ve şu şekilde tanımlanır:

int8 ColorTransformDelta(int8 t, int8 c) {
  return (t * c) >> 5;
}

8 bitlik imzasız temsilden (uint8) 8 bit imzalı biçime dönüşüm ColorTransformDelta() çağrılmadan önce one (int8) gereklidir. İmzalanmış değer 8 bitlik bir ikinin tamamlayıcı sayısı (yani uint8 aralığı) olarak yorumlanmalıdır [128..255], dönüştürülmüş int8 değerinin [-128..-1] aralığıyla eşlenir).

Çarpma işlemi daha fazla hassasiyet kullanılarak (en az 16 bit hassasiyeti). Kaydırma işleminin işaret uzantısı özelliği önemli değildir burayı tıklayın; sonuçtan yalnızca en düşük 8 bit kullanılır ve bu ve imzasız kaymaların birbirleriyle tutarlı olduğunu gösterir.

Şimdi de kod çözmenin uygulanabilmesi için renk dönüştürme verilerinin içeriğini açıklıyoruz. orijinal kırmızı ve mavi değerlerini kurtarabilirsiniz. İlgili içeriği oluşturmak için kullanılan renk dönüştürme verilerinin ilk 3 biti, renk tonunun genişliğini ve yüksekliğini tahminci dönüşümünde olduğu gibi bit sayısı olan resim bloğu:

int size_bits = ReadBits(3) + 2;
int block_width = 1 << size_bits;
int block_height = 1 << size_bits;

Renk dönüştürme verilerinin kalan kısmı ColorTransformElement içerir örneklerini içerir. Her biri ColorTransformElement 'cte', alt çözünürlüklü bir resimde piksel olarak değerlendirilir alfa bileşeni 255, kırmızı bileşen cte.red_to_blue, yeşil bileşen cte.green_to_blue, mavi bileşen cte.green_to_red.

Kod çözme sırasında, ColorTransformElement blok örneğinin kodu çözülür ve ters renk dönüşümü, piksellerin ARGB değerlerine uygulanır. Farklı daha önce de belirtildiği gibi, ters renk dönüşümünü Kırmızı ve mavi kanallara ColorTransformElement değerleri. Alfa ve yeşil olduğu gibi bırakılır.

void InverseTransform(uint8 red, uint8 green, uint8 blue,
                      ColorTransformElement *trans,
                      uint8 *new_red, uint8 *new_blue) {
  // Transformed values of red and blue components
  int tmp_red = red;
  int tmp_blue = blue;

  // Applying the inverse transform is just adding the
  // color transform deltas
  tmp_red  += ColorTransformDelta(trans->green_to_red, green);
  tmp_blue += ColorTransformDelta(trans->green_to_blue, green);
  tmp_blue +=
      ColorTransformDelta(trans->red_to_blue, tmp_red & 0xff);

  *new_red = tmp_red & 0xff;
  *new_blue = tmp_blue & 0xff;
}

4.3 Yeşil Çıkarma Dönüşümü

Yeşil çıkarma dönüşümü, yeşil değerleri şu öğenin kırmızı ve mavi değerlerinden çıkarır: her bir pikselde bir araya gelir. Bu dönüşüm mevcut olduğunda kod çözücünün yeşil renk eklemesi hem kırmızı hem de mavi değerlere ayarlayın. Bununla ilişkilendirilmiş veri yok gerekir. Kod çözücü, ters dönüşümü şu şekilde uygular:

void AddGreenToBlueAndRed(uint8 green, uint8 *red, uint8 *blue) {
  *red  = (*red  + green) & 0xff;
  *blue = (*blue + green) & 0xff;
}

Bu dönüşüm, renk dönüşümü kullanılarak modellenebileceği için gereksizdir ancak burada ek veri olmadığından, yeşil çıkarma dönüşümü daha az bit kullanarak kodlanır.

4.4 Renk Dizine Ekleme Dönüşümü

Çok sayıda benzersiz piksel değeri yoksa, tek bir sistem kullanarak renk dizini dizisi oluşturur ve piksel değerlerini dizinin dizinleriyle değiştirir. Renk dizine ekleme dönüşümü bunu sağlar. (WebP kayıpsız bağlamında özellikle benzer ancak daha farklı dinamik kavram WebP kayıpsız kodlamada bulunur: renk önbelleği.)

Renk dizine ekleme dönüşümü, görüntüsüdür. Bu sayı bir eşiğin (256) altındaysa bu değerlerin bir dizisi oluşturur ARGB değerleri (daha sonra piksel değerlerini karşılık gelen dizin: piksellerin yeşil kanalı dizini için, tüm alfa değerleri 255 ve tüm kırmızı ve mavi değerleri 0 olarak ayarlanır.

Dönüşüm verileri, renk tablosu boyutunu ve renkteki girişleri içerir tablosunu oluşturalım. Kod çözücü, renk dizine ekleme dönüşüm verilerini şu şekilde okur:

// 8-bit value for the color table size
int color_table_size = ReadBits(8) + 1;

Renk tablosu, resim depolama biçiminin kendisi kullanılarak depolanır. Renk tablosu RIFF başlığı, resim boyutu ve bağlantısı olmadan bir resim okunarak elde edilebilir. 1 piksel yüksekliğinde ve color_table_size genişliğinde olduğu varsayılarak dönüştürülür. Renk tablosu, görüntü entropisini azaltmak için her zaman çıkarma kodludur. Deltalar palet renklerinin entropileri genellikle renklerden çok daha azdır Bu da daha küçük resimlerde önemli tasarruf sağlar. Kod çözmede, renk tablosundaki her son renk, önceki renk bileşeni değerlerini her ARGB bileşenine göre ayrı ayrı depolayarak önemli olan 8 bit'lik dilimde yer alır.

Resmin ters dönüşümü, basitçe piksel değerlerinin (bu değer, renk tablosu dizinleridir). Dizine ekleme ARGB renginin yeşil bileşeni temel alınarak yapılır.

// Inverse transform
argb = color_table[GREEN(argb)];

Dizin color_table_size değerine eşit veya bundan daha büyükse a hayatı simgesi renk değeri 0x00000000 (şeffaf siyah) olarak ayarlanmalıdır.

Renk tablosu küçükse (16 renge eşit veya daha az renge eşitse) birkaç piksel tek bir piksel halinde gruplandırılır. Piksel gruplandırması birkaç (2, 4 veya 8) paketi içerir pikselleri tek piksele dönüştürür ve sırasıyla resim genişliğini azaltır. Piksel paketleme, verilerin daha verimli bir şekilde ortak dağıtım entropi kodlamasına komşu pikseller oluşturur ve entropi kodu içerir, ancak yalnızca 16 veya daha az benzersiz değer olduğunda kullanılabilir.

color_table_size, kaç pikselin birleştirildiğini belirtir:

int width_bits;
if (color_table_size <= 2) {
  width_bits = 3;
} else if (color_table_size <= 4) {
  width_bits = 2;
} else if (color_table_size <= 16) {
  width_bits = 1;
} else {
  width_bits = 0;
}

width_bits öğesinin değeri 0, 1, 2 veya 3'tür. 0 değeri, piksel olmadığını gösterir gruplama yapılır. 1 değeri, iki pikselin ve her pikselin [0..15] aralığı vardır. 2 değeri, dört piksel birleştirilir ve her bir pikselin [0..3] aralığı vardır. 3 değeri sekiz pikselin birleştirildiğini ve her pikselin [0..1], yani ikilik değerdir.

Değerler, yeşil bileşene şu şekilde yerleştirilir:

  • width_bits = 1: Her x değeri için x Re 0 (mod 2), bir yeşil değeri, x'teki değer, rastgele sayı x / 2'deki yeşil bir değer ve x + 1'deki yeşil bir değer x / 2'deki yeşil değerin 4 en önemli biti.
  • width_bits = 2: Her x değeri için x Re 0 (mod 4), bir yeşil x'teki değer, x / 4'teki yeşil değer ve x + 1 - x + 3 aralığındaki yeşil değerler x / 4'teki yeşil değerin daha önemli bitlerine göre sıralanır.
  • width_bits = 3: Her x değeri için x kazançları 0 (mod 8), yeşil x'teki değer, yeşilin en az anlamlı bitine konumlandırılır x / 8'deki değer ve x + 1 - x + 7 arasındaki yeşil değerler sırayla konumlandırılır x / 8'deki yeşil değerin daha önemli bitlerine ekler.

Bu dönüşüm okunduktan sonra image_width, width_bits tarafından alt örneklenir. Bu sonraki dönüşümlerin boyutunu etkiler. Yeni boyut şöyle hesaplanabilir: Daha önce tanımlandığı şekliyle DIV_ROUND_UP.

image_width = DIV_ROUND_UP(image_width, 1 << width_bits);

5 Resim Verisi

Resim verileri, tarama satırı sırasındaki bir piksel değerleri dizisidir.

5.1 Resim Verilerinin Rolleri

Resim verilerini beş farklı rolde kullanırız:

  1. ARGB resmi: Resmin gerçek piksellerini depolar.
  2. Entropi resmi: Meta ön ek kodlarını depolar (bkz. "Meta Önek Kodlarının Kodunu Çözme").
  3. Tahminci görüntüsü: Tahminci dönüşümü için meta verileri depolar (bkz. "Tahmin Aracı Dönüşümü").
  4. Renk dönüştürme resmi: ColorTransformElement değerleri tarafından oluşturuldu ("Renk Dönüşümü" bölümünde tanımlanmıştır) için farklı bloklar gösterir.
  5. Renk dizine ekleme resmi: Boyut dizisi color_table_size (en fazla 256 ARGB) değerleri) depolayarak (bkz. "Renk Dizine Ekleme Dönüşümü").

5.2 Resim Verilerinin Kodlanması

Resim verilerinin kodlanması rolünden bağımsızdır.

Resim önce bir dizi sabit boyutlu bloka bölünür (genellikle 16x16 boyutundaki). blok) seçebilirsiniz. Bu blokların her biri kendi entropi kodları kullanılarak modellenir. Ayrıca, birkaç blok aynı entropi kodunu paylaşabilir.

Mantıksal: Entropi kodunu depolamanın maliyeti vardır. Maliyet en aza indirebilir İstatistiksel olarak benzer bloklar bir entropi kodunu paylaşır ve böylece bu kodu yalnızca bir kez. Örneğin, kodlayıcı benzer blokları kümeleyerek bulabilir. kullanarak veya rastgele sayılarla bir çifti sürekli olarak birleştirerek kodlamak için gereken toplam bit miktarını azalttığında, seçtiğiniz kümeler resim.

Her piksel, aşağıdaki üç olası yöntemden biri kullanılarak kodlanır:

  1. Ön ek kodlu değişmez değerler: Her kanal (yeşil, kırmızı, mavi ve alfa) bağımsız olarak entropi kodlanmıştır.
  2. LZ77 geriye dönük referansı: Bir piksel dizisi, resim.
  3. Renk önbelleği kodu: Kısa bir çarpımsal karma kodu (renk önbelleği) dizini) görürsünüz.

Aşağıdaki alt bölümlerde bunların her biri ayrıntılı olarak açıklanmaktadır.

5.2.1 Ön Ek Kodlu Değişmez Değerler

Piksel, ön ek kodlu yeşil, kırmızı, mavi ve alfa değerleri olarak depolanır sipariş). Aşağıdaki özellikler için bkz. Bölüm 6.2.3 bolca fırsat sunuyor.

5.2.2 LZ77 Geriye Dönük Referans

Geriye dönük referanslar, uzunluk ve mesafe kodu demetleridir:

  • Uzunluk, tarama çizgisi sırasındaki kaç pikselin kopyalanacağını belirtir.
  • Mesafe kodu, daha önce görülen bir yerin konumunu gösteren bir sayıdır piksellerin kopyalanacağı piksel. Tam eşleme aşağıda açıklanmıştır.

Uzunluk ve mesafe değerleri LZ77 önek kodlaması kullanılarak depolanır.

LZ77 ön ek kodlaması, büyük tam sayı değerlerini iki bölüme ayırır: önek kodu ve ekstra bit değerlerini ekleyin. Önek kodu, bir entropi kodu kullanılarak depolanır ekstra bitler oldukları gibi (entropi kodu olmadan) depolanır.

Mantıksal: Bu yaklaşım entropi için depolama gereksinimini azaltır girin. Ayrıca, büyük değerler genellikle nadiren görülür. Bu nedenle, değer ekleyemeyeceğim. Böylece, bu yaklaşım sayesinde yardımcı olabilir.

Aşağıdaki tabloda, izin verebilirsiniz.

Değer aralığı Önek kodu Ekstra bitler
1 0 0
2 1 0
3 2 0
4 3 0
5..6 4 1
7..8 5 1
9..12 6 2
13...16 7 2
... ... ...
3072..4096 23 10
... ... ...
524289..786432 38 18
786433..1048576 39 18

Önek kodundan bir (uzunluk ya da mesafe) değeri elde etmek için sözde kod şöyle olabilir: şöyle olur:

if (prefix_code < 4) {
  return prefix_code + 1;
}
int extra_bits = (prefix_code - 2) >> 1;
int offset = (2 + (prefix_code & 1)) << extra_bits;
return offset + ReadBits(extra_bits) + 1;
Mesafe Eşleme

Daha önce belirtildiği gibi, mesafe kodu bir nesnenin konumunu gösteren bir sayıdır daha önce görülen ve piksellerin kopyalanacağı piksel. Bu alt bölüm mesafe kodu ile önceki bir uzaklık kodu arasındaki konum piksel.

120'den büyük mesafe kodları, piksel mesafesini tarama çizgisi sırasına göre belirtir. farkı 120'ye çıkarır.

En küçük mesafe kodları [1..120] özeldir ve yakın zamandaki ne kadarının nerede olduğunu gösterir. Bu mahalle 120 pikselden oluşur:

  • Geçerli pikselin 1 ila 7 satır üzerinde olan ve en fazla 8 sütun içeren pikseller sola veya en fazla 7 sütuna dokunun. [Toplam bu tür piksellerin sayısı = 7 * (8 + 1 + 7) = 112].
  • Geçerli pikselle aynı satırda bulunan ve en fazla 8 adet olan pikseller sütunlarını tıklayın. [8 bu tür piksel].

distance_code mesafe kodu ile komşu piksel arasındaki eşleme (xi, yi) ofseti aşağıdaki gibidir:

(0, 1),  (1, 0),  (1, 1),  (-1, 1), (0, 2),  (2, 0),  (1, 2),
(-1, 2), (2, 1),  (-2, 1), (2, 2),  (-2, 2), (0, 3),  (3, 0),
(1, 3),  (-1, 3), (3, 1),  (-3, 1), (2, 3),  (-2, 3), (3, 2),
(-3, 2), (0, 4),  (4, 0),  (1, 4),  (-1, 4), (4, 1),  (-4, 1),
(3, 3),  (-3, 3), (2, 4),  (-2, 4), (4, 2),  (-4, 2), (0, 5),
(3, 4),  (-3, 4), (4, 3),  (-4, 3), (5, 0),  (1, 5),  (-1, 5),
(5, 1),  (-5, 1), (2, 5),  (-2, 5), (5, 2),  (-5, 2), (4, 4),
(-4, 4), (3, 5),  (-3, 5), (5, 3),  (-5, 3), (0, 6),  (6, 0),
(1, 6),  (-1, 6), (6, 1),  (-6, 1), (2, 6),  (-2, 6), (6, 2),
(-6, 2), (4, 5),  (-4, 5), (5, 4),  (-5, 4), (3, 6),  (-3, 6),
(6, 3),  (-6, 3), (0, 7),  (7, 0),  (1, 7),  (-1, 7), (5, 5),
(-5, 5), (7, 1),  (-7, 1), (4, 6),  (-4, 6), (6, 4),  (-6, 4),
(2, 7),  (-2, 7), (7, 2),  (-7, 2), (3, 7),  (-3, 7), (7, 3),
(-7, 3), (5, 6),  (-5, 6), (6, 5),  (-6, 5), (8, 0),  (4, 7),
(-4, 7), (7, 4),  (-7, 4), (8, 1),  (8, 2),  (6, 6),  (-6, 6),
(8, 3),  (5, 7),  (-5, 7), (7, 5),  (-7, 5), (8, 4),  (6, 7),
(-6, 7), (7, 6),  (-7, 6), (8, 5),  (7, 7),  (-7, 7), (8, 6),
(8, 7)

Örneğin, 1 mesafe kodu, mesafe kodu için (0, 1) komşu piksel, yani geçerli pikselin üzerindeki piksel (0 piksel) X yönünde 1 piksel fark, Y yönünde ise 1 piksel fark). Benzer şekilde, mesafe kodu 3 sol üstteki pikseli belirtir.

Kod çözücü, distance_code mesafe kodunu tarama çizgisi sırasına dönüştürebilir dist mesafesi şu şekildedir:

(xi, yi) = distance_map[distance_code - 1]
dist = xi + yi * image_width
if (dist < 1) {
  dist = 1
}

Burada distance_map yukarıda belirtilen eşleme, image_width ise genişliktir piksel cinsinden kaydedin.

5.2.3 Renk Önbelleği Kodlaması

Renk önbelleği, resimde son zamanlarda kullanılan bir dizi rengi depolar.

Mantıksal: Bu şekilde, son kullanılan renkler bazen diğer iki yöntemi kullanarak yayınlamaktan daha etkilidir (bkz. 5.2.1 ve 5.2.2) dâhildir.

Renk önbellek kodları aşağıdaki gibi depolanır. İlk olarak, renk önbelleğinin kullanılıp kullanılmadığını gösterir. Bu bit 0 ise, renk önbellek kodu bulunmaz ve bunlar, yeşil renk kodunu çözen önek kodunda iletilmez ve uzunluk öneki kodları kullanabilirsiniz. Bununla birlikte, bu bit 1 ise, renk önbelleği size sonrakini oku:

int color_cache_code_bits = ReadBits(4);
int color_cache_size = 1 << color_cache_code_bits;

color_cache_code_bits, renk önbelleğinin (1 << color_cache_code_bits) boyutunu tanımlar. Şunun için izin verilen değer aralığı: color_cache_code_bits [1..11] tarihinde. Uyumlu kod çözücüler diğer değerler için bozuk bit akışı.

Renk önbelleği, color_cache_size boyutunda bir dizidir. Her giriş bir ARGB depolar rengi. Renkler, (0x1e35a7bd * color) >> (32 - color_cache_code_bits) dizine eklenerek aranır. Renk önbelleğinde yalnızca bir arama yapılır; yok çatışmaların çözümü.

Bir resmin kodunu çözmenin veya kodlamanın başında, tüm renkli tüm girişler önbellek değerleri sıfır olarak ayarlanır. Renk önbelleği kodu, şurada bu renge dönüştürülür: kod çözme süresi. Renk önbelleğinin durumu, geriye referansla veya değişmez değer olarak üretilmiş olması fark etmeksizin akışta göründükleri sıraya sokmaktır.

6 Entropi Kodu

6.1 Genel Bakış

Verilerin çoğu standart ön ek kodu kullanılarak kodlanır. Bu nedenle kodlar, önek kod uzunluklarını gerçek önek kodlarının aksine.

Özellikle bu biçim, uzamsal varyant ön ek kodlamasını kullanır. Başka resmin farklı blokları potansiyel olarak farklı entropi kullanabilir ekleyebilirsiniz.

Mantıksal: Resmin farklı alanları farklı özelliklere sahip olabilir. Dolayısıyla, farklı entropi kodları kullanmalarına izin vermek daha fazla esneklik sağlar ve daha iyi sıkıştırma olasılığı vardır.

6.2 Ayrıntılar

Kodlanmış resim verileri birkaç bölümden oluşur:

  1. Önek kodlarının kodunu çözme ve oluşturma.
  2. Meta önek kodları.
  3. Entropi kodlu görüntü verileri.

Belirli bir piksel (x, y) için, şununla ilişkili beş ön ek kodundan oluşan bir küme vardır: somut olarak ortaya koyar. Bu kodlar (bit akışı sırasına göre):

  • Önek kodu 1: Yeşil kanal, geriye dönük referans uzunluğu ve renk önbelleğine girer.
  • Önek kodu 2, #3 ve #4: Kırmızı, mavi ve alfa kanalları için kullanılır. tıklayın.
  • Önek kodu 5: Geriye referans mesafesi için kullanılır.

Bundan böyle, bu küme bir önek kod grubu olarak adlandırılır.

6.2.1 Önek Kodlarının Kodunu Çözme ve Oluşturma

Bu bölümde, ön ek kodu uzunluklarının bit akışından nasıl okunacağı açıklanmaktadır.

Önek kodu uzunlukları iki şekilde kodlanabilir. Kullanılan yöntem belirtilmiş bir veri kümesi oluşturun.

  • Bu bit 1 ise basit bir kod uzunluğu kodudur.
  • Bu bit 0 ise normal kod uzunluğu kodudur.

Her iki durumda da, hâlâ akış şeklinde gösterilir. Bu verimsiz olabilir ancak biçim nedeniyle izin verilir. Açıklanan ağaç tam bir ikili ağaç olmalıdır. Tek yapraklı düğüm tam bir ikili ağacı kabul edilir ve veya normal kod uzunluğu kodu kullanabilirsiniz. Tek bir yaprağı kodlarken normal kod uzunluğu kodunu kullanan bir düğüm varsa biri hariç tümünün uzunluğu sıfırdır. Tek yapraklı düğüm değerinin uzunluğu ise 1 olarak işaretlenir ( bitlerinin tüketildiğini gösterir.

Basit Kod Uzunluğu Kodu

Bu varyant, yalnızca 1 veya 2 ön ek sembolünün bulunduğu özel durumda kullanılır kod uzunluğu 1 olan [0..255] aralığı. Diğer tüm ön ek kodu uzunlukları sıfıra eşittir.

İlk bit, simgelerin sayısını gösterir:

int num_symbols = ReadBits(1) + 1;

Sembol değerleri aşağıda verilmiştir.

Bu ilk sembol, 1 veya 8 bit kullanılarak kodlanmıştır. is_first_8bits Aralık, sırasıyla [0..1] veya [0..255] şeklindedir. İkinci sembolü (varsa), her zaman [0..255] aralığında olduğu varsayılır ve 8 bit kullanabilirsiniz.

int is_first_8bits = ReadBits(1);
symbol0 = ReadBits(1 + 7 * is_first_8bits);
code_lengths[symbol0] = 1;
if (num_symbols == 2) {
  symbol1 = ReadBits(8);
  code_lengths[symbol1] = 1;
}

Bu iki simge farklı olmalıdır. Yinelenen simgelere izin verilir verimsizdir.

Not: Diğer bir özel durum da tüm önek kodu uzunluklarının sıfır (sıfır) olmasıdır. önek kodu ekleyin). Örneğin, mesafe için bir önek kodu aşağıdaki durumlarda boş olabilir: geriye dönük referans yoktur. Benzer şekilde, alfa, kırmızı ve aynı meta önek kodu içinde tüm pikseller üretilirse mavi boş olabilir kullanmanızı öneririz. Ancak bu durumun özel olarak ele alınması gerekmez çünkü boş önek kodları, tek sembollü 0 simgesi içeren kodlar şeklinde kodlanabilir.

Normal Kod Uzunluğu Kodu

Önek kodunun kod uzunlukları 8 bite sığar ve aşağıdaki gibi okunur. İlk olarak, num_code_lengths, kod uzunluklarının sayısını belirtir.

int num_code_lengths = 4 + ReadBits(4);

Kod uzunlukları ise ön ek kodları kullanılarak kodlanır; alt düzey kod uzunluklar, code_length_code_lengths, önce okunması gerekiyor. Bunların geri kalan code_length_code_lengths (kCodeLengthCodeOrder talimatına göre) sıfırlardır.

int kCodeLengthCodes = 19;
int kCodeLengthCodeOrder[kCodeLengthCodes] = {
  17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
int code_length_code_lengths[kCodeLengthCodes] = { 0 };  // All zeros
for (i = 0; i < num_code_lengths; ++i) {
  code_length_code_lengths[kCodeLengthCodeOrder[i]] = ReadBits(3);
}

Sonra, ReadBits(1) == 0 ise maksimum farklı okuma sembolü sayısı (max_symbol) her simge türü (A, R, G, B ve mesafe) için alfabe boyutu:

  • G kanalı: 256 + 24 + color_cache_size
  • Diğer değişmez değerler (A, R ve B): 256
  • Mesafe kodu: 40

Aksi takdirde şu şekilde tanımlanır:

int length_nbits = 2 + 2 * ReadBits(3);
int max_symbol = 2 + ReadBits(length_nbits);

max_symbol, sembol türü için alfabenin boyutundan büyükse bit akışı geçersiz.

Daha sonra code_length_code_lengths öğesinden bir önek tablosu oluşturulur ve en çok max_symbol kod uzunluğunda olabilir.

  • [0..15] kod, sabit kod uzunluklarını belirtir.
    • 0 değeri, hiçbir sembolün kodlanmadığı anlamına gelir.
    • [1..15] değerleri, ilgili kodun bit uzunluğunu belirtir.
  • Kod 16, sıfır olmayan önceki değeri [3,.6] kez tekrarlar, yani 3 + ReadBits(2) defa. Kod 16, sıfır olmayan bir değerden önce kullanılırsa değer gönderildiyse 8 değeri tekrarlanır.
  • Kod 17, sıfır uzunluğunda [3..10], yani 3 + ReadBits(3) kez bir seri yayar.
  • Kod 18, sıfır uzunluğunda bir seri yayar [11..138], yani 11 + ReadBits(7) defa.

Kod uzunlukları okunduktan sonra, her sembol türü (A, R, G, B ve mesafe), ilgili alfabe boyutları kullanılarak oluşturulur.

Normal Kod Uzunluğu Kodu tam bir karar ağacını, yani Sıfır olmayan tüm kodlar için 2 ^ (-length) tam olarak bir olmalıdır. Bununla birlikte, bu kuralın bir istisnası vardır: Yaprak düğümünün bulunduğu tek yapraklı düğüm ağacı değer 1 ile işaretlenir ve diğer değerler 0 olarak işaretlenir.

6.2.2 Meta Önek Kodlarının Kodunu Çözme

Daha önce de belirtildiği gibi bu biçim, bloklarından oluşur. Meta ön ek kodları, hangi dizinlerin resmin farklı bölümlerinde kullanılacak ön ek kodları.

Meta önek kodları, yalnızca resim ARGB resminin rolü

Meta ön ek kodları için, 1 bit ile belirtilen iki olasılık vardır. değer:

  • Bu bit sıfırsa her yerde yalnızca bir meta ön ek kodu kullanılır resim. Başka veri saklanmaz.
  • Bu bit bir bitse resimde birden çok meta önek kodu kullanılır. Bu meta önek kodları bir entropi resmi (aşağıda açıklanmıştır) olarak saklanır.

Bir pikselin kırmızı ve yeşil bileşenleri ARGB resminin belirli bir bloğunu kullanın.

Entropi Resmi

Entropi resmi, anahtar kelimenin farklı kısımlarında hangi ön ek kodların kullanıldığını görüntüsüdür.

İlk 3 bit prefix_bits değerini içerir. Entropinin boyutları görüntü, prefix_bits kaynağından türetilir:

int prefix_bits = ReadBits(3) + 2;
int prefix_image_width =
    DIV_ROUND_UP(image_width, 1 << prefix_bits);
int prefix_image_height =
    DIV_ROUND_UP(image_height, 1 << prefix_bits);

Bu örnekte DIV_ROUND_UP, daha önce tanımlandığı gibidir.

Sonraki bitler, genişliği prefix_image_width ve yüksekliği olan bir entropi resmi içerir prefix_image_height.

Meta Önek Kodlarının Yorumlanması

ARGB resmindeki ön ek kodu gruplarının sayısı, entropi resmindeki en büyük meta ön ek kodu:

int num_prefix_groups = max(entropy image) + 1;

Burada max(entropy image), entropi resmidir.

Her ön ek kodu grubu beş ön ek kodu içerdiğinden, öneklerin toplam sayısı kodlar:

int num_prefix_codes = 5 * num_prefix_groups;

ARGB resmindeki bir piksel (x, y) göz önüne alındığında, kodlardan birini seçin:

int position =
    (y >> prefix_bits) * prefix_image_width + (x >> prefix_bits);
int meta_prefix_code = (entropy_image[position] >> 8) & 0xffff;
PrefixCodeGroup prefix_group = prefix_code_groups[meta_prefix_code];

Burada PrefixCodeGroup yapısının var olduğunu varsaydığımız beş ön ek kodundan oluşan bir kümeyi temsil eder. Ayrıca, prefix_code_groups, PrefixCodeGroup (num_prefix_groups boyutunda).

Ardından kod çözücü, pikselin kodunu çözmek için prefix_group ön ek kod grubunu kullanır (x, y), "Entropi Kodlu Resmin Kodunu Çözme" bölümünde açıklandığı gibi Veri".

6.2.3 Entropi Kodlu Resim Verilerinin Kodunu Çözme

Resimdeki geçerli konum (x, y) için kod çözücü ilk olarak karşılık gelen önek kodu grubuna dokunun (son bölümde açıklandığı şekilde). Raporda önek kod grubunda, piksel aşağıdaki gibi okunur ve kodu çözülür.

Daha sonra, ön ek kodu 1'i kullanarak bit akışından S simgesini okuyun. S'nin 0 - aralığındaki herhangi bir tam sayı (256 + 24 + color_cache_size- 1).

S'nin yorumlanması değerine bağlıdır:

  1. Eğer S < 256
    1. Yeşil bileşen olarak S kullanın.
    2. Ön ek kodu 2'yi kullanarak bit akışından kırmızıyı okuyun.
    3. Ön ek kodu 3'ü kullanarak bit akışından maviyi okuyun.
    4. Ön ek kodu 4'ü kullanarak bit akışından alfayı okuyun.
  2. S >= 256 ve S < 256 + 24
    1. Uzunluk ön eki kodu olarak S - 256 değerini kullanın.
    2. Bit akışından gelen uzunluk için ekstra bitleri okuyun.
    3. Uzunluk öneki kodundan ve bir veri vardır.
    4. Ön ek kodu 5'i kullanarak bit akışından mesafe ön eki kodunu okuyun.
    5. Bit akışından uzaklık için ekstra bitleri okuyun.
    6. Mesafe önek kodundan geriye dönük referans mesafe D'yi belirleme ve ekstra bitler okunur.
    7. L piksellerini (tarama satırı sırasına göre) başlayan piksel dizisinden kopyala eksi D piksel olarak görünür.
  3. S >= 256 + 24 ise
    1. Renk önbelleğine dizin olarak S - (256 + 24) değerini kullanın.
    2. Bu dizindeki renk önbelleğinden ARGB rengi alın.

7 Biçimin Genel Yapısı

Aşağıda, Artırılmış Backus-Naur Formu (ABNF) biçiminde bir görünüm verilmiştir RFC 5234 RFC 7405. Tüm ayrıntıları kapsamaz. Resmin sonu (EOI) yalnızca örtülü olarak piksel sayısı (image_width * image_height) olarak kodlanır.

*element değerinin, element değerinin 0 veya daha fazla kez tekrarlanabileceği anlamına geldiğini unutmayın. 5element element değerinin tam olarak 5 kez tekrarlandığı anlamına gelir. %b, ikilik bir değeri temsil eder.

7.1 Temel Yapı

format        = RIFF-header image-header image-stream
RIFF-header   = %s"RIFF" 4OCTET %s"WEBPVP8L" 4OCTET
image-header  = %x2F image-size alpha-is-used version
image-size    = 14BIT 14BIT ; width - 1, height - 1
alpha-is-used = 1BIT
version       = 3BIT ; 0
image-stream  = optional-transform spatially-coded-image

7.2 Dönüşümlerin Yapısı

optional-transform   =  (%b1 transform optional-transform) / %b0
transform            =  predictor-tx / color-tx / subtract-green-tx
transform            =/ color-indexing-tx

predictor-tx         =  %b00 predictor-image
predictor-image      =  3BIT ; sub-pixel code
                        entropy-coded-image

color-tx             =  %b01 color-image
color-image          =  3BIT ; sub-pixel code
                        entropy-coded-image

subtract-green-tx    =  %b10

color-indexing-tx    =  %b11 color-indexing-image
color-indexing-image =  8BIT ; color count
                        entropy-coded-image

7.3 Resim Verilerinin Yapısı

spatially-coded-image =  color-cache-info meta-prefix data
entropy-coded-image   =  color-cache-info data

color-cache-info      =  %b0
color-cache-info      =/ (%b1 4BIT) ; 1 followed by color cache size

meta-prefix           =  %b0 / (%b1 entropy-image)

data                  =  prefix-codes lz77-coded-image
entropy-image         =  3BIT ; subsample value
                         entropy-coded-image

prefix-codes          =  prefix-code-group *prefix-codes
prefix-code-group     =
    5prefix-code ; See "Interpretation of Meta Prefix Codes" to
                 ; understand what each of these five prefix
                 ; codes are for.

prefix-code           =  simple-prefix-code / normal-prefix-code
simple-prefix-code    =  ; see "Simple Code Length Code" for details
normal-prefix-code    =  ; see "Normal Code Length Code" for details

lz77-coded-image      =
    *((argb-pixel / lz77-copy / color-cache-code) lz77-coded-image)

Aşağıda olası bir dizi örnek verilmiştir:

RIFF-header image-size %b1 subtract-green-tx
%b1 predictor-tx %b0 color-cache-info
%b0 prefix-codes lz77-coded-image