Jyrki Alakuijala, Ph.D., 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. Toplu verilerin sıkıştırılması için sıralı veri sıkıştırma (LZ77) için evrensel bir algoritma, önek kodlama ve renk önbelleği kullanılır. PNG'den daha hızlı kod çözme hızlarının yanı sıra günümüzün PNG biçimiyle elde edilebilenden %25 daha yoğun sıkıştırma elde edildiği gösterilmiştir.
1 Giriş
Bu belgede, kayıpsız WebP resminin sıkıştırılmış veri gösterimi açıklanmaktadı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, bit akışlarını tanımlamak için C programlama dili söz dizimini yoğun olarak kullanırız ve bit okuma işlevi ReadBits(n)
olduğunu varsayıyoruz. Baytlar, onları içeren akıştaki doğal sırada okunur ve her baytın bitleri en az anlamlı bit öncelikli sırada okunur. Aynı anda birden fazla bit okunduğunda tam sayı, orijinal verilerden orijinal sırada oluşturulur. Döndürülen tam sayının en önemli bitleri, orijinal verilerin en önemli bitleridir. Dolayısıyla,
ifade
b = ReadBits(2);
aşağıdaki iki ifadeyle 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. Tam bir ARGB pikseli, 32 bitten oluşan imzalanmamış bir tam sayı olan uint32 adlı bir türle temsil edilir. Dönüşümlerin davranışını gösteren kodda bu değerler aşağıdaki bitlerde kodlanır: alfa 31..24 bitlerinde, kırmızı 23..16 bitlerinde, yeşil 15..8 bitlerinde ve mavi 7..0 bitlerinde. Ancak, biçimin uygulamalarında dahili olarak başka bir gösterim kullanılabilir.
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 Adlandırma
- ARGB
- Alfa, kırmızı, yeşil ve mavi değerlerden oluşan bir piksel değeri.
- ARGB resmi
- ARGB pikselleri içeren iki boyutlu bir dizi.
- renk önbelleği
- Son kullanılan renkleri daha kısa kodlarla çağırabilmek için depolamak üzere küçük bir karma adresli dizi.
- 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
- Renk bileşenlerinin korelasyonlarıyla ilgili veriler içeren iki boyutlu bir alt çözünürlüklü resim.
- mesafe eşleme
- LZ77 mesafelerini, iki boyutlu yakınlıktaki pikseller için en küçük değerlere sahip olacak şekilde değiştirir.
- entropi resmi
- Resimdeki ilgili karede hangi entropi kodlamasının kullanılacağını belirten iki boyutlu bir alt çözünürlüklü resimdir. Yani her piksel bir meta ön ek kodudur.
- 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 ek tablosundaki bir öğeyi dizine ekleyen küçük bir tam sayı (16 bit'e kadar).
- Tahmin resmi
- Resimdeki belirli bir kare için hangi mekansal öngörücünün kullanıldığını gösteren iki boyutlu bir alt çözünürlük resmi.
- önek kodu
- Daha az sayıda bitin kullanıldığı entropi kodlaması yapmanın klasik yolu bakın.
- önek kodlaması
- Daha büyük tam sayıları entropi kodlamanın bir yoludur. Bu yöntemde, entropi kodu kullanılarak tam sayının birkaç biti kodlanır ve kalan bitler ham olarak kodlanır. Bu da entropi kodlarının tanımlarının ne kadar küçük olsa da simge aralığı geniş olduğundan emin olun.
- satır tarama sırası
- Piksellerden oluşan bir işleme sırası (soldan sağa ve yukarıdan aşağıya), pikselden uzaklaştırın. Bir satır tamamlandığında bir sonraki satırın sol sütunundan devam edin.
3 RIFF Başlığı
Üstbilginin başında RIFF kapsayıcısı bulunur. Bu, aşağıdaki 21 bayttan oluşur:
- Dize 'RIFF'.
- Yığın uzunluğunun tam boyutu olan 32 bitlik küçük son değeri kontrol edilen parçasını görebilirsiniz. Bu değer normalde yükü boyutuna eşittir (dosya boyutu eksi 8 bayt: "RIFF" tanımlayıcısı için 4 bayt ve değerin kendisini depolamak için 4 bayt).
- "WEBP" dizesi (RIFF kapsayıcı adı).
- Dize: "VP8L" (Kayıpsız kodlanmış resim verileri için dört kod).
- Kaybetsiz akıştaki bayt sayısının küçük endian, 32 bitlik değeri.
- 1 bayt 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 şekilde 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ği için 14 bit hassasiyet, kayıpsız WebP resminin maksimum boyutunu 16.384x16.384 piksel ile sınırlandırır.
alpha_is_used biti yalnızca bir ipucudur ve kod çözmeyi etkilememelidir. Resimdeki tüm alfa değerleri 255 olduğunda 0, aksi takdirde 1 olarak ayarlanmalıdır.
int alpha_is_used = ReadBits(1);
version_number, 0 olarak ayarlanması gereken 3 bitlik bir koddur. Diğer tüm değerler hata olarak kabul edilmelidir.
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. Dönüşümler yalnızca ana düzey ARGB resmi için kullanılır; alt çözünürlüklü resimlerde (renk dönüştürme resmi, entropi resmi ve tahmin resmi) dönüşüm yoktur, dönüşümlerin sonunu belirten 0 bit bile yoktur.
Genellikle bir kodlayıcı, artık görüntüdeki Shannon entropisi azaltmak için bu dönüştürme işlemlerini kullanır. Ayrıca, dönüşüm verilerine entropi minimizasyonuna göre karar verilebilir.
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üştürme 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, bit akışından okundukları ters sırada (yani sondan başa) uygulanır.
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, kullanılacak tahmin türünü belirler. 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 tekniklerle kodlanır.
İki boyutlu dizine ekleme işleminde blok sütun sayısı (transform_width
) kullanılır. 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, mevcut piksel değeri, değerleri zaten bilinen bir veya daha fazla komşu pikselden tahmin edilir.
Mevcut pikselin (P) komşu piksellerini (TL, T, TR ve L) aşağıdaki gibi seçtik:
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, 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;
}
Seçilen öngörücü 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 her ARGB bileşeni için aşağıdaki gibi gerçekleştirilir:
// 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. Bu piksellerin modundan [0..13] bağımsız olarak bir öngörücü dönüştürme varsa resmin en soldaki üst pikseli için tahmin edilen değer 0xff000000, en üst satırdaki tüm pikseller L-piksel, en soldaki sütundaki tüm pikseller ise T-piksel olur.
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ğerin her kanalının kodlanmış artık değere eklenmesi ile elde edilir.
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üştürme işleminin amacı, her pikselin R, G ve B değerlerinin korelasyonunu kaldırmaktır. Renk dönüştürme işlemi, yeşil (G) değerini olduğu gibi tutar, kırmızı (R) değerini yeşil değere göre, mavi (B) değerini ise yeşil ve ardından kırmızı değere göre dönüştürür.
Tahminci dönüştürme işleminde olduğu gibi, önce resim bloklara bölünür 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üştürme işlemi, bir renk dönüştürme deltası tanımlanarak yapılır. Renk dönüştürme deltası, belirli bir bloktaki tüm pikseller için aynı olan ColorTransformElement
değerine bağlıdır. Delta,
sağlayabilirsiniz. Ters renk dönüşümü, yalnızca bu deltaları ekler.
Renk dönüştürme işlevi aşağıdaki şekilde 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. İşaretli değer, 8 bitlik ikilik tamamlayıcı sayı olarak yorumlanmalıdır (yani: uint8 aralığı [128..255], dönüştürülmüş int8 değerinin [-128..-1] aralığıyla eşlenir).
Çarpma işlemi daha fazla kesinlik (en az 16 bit ile) hassasiyeti). Kaydırma işleminin işaret uzantısı özelliği burada önemli değildir; sonuçtan yalnızca en düşük 8 bit kullanılır ve bu bitlerde işaret uzantısı kaydırma ve işaretsiz kaydırma birbirine tutarlıdır.
Şimdi, renk dönüştürme verilerinin içeriğini açıklıyoruz. Böylece kod çözme işlemi, ters renk dönüştürme işlemini uygulayabilir ve orijinal kırmızı ve mavi değerlerini kurtarabilir. Renk dönüştürme verilerinin ilk 3 biti, tahminci dönüştürme gibi resim bloğunun genişliğini ve yüksekliğini bit sayısı olarak içerir:
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 ColorTransformElement
'cte'
, alfa bileşeni 255
, kırmızı bileşeni cte.red_to_blue
, yeşil bileşeni cte.green_to_blue
ve mavi bileşeni cte.green_to_red
olan bir alt çözünürlüklü resimdeki piksel olarak değerlendirilir.
Kod çözme sırasında, blokların ColorTransformElement
örneğinin kodu çözülür ve ters renk dönüştürme işlemi, piksellerin ARGB değerlerine uygulanır. Daha önce de belirtildiği gibi, bu ters renk dönüşümü yalnızca kırmızı ve mavi kanallara ColorTransformElement
değerleri ekler. Alfa ve yeşil kanallar 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. Bu dönüştürme işlemiyle ilişkili veri yok. 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;
}
Renk dönüştürme işlemi kullanılarak modellenebildiği için bu dönüştürme işlemi gereksizdir ancak burada ek veri olmadığından yeşil çıkarma dönüştürme işlemi, tam teşekküllü bir renk dönüştürme işlemine kıyasla daha az bit kullanılarak kodlanabilir.
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, WebP kayıpsız kodlamasında benzer ancak daha dinamik bir kavram (renk önbelleği) bulunduğundan bunu özellikle palet dönüşümü olarak adlandırmıyoruz.)
Renk dizine ekleme dönüşümü, görüntüsüdür. Bu sayı bir eşiğin (256) altındaysa bu ARGB değerlerinin bir dizisi oluşturulur. Bu dizi daha sonra piksel değerlerini ilgili dizinle değiştirmek için kullanılır: Piksellerin yeşil kanalı dizinle değiştirilir, tüm alfa değerleri 255'e, tüm kırmızı ve mavi değerler ise 0'a ayarlanır.
Dönüşüm verileri, renk tablosu boyutunu ve renk tablosundaki girişleri içerir. 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çimi 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, resim entropisi azaltmak için her zaman çıkarma kodlamasıyla oluşturulur. Deltalar
palet renklerinin entropileri genellikle renklerden çok daha azdır
Bu da daha küçük resimlerde önemli tasarruf sağlar. Kod çözme işleminde, önceki renk bileşeni değerleri her ARGB bileşenine ayrı ayrı eklenip sonucun en az anlamlı 8 biti depolanarak renk tablosundaki her nihai renk elde edilebilir.
Resim için ters dönüşüm, basitçe piksel değerlerinin (bu, 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 bu değerden büyükse argb renk değeri 0x00000000 (şeffaf siyah) olarak ayarlanmalıdır.
Renk tablosu küçük olduğunda (16 renge eşit veya daha az) birkaç piksel tek bir pikselde gruplandırılır. Piksel paketleme, birkaç (2, 4 veya 8) pikseli tek bir piksele sığdırır ve sırasıyla resim genişliğini azaltır. Piksel birleştirme, komşu piksellerin daha verimli bir ortak dağıtım entropi kodlamasına olanak tanır ve entropi koduna aritmetik kodlamaya benzer bazı avantajlar sağlar 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 birleştirildiğini ve her pikselin [0..15] aralığına sahip olduğunu gösterir. 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 aşağıdaki şekilde paketlenir:
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: x ≡ 0 (mod 4) olan her x değeri için x'deki yeşil değer, x / 4'teki yeşil değerin en az anlamlı 2 bitine yerleştirilir ve x + 1 ile x + 3 arasındaki yeşil değerler, x / 4'teki yeşil değerin daha anlamlı bitlerine göre yerleştirilir.width_bits
= 3: x ≡ 0 (mod 8) olan her x değeri için x'deki yeşil değer, x / 8'deki yeşil değerin en az anlamlı bitine yerleştirilir ve x + 1 ile x + 7 arasındaki yeşil değerler, x / 8'deki yeşil değerin daha anlamlı bitlerine göre yerleştirilir.
Bu dönüşüm okunduktan sonra image_width
, width_bits
tarafından alt örneklenir. Bu
sonraki dönüşümlerin boyutunu etkiler. Yeni boyut, daha önce tanımlandığı gibi DIV_ROUND_UP
kullanılarak hesaplanabilir.
image_width = DIV_ROUND_UP(image_width, 1 << width_bits);
5 Resim Verisi
Resim verileri, tarama satırı sırasına göre bir piksel değeri dizisidir.
5.1 Resim Verilerinin Rolleri
Resim verilerini beş farklı rolde kullanırız:
- ARGB resmi: Resmin gerçek piksellerini depolar.
- Entropi resmi: Meta ön ek kodlarını depolar ("Meta Ön Ek Kodlarının Kod Çözülmesi" bölümüne bakın).
- Tahminci görüntüsü: Tahminci dönüşümü için meta verileri depolar (bkz. "Tahmin Aracı Dönüşümü").
- Renk dönüştürme resmi: Resmin farklı blokları için
ColorTransformElement
değerleri ("Renk Dönüştürme" bölümünde tanımlanır) kullanılarak oluşturulur. - Renk dizine ekleme resmi: Renk dizine ekleme dönüştürme işleminin meta verilerini depolayan
color_table_size
boyutunda bir dizi (256'a kadar ARGB değeri) ("Renk dizine ekleme dönüştürme" bölümüne bakın).
5.2 Resim Verilerinin Kodlanması
Resim verilerinin kodlanması rolünden bağımsızdır.
Resim önce sabit boyutlu bir blok grubuna (genellikle 16x16 blok) bölünür. Bu blokların her biri kendi entropi kodları kullanılarak modellenir. Ayrıca, birkaç blok aynı entropi kodunu paylaşabilir.
Mantık: Entropy kodu depolamak maliyetlidir. Maliyet en aza indirebilir istatistiksel olarak benzer blokların bir entropi kodu paylaşması ve dolayısıyla bu kodu depolaması yalnızca bir kez. Örneğin, bir kodlayıcı, benzer blokları istatistiksel özelliklerini kullanarak gruplandırarak veya resmi kodlamak için gereken toplam bit miktarını azalttığında rastgele seçilen bir çift kümeyi tekrar tekrar birleştirerek bulabilir.
Her piksel, aşağıdaki üç olası yöntemden biri kullanılarak kodlanır:
- Ön ek kodlu değişmezler: Her kanal (yeşil, kırmızı, mavi ve alfa) bağımsız olarak entropi kodlanır.
- LZ77 geriye dönük referansı: Bir piksel dizisi, resim.
- 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 Önek Kodlu Değişkenler
Piksel, yeşil, kırmızı, mavi ve alfa (bu sırayla) ön ek kodlu değerler olarak depolanır. Ayrıntılı bilgi için Bölüm 6.2.3'e bolca fırsat sunuyor.
5.2.2 LZ77 Geriye Dönük Referans
Geriye dönük referanslar, uzunluk ve mesafe kodu çiftlerinden oluşur:
- 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ırken ek bitler olduğu 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, farklı değer aralıkları depolamak için kullanılan ön ek kodları ve ek bitler gösterilmektedir.
Değer aralığı | Ön ek 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 değer (uzunluk veya mesafe) elde etmek için kullanılan sözde kod aşağıdaki gibidir:
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 de belirtildiği gibi, mesafe kodu, daha önce görmüş olduğunuz bir pikselin konumunu belirten ve piksellerin kopyalanacağı bir sayıdır. 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 çizgisine göre belirtir. farkı 120'ye çıkarır.
En küçük mesafe kodları [1..120] özeldir ve geçerli pikselin yakın çevresi için ayrılmıştır. 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. [Böyle piksellerin toplam 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)
uzaklığını
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 üst pikseli gösterir.
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 yakın zamanda 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 önbelleği kodları aşağıdaki gibi saklanır. İlk olarak, renk önbelleğinin kullanılıp kullanılmadığını gösterir. Bu bit 0 ise renk önbelleği kodu yoktur ve yeşil simgelerin ve uzunluk ön ek kodlarının kodunu çözen ön ek kodunda iletilmez. 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ği (1 <<
color_cache_code_bits
) boyutunu tanımlar. color_cache_code_bits
için izin verilen değer aralığı [1..11]'dir. 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şte bir ARGB rengi saklanır. Renkler, (0x1e35a7bd * color) >> (32 -
color_cache_code_bits)
dizine eklenerek aranır. Renk önbelleği yalnızca bir kez arandığından çakışma çözümü yoktur.
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, kanonik ö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:
- Önek kodlarının kodunu çözme ve oluşturma.
- Meta ön ek kodları.
- Entropi kodlu resim verileri.
Her bir piksel (x, y) için, piksel ile ilişkili beş ön ek kodu vardır. 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.
- Ön ek kodu #5: Geriye dönük 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.
Ön ek kod uzunlukları iki şekilde kodlanabilir. Kullanılan yöntem 1 bitlik bir değerle belirtilir.
- Bu bit 1 ise basit kod uzunluğu kodu'dur.
- Bu bit 0 ise normal kod uzunluğu kodudur.
Her iki durumda da, akışta yer alan ancak kullanılmayan kod uzunlukları olabilir. Bu verimsiz olabilir ancak biçim nedeniyle izin verilir. Açıklanan ağaç tam bir ikili ağaç olmalıdır. Tek bir yaprak düğüm, tam bir ikili ağaç olarak kabul edilir ve basit kod uzunluğu kodu veya normal kod uzunluğu kodu kullanılarak kodlanabilir. Normal kod uzunluğu kodu kullanılarak tek bir yaprak düğüm kodlanırken, bir kod uzunluğu hariç tümü sıfırdır ve tek yaprak düğüm değeri, bu tek yaprak düğüm ağacı kullanıldığında hiçbir bit tüketilmese bile 1 uzunluğuyla işaretlenir.
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ı dolaylı olarak sıfırdır.
İlk bit, simgelerin sayısını gösterir:
int num_symbols = ReadBits(1) + 1;
Aşağıda simge değerleri 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. Varsa ikinci sembolün her zaman [0..255] aralığında olduğu ve 8 bit kullanılarak kodlandığı varsayılır.
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;
}
İki simge farklı olmalıdır. Yinelenen simgelere izin verilir verimsizdir.
Not: Tüm ön kod uzunluklarının sıfır olduğu (boş bir ön kod) durumlar da özel durumlar arasındadır. Örneğin, mesafe için bir önek kodu aşağıdaki durumlarda boş olabilir:
geriye dönük referans yoktur. Benzer şekilde, aynı meta ön ek kodundaki tüm pikseller renk önbelleği kullanılarak üretilirse alfa, kırmızı ve mavi için ön ek kodları boş olabilir. 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ı da önek kodları kullanılarak kodlanır. Öncelikle alt düzey kod uzunluklarının (code_length_code_lengths
) okunması gerekir. Bu code_length_code_lengths
değerlerinin geri kalanı (kCodeLengthCodeOrder
'daki sıraya göre) sıfırdı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);
}
Ardından, ReadBits(1) == 0
ise her simge türü (A, R, G, B ve mesafe) için okunabilen maksimum farklı simge sayısı (max_symbol
) alfabe boyutuna ayarlanır:
- 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
, simge türündeki alfabenin boyutundan büyükse bit akışı geçersizdir.
Ardından code_length_code_lengths
ile bir ön ek tablosu oluşturulur ve max_symbol
kod uzunluğuna kadar okumak için kullanılır.
- Kod [0..15], değişmez kod uzunluklarını belirtir.
- 0 değeri, kodlanmış simge olmadığı anlamına gelir.
- [1..15] değerleri, ilgili kodun bit uzunluğunu gösterir.
- 16 numaralı kod, önceki sıfır olmayan değeri [3..6] kez, yani
3 + ReadBits(2)
kez tekrar eder. Kod 16, sıfır olmayan bir değerden önce kullanılırsa değer gönderildiyse 8 değeri tekrarlanır. - 17 numaralı kod, [3..10] uzunluğunda bir sıfır dizisi, yani
3 + ReadBits(3)
kez sıfır gönderir. - 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ı kodlamalıdır. Yani sıfır olmayan tüm kodlar için 2 ^ (-length)
toplamı tam olarak bir olmalıdır. Ancak bu kuralın tek bir istisnası vardır: Tek yapraklı ağaç. Bu ağaçta, yaprak düğüm değeri 1 ile, diğer değerler ise 0 ile işaretlenir.
6.2.2 Meta Ön Ek Kodlarının Kod Çözülmesi
Daha önce de belirtildiği gibi, bu biçim, resmin farklı blokları için farklı ön ek kodlarının kullanılmasına olanak tanır. Meta ön ek kodları, hangi dizinlerin ön ek kodları kullanabilirsiniz.
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 ise resim birden fazla meta ön ek kodu kullanır. Bu meta ön ek kodları, entropi resmi olarak saklanır (aşağıda açıklanmıştır).
Bir pikselin kırmızı ve yeşil bileşenleri ARGB resminin belirli bir bloğunu kullanın.
Entropi Resmi
Entropi resmi, resmin farklı bölümlerinde hangi ön ek kodlarının kullanıldığını tanımlar.
İlk 3 bit, prefix_bits
değerini içerir. Entropy görüntüsünün boyutları prefix_bits
'ten 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 önek kodu gruplarının sayısı, entropi resminden en büyük meta önek kodu bulunarak elde edilebilir:
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 toplam ön ek kodu sayısı:
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ü, "Entropy Kodlu Görüntü Verilerinin Kodunu Çözme" bölümünde açıklandığı gibi pikselin (x, y) kodunu çözmek için ön ek kod grubu prefix_group
'ü kullanır.
6.2.3 Entropi Kodlu Resim Verilerinin Kodunu Çözme
Kod çözücü, resimdeki mevcut konum (x, y) için önce ilgili ön ek kod grubunu tanımlar (önceki bölümde açıklandığı gibi). 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
ile (256 + 24 +
color_cache_size
- 1)
aralığındaki herhangi bir tam sayı olduğunu unutmayın.
S değerinin yorumlanması, değerine bağlıdır:
- S < 256 ise
- Yeşil bileşen olarak S'yi kullanın.
- 2 numaralı ön ek kodunu kullanarak bit akışından kırmızıyı okuyun.
- 3 numaralı ön ek kodunu kullanarak bit akışından mavi rengi okuyun.
- 4 numaralı ön ek kodunu kullanarak bit akışından alfa okuma.
- S >= 256 ve S < 256 + 24
- Uzunluk ön eki kodu olarak S - 256 değerini kullanın.
- Bit akışından uzunluk için fazladan bit okuyun.
- Uzunluk ön ek kodu ve okunan ekstra bitlerden geriye referans uzunluğu L'yi belirleyin.
- Ön ek kodu 5'i kullanarak bit akışından mesafe ön eki kodunu okuyun.
- Bit akışından uzaklık için fazladan bit okuyun.
- Mesafe önek kodundan geriye dönük referans mesafe D'yi belirleme ve ekstra bitler okunur.
- Mevcut konumdan başlayıp D piksel eksik olacak şekilde piksel dizisinden L piksel (tarama satırı sırasına göre) kopyalanır.
- S >= 256 + 24 ise
- Renk önbelleğindeki dizin olarak S - (256 + 24) değerini kullanın.
- Söz konusu dizindeki renk önbelleğinden ARGB rengini 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ı içermez. Resim sonu (EOI) yalnızca piksel sayısına (image_width * image_height) dolaylı olarak kodlanır.
*element
, element
'nin 0 veya daha fazla kez tekrarlanabileceğini belirtir. 5element
element
ifadesinin 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