مواصفات تقنية WebP لتدفق البيانات بدون فقدان بيانات

جيركي ألاكويالا، دكتوراه Google, Inc., 09/03/2023

ملخص

تنسيق WebP بدون فقدان البيانات هو تنسيق صور لضغط الصور بتنسيق ARGB بدون فقدان البيانات. تشير رسالة الأشكال البيانية يخزن التنسيق بدون فقدان البيانات قيم البكسل بالضبط ويستعيدها، بما في ذلك قيم الألوان لبكسل شفافة بالكامل. يشير هذا المصطلح إلى خوارزمية عامة للسلاسل التسلسلية. يتم استخدام ضغط البيانات (LZ77) وترميز البادئة وذاكرة التخزين المؤقت للألوان ضغط البيانات المجمّعة. تم فك ترميز السرعات الأسرع من تنسيق PNG إلى جانب ضغط أكثر كثافة بنسبة 25% مقارنةً باستخدامه بتنسيق PNG اليوم.

1 مقدمة

يوضِّح هذا المستند تمثيل البيانات المضغوطة باستخدام تنسيق WebP بدون فقدان البيانات. . وهو مخصّص كمرجع مفصّل لتنفيذ تطبيقات الترميز والترميز بدون فقدان للبيانات في WebP.

في هذا المستند، نستخدم على نطاق واسع بناء جملة لغة البرمجة C لوصف تدفق البيانات البتية ونفترض وجود دالة لقراءة وحدات البت، ReadBits(n) تتم قراءة وحدات البايت بالترتيب الطبيعي للبث الذي يحتوي على ويتم قراءة وحدات بت من كل بايت بترتيب بت أولاً أقل أهمية. فعندما تتم قراءة وحدات بت متعددة في الوقت نفسه، يتم إنشاء العدد الصحيح من البيانات الأصلية بالترتيب الأصلي. أهم أجزاء البيانات المعروضة العدد الصحيح هو أيضًا أهم وحدات البت في البيانات الأصلية. وبالتالي، عبارة

b = ReadBits(2);

مع العبارتين التاليتين:

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

نفترض أنّ كل مكوّن من مكوّنات اللون، أي ألفا والأحمر والأزرق والأخضر، يتم تمثيله باستخدام بايتة 8 بت. نُعرّف النوع المقابل على أنه uint8. حاسمة يتم تمثيل بكسل ARGB بالكامل بنوع يسمى uint32، وهو علامة غير موقَّعة عدد صحيح يتكون من 32 بت. في الكود الذي يُظهر سلوك يتم تنظيم هذه القيم في وحدات البت التالية: ألفا بالبت 31..24، أحمر بوحدات بت 23..16، وأخضر 15..8، وأزرق بوحدات بت 7..0؛ وَلَكِنْ لعمليات تنفيذ التنسيق مجانية استخدام تمثيل آخر داخليًا.

بشكل عام، تحتوي صورة WebP بدون فقدان البيانات على بيانات العنوان وتحويل المعلومات بيانات الصور الفعلية. تحتوي العناوين على عرض الصورة وارتفاعها. تنسيق WebP صورة بدون فقدان البيانات يمكن أن تمر بأربعة أنواع مختلفة من التحويلات قبل بالإنتروبيا. تحتوي معلومات التحويل في بث البتات على البيانات المطلوبة لتطبيق عمليات التحويل العكسية ذات الصلة.

2 التسمية

أرغيغابايت
قيمة بكسل تتكون من قيم ألفا والأحمر والأخضر والأزرق.
صورة ARGB
مصفوفة ثنائية الأبعاد تحتوي على وحدات بكسل ARGB
ذاكرة تخزين مؤقت للألوان
صفيف صغير موجَّه إلى التجزئة لتخزين الألوان المستخدَمة مؤخرًا حتى تتمكّن من تذكُرها باستخدام رموز أقصر
صورة فهرسة الألوان
صورة أحادية الأبعاد للألوان التي يمكن فهرستها باستخدام عدد صحيح صغير (يصل إلى 256 ضمن WebP بدون فقدان البيانات).
صورة لتحويل الألوان
صورة ثنائية الأبعاد بدرجة دقة منخفضة تحتوي على بيانات عن الارتباطات بين مكوّنات اللون
ربط المسافات
تغيير مسافات LZ77 لتصبح أصغر قيم للبكسل في التقارب الثنائي الأبعاد
صورة إنتروبيا
صورة ثنائية الأبعاد لدرجة الدقة الفرعية وتشير إلى رمز القصور الحراري استخدامها في مربع خاص في الصورة، أي أن كل بكسل عبارة عن علامة تعريف رمز البادئة.
LZ77
خوارزمية لضغط النافذة منزلق تستند إلى القاموس وتُصدر إما أو تصفها كسلاسل من الرموز القديمة
رمز البادئة الوصفية
عدد صحيح صغير (يصل إلى 16 بت) يفهرس عنصرًا في جدول البادئة التعريفية .
صورة المتنبّئ
صورة ثنائية الأبعاد لدرجة الدقة الفرعية وتشير إلى المتنبئ المكاني مُستخدَمة لمربّع معيّن في الصورة
رمز البادئة
طريقة كلاسيكية لترميز القصور الحراري باستخدام عدد أقل من وحدات البت للحصول على رموز أكثر تكرارًا
ترميز البادئة
طريقة لتشفير عدد أكبر من الأعداد الصحيحة باستخدام رمز معلوماتي، حيث يتم ترميز بضعة بتات من العدد الصحيح باستخدام رمز معلوماتي ويتم ترميز البتات المتبقية بشكل خام. ويسمح ذلك بمحاولة إبقاء أوصاف رموز الترميز الإنتروبي صغيرة نسبيًا حتى عندما يكون نطاق الرموز كبيرًا.
طلب مسح ضوئي
ترتيب معالجة وحدات البكسل (من اليسار إلى اليمين ومن أعلى إلى أسفل)، بدءًا من من وحدة البكسل العلوية اليسرى. بمجرد اكتمال أحد الصفوف، يمكنك المتابعة من العمود الأيسر من الصف التالي.

3 رؤوس RIFF

تحتوي بداية الرأس على حاوية RIFF. يتألّف هذا الرمز من البكيتَين التاليتَين المكوّنتَين من 21 بايت:

  1. سلسلة 'RIFF'.
  2. قيمة 32 بت بترتيب الوحدات الأقل أهمية لطول الجزء، وهو الحجم الكامل للجزء الذي يتحكّم فيه رأس RIFF عادةً، يساوي هذا حجم حمولة البيانات (حجم الملف مطروحًا منه 8 بايت: 4 بايت لـ "RIFF" 4 بايت لتخزين القيمة نفسها).
  3. سلسلة "WEBP" (اسم حاوية RIFF).
  4. السلسلة "VP8L" (FourCC لبيانات الصور التي تم ترميزها بدون فقدان)
  5. قيمة صغيرة 32 بت لعدد وحدات البايت في بث بدون فقدان البيانات.
  6. توقيع 1 بايت 0x2f.

أول 28 بت من مصدر البيانات البت هي يحدد عرض الصورة وارتفاعها. يتم فك ترميز العرض والارتفاع كأرقام صحيحة تبلغ 14 بت على النحو التالي:

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

تؤدي دقة 14 بت لعرض الصورة وارتفاعها إلى الحد من الحد الأقصى لحجم صورة WebP بدون فقدان التفاصيل إلى 16384 × 16384 بكسل.

البت alpha_is_used هو تلميح فقط، ولن يؤثر في فكّ الترميز. يجب ضبطها على 0 عندما تكون جميع قيم شفافية الصورة 255، و1 في الحالات الأخرى.

int alpha_is_used = ReadBits(1);

رقم_الإصدار هو رمز مكون من 3 بت يجب ضبطه على القيمة 0. يجب أن تكون أي قيمة أخرى على أنه خطأ.

int version_number = ReadBits(3);

4 تحويلات

وعمليات التحويل هي عمليات معالجة عكسية لبيانات الصورة يمكن أن تقلل القصور الرمزي المتبقي من خلال نمذجة الارتباطات المكانية واللونية. ويمكن أن يؤدي ذلك إلى تكثيف عملية الضغط النهائية.

يمكن أن تمر الصورة بأربعة أنواع من التحويلات. يشير بت واحد إلى حدوث تحويل. ويُسمح باستخدام كل تحويل مرة واحدة فقط. لا يتم استخدام عمليات التحويل إلا للصورة ARGB ذات المستوى الرئيسي، ولا تحتوي الصور ذات الدقة المنخفضة (صورة تحويل الألوان وصورة معلومات الانتروبي وصورة المتوقّع) على عمليات تحويل، ولا حتى القيمة 0 التي تشير إلى نهاية عمليات التحويل.

ويستخدم عادةً برنامج ترميز هذه التحويلات لخفض قصور شانون. في الصورة المتبقية. كما يمكن تحديد بيانات التحويل بناءً على القصور .

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

// Decode actual image data (Section 5).

إذا كان هناك تحويل، يحدّد البتّان التاليان نوع التحويل. هناك أربعة أنواع من التحويلات.

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

نوع التحويل متبوعًا ببيانات التحويل. تحتوي بيانات التحويل على المعلومات المطلوبة لتطبيق التحويل العكسي، وتعتمد على نوع التحويل. يتم تطبيق التحويلات العكسية بالترتيب العكسي الذي تتم قراءتها من البث المباشر للبيانات، أي آخر جزء أولاً.

بعد ذلك، نصف بيانات التحويل لأنواع مختلفة.

4.1 تحويل أداة التوقّع

ويمكن استخدام تحويل المتنبئ للحد من القصور من خلال استغلال التي غالبًا ما تكون وحدات البكسل المجاورة مرتبطة ببعضها. وفي تحويل المتنبئ، تتنبأ بقيمة البكسل الحالية من وحدات البكسل التي سبق فك ترميزها (في سطر البحث). ترتيب) ويتم ترميز القيمة المتبقية فقط (الفعلية - المتنبأ بها). الأخضر أي مكون من 14 تنبؤًا يتم استخدامه في البكسل كتلة معينة من صورة ARGB. يحدِّد وضع التوقّع نوع المحاولة التي سيتم استخدامها. نقسم الصورة إلى مربّعات، وتستخدم كلّ وحدات البكسل في أحد المربّعات وضع التنبؤ نفسه.

تحدِّد أول 3 بتات من بيانات التوقّع عرض الكتلة وارتفاعها بعدد البتات.

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);

تحتوي بيانات التحويل على وضع التنبؤ لكل كتلة من الصورة. أُنشأها جون هنتر، الذي كان متخصصًا هي صورة ذات دقة فرعية يحدد فيها المكون الأخضر للبكسل يتم استخدام المؤشرات الأربعة عشر لجميع وحدات البكسل البالغ عددها block_width * block_height داخل كتلة معينة من صورة ARGB. تم ترميز هذه الصورة ذات درجة الدقة الفرعية باستخدام الأساليب نفسها الموضّحة في الفصل 5.

يُستخدم عدد أعمدة القالب، transform_width، في الوضع الثنائي الأبعاد. الفهرسة. بالنسبة للبكسل (س، ص)، يمكن حساب كتلة الفلاتر المعنية العنوان بواسطة:

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

هناك 14 وضعًا مختلفًا للتوقّع. في كل وضع من أوضاع التنبؤ، يتم التنبؤ بقيمة البكسل من وحدة بكسل مجاور واحدة أو أكثر تكون قيمها معروفة بالفعل.

اخترنا وحدات البكسل المجاورة (TL وT وTR وL) للوحدة الحالية (P) على النحو التالي:

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

حيث يشير TL إلى أعلى يمين، ويشير T إلى أعلى، ويشير TR إلى أعلى يمين، ويشير L إلى يمين. في وقت توقّع قيمة لوحدة البكسل P، سبق أن تمت معالجة جميع وحدات البكسل O وTL وT وTR وL، وتكون وحدة البكسل P وجميع وحدات البكسل X غير معروفة.

استنادًا إلى وحدات البكسل المجاورة السابقة، يتم تحديد أوضاع التوقّع المختلفة على النحو التالي.

الوضع القيمة المتوقّعة لكل قناة من وحدات البكسل الحالية
0 0xff000000 (يمثّل اللون الأسود الخالص في ARGB)
1 L
2 T
3 تركيا
4 قائد فريق
5 المتوسط2(المتوسط2(L, TR), T)
6 Average2(L, TL)
7 متوسطة 2(لتر، T)
8 Average2(TL, T)
9 متوسط2(T, TR)
10 Average2(Avg2(L, TL), Average2(T, TR))
11 Select(L, T, TL)
12 ClampAddSubtractFull(L, T, TL)
13 ClampAddSubtractHalf(Average2(L, T), TL)

يتم تحديد Average2 على النحو التالي لكل مكوّن ARGB:

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

يتم تعريف أداة التوقّع "اختيار" على النحو التالي:

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 وClampAddSubtractHalf. لكل مكوّن ARGB على النحو التالي:

// 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);
}

هناك قواعد معالجة خاصة لبعض وحدات بكسل الحدود. إذا كان هناك فإن تحويل المتنبئ، بصرف النظر عن الوضع [0..13] لهذه البكسلات، والقيمة المتوقعة للبكسل العلوي الأيسر من الصورة هي 0xff000000، وحدات البكسل في الصف العلوي هي L-pixel، وتكون جميع وحدات البكسل في العمود الموجود في أقصى اليسار T-pixel.

تكون معالجة بكسل TR للبكسل في العمود الموجود في أقصى اليمين استثنائية. يتم توقّع وحدات البكسل في العمود الأيمن باستخدام الأوضاع [0..13]، تمامًا مثل وحدات البكسل التي لا تكون على الحدود، ولكن يتم استخدام وحدات البكسل الأيسر في الصف نفسه الذي يتضمّن وحدات البكسل الحالية كوحدات بكسل TR بدلاً من ذلك.

يتم الحصول على قيمة البكسل النهائية من خلال إضافة كل قناة من القيمة المتنبأ بها. إلى القيمة المتبقية المشفرة.

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 تحويل الألوان

الهدف من تحويل اللون هو ديكور قيم R وG وB لكل منها pixel. تحافظ عملية تحويل الألوان على قيمة اللون الأخضر (G) كما هي، وتحوّل قيمة اللون الأحمر (R) استنادًا إلى قيمة اللون الأخضر، وتحوّل قيمة اللون الأزرق (B) استنادًا إلى قيمة اللون الأخضر ثم إلى قيمة اللون الأحمر.

وكما هو الحال مع تحويل المتنبئ، تُقسم الصورة أولاً إلى ويتم استخدام وضع التحويل نفسه لجميع وحدات البكسل في الكتلة. بالنسبة كل كتلة، هناك ثلاثة أنواع من عناصر تحويل الألوان.

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

ويتم تحويل اللون الفعلي عن طريق تحديد دلتا تحويل اللون. تشير رسالة الأشكال البيانية تعتمد دلتا تحويل اللون على ColorTransformElement، وهي نفسها لجميع وحدات البكسل في كتلة معينة. ويتم طرح الدلتا أثناء تحويل الألوان. ومن ثم، يضفي تحويل اللون العكسي تلك الدلتا فقط.

يتم تعريف دالة تحويل الألوان على النحو التالي:

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 باستخدام عدد صحيح 8 بت يحمل علامة ويمثّل رقمًا بنقطة ثابتة 3.5 وقناة ألوان RGB 8 بت تحمل علامة (c) [-128..127] ويتم تعريفه على النحو التالي:

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

إحالة ناجحة من التمثيل غير الموقع ذو الإصدار 8 بت (uint8) إلى النموذج الموقَّع على 8 بت يجب إدخال واحد (int8) قبل طلب ColorTransformDelta(). يجب تفسير القيمة التي تحمل علامة كعدد تكميلي ثنائي بسعة 8 بت (أي أنّه يتم ربط نطاق uint8 [128..255] بنطاق [-128..-1] لقيمة int8 المحوَّلة).

يجب إجراء الضرب بدقة أكبر (باستخدام 16 بت على الأقل الدقة). لا يهم خاصية إضافة العلامة الخاصة بعملية shift هنا؛ يتم استخدام أقل 8 بتات فقط من النتيجة، وفي هذه البتات، تبديل إضافة العلامة والنقل غير الموقع متسقًا مع بعضهما البعض.

الآن، نصف محتويات بيانات تحويل الألوان بحيث يمكن تطبيق فك الترميز تحويل اللون العكسي واسترداد القيم الأصلية الحمراء والزرقاء. تشير رسالة الأشكال البيانية أول 3 بت من بيانات تحويل الألوان تحتوي على عرض وارتفاع كتلة صورة بعدد وحدات البت، تمامًا مثل تحويل المتنبئ:

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

يحتوي الجزء المتبقي من بيانات تحويل الألوان على ColorTransformElement الحالات، تتوافق مع كل كتلة من الصورة. على كل يتم التعامل مع ColorTransformElement 'cte' على أنّها وحدة بكسل في صورة ذات دقة فرعية. الذي يكون مكوّن ألفا الخاص به 255، والمكون الأحمر هو cte.red_to_blue، أخضر هو cte.green_to_blue، والمكون الأزرق هو cte.green_to_red.

أثناء فك الترميز، يتم فك ترميز مثيلات ColorTransformElement من القطع يتم تطبيق تحويل الألوان العكسي على قيم ARGB للبكسل. بالنسبة ذكرته سابقًا، أن تحويل اللون العكسي هو مجرد إضافة ColorTransformElement إلى القناتين الأحمر والأزرق. يشير ذلك المصطلح إلى حرف "ألفا" واللون الأخضر. يتم ترك القنوات كما هي.

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 طرح التحويل الأخضر

يطرح تحويل الطرح الأخضر القيم الخضراء من القيم الحمراء والزرقاء كل بكسل. وعند توفّر هذا التحويل، يجب أن تضيف أداة فك الترميز ترميز لكل من القيمتين الأحمر والأزرق. ليس هناك أي بيانات مرتبطة بهذا. تحويل. يطبّق برنامج فك الترميز التحويل العكسي على النحو التالي:

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

هذا التحويل متكرر، حيث يمكن نمذته باستخدام تحويل الألوان، ولكن نظرًا لعدم وجود بيانات إضافية هنا، يمكن إجراء تحويل الطرح الأخضر ترميزها باستخدام وحدات بت أقل من تحويل اللون كامل المنفوخ.

4.4 تحويل فهرسة الألوان

إذا لم تكن هناك قيم فريدة كثيرة للبكسل، قد يكون من الأفضل إنشاء ملف مصفوفة فهرس الألوان واستبدال قيم البكسل بفهارس المصفوفة. اللون الذي يؤدي تحويل الفهرسة إلى تحقيق ذلك (في سياق WebP بدون فقدان المعلومات، لا نسميه تحديدًا تحويل لوحة الألوان لأنّ هناك مفهومًا مشابهًا ولكنه أكثر ديناميكية في ترميز WebP بدون فقدان المعلومات: ذاكرة التخزين المؤقت للألوان).

يتحقق تحويل فهرسة الألوان من عدد قيم ARGB الفريدة في . وإذا كان هذا الرقم أقل من الحد الأدنى (256)، فإن ذلك يؤدي إلى إنشاء صفيف من تلك قيم ARGB، والتي تُستخدم بعد ذلك لاستبدال قيم البكسل بـ الفهرس المتجاوب: يتم استبدال القناة الخضراء لوحدات البكسل يتم تعيين جميع قيم ألفا على 255، وجميع قيم اللون الأحمر والأزرق على 0.

تحتوي بيانات التحويل على حجم جدول الألوان والإدخالات في جدول الألوان. تقرأ أداة فك الترميز بيانات تحويل فهرسة الألوان على النحو التالي:

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

يتم تخزين جدول الألوان باستخدام تنسيق تخزين الصور نفسه. جدول الألوان يمكن الحصول عليه من خلال قراءة صورة، دون عنوان RIFF، وحجم الصورة، المتغير، على افتراض أن ارتفاع 1 بكسل وعرض color_table_size. يتم ترميز جدول الألوان دائمًا بالطرح لتقليل قصور الصورة. دلتا من ألوان لوحة الألوان تحتوي عادةً على قصور أقل بكثير من الألوان نفسها، ما يؤدي إلى توفير كبير في الصور الأصغر حجمًا. في فك الترميز، كل لون نهائي في جدول الألوان عن طريق إضافة قيم مكون اللون حسب كل مكون ARGB على حدة وتخزين أقل 8 بتات كبيرة من النتيجة.

التحويل العكسي للصورة هو ببساطة استبدال قيم البكسل (التي هي فهارس لجدول الألوان) بقيم جدول الألوان الفعلية. الفهرسة بناءً على العنصر الأخضر للون ARGB.

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

إذا كان الفهرس يساوي color_table_size أو يزيد عنه، يتم استخدام قيمة اللون argb على 0x00000000 (أسود شفاف).

عندما يكون جدول الألوان صغيرًا (يساوي أو أقل من 16 لونًا)، فإن العديد من وحدات البكسل مجمعة في بكسل واحد. حزم وحدات البكسل متعددة (2 أو 4 أو 8) بكسل في بكسل واحد، مما يقلل عرض الصورة على التوالي. تسمح عملية تجميع وحدات البكسل بترميز معلومات المحتوى العشوائي المشترك لوحدات البكسل المجاورة بكفاءة أكبر، كما توفّر بعض المزايا التي تشبه الترميز الحسابي لرمز معلومات المحتوى العشوائي، ولكن لا يمكن استخدامها إلا عندما تكون هناك 16 قيمة فريدة أو أقل.

تحدّد الدالة color_table_size عدد وحدات البكسل التي يتم دمجها:

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 هي 0 أو 1 أو 2 أو 3. تشير القيمة 0 إلى عدم وجود بكسل التجميع للصورة. تشير القيمة 1 إلى أن اثنين من وحدات البكسل معًا، ويكون لكل وحدة بكسل نطاق [0..15]. تشير القيمة 2 إلى أنّه يتم دمج أربعة بكسل، وأنّ كل بكسل له نطاق من [0..3]. القيمة 3 يشير إلى أنه قد تم دمج ثماني وحدات بكسل ويكون لكل بكسل نطاق [0..1]، أي قيمة ثنائية.

يتم تجميع القيم في المكوّن الأخضر على النحو التالي:

  • width_bits = 1: لكل قيمة x، حيث x ≡ 0 (mod 2)، يتم وضع قيمة ملفّ رسومات برمجي خضراء عند x في وحدات البت الأربع الأقل أهمية من قيمة الملفّ الرسومي البرمجي الخضراء عند x / 2، ويتم وضع قيمة ملفّ رسومات برمجي خضراء عند x + 1 في وحدات البت الأربع الأكثر أهمية من قيمة الملفّ الرسومي البرمجي الخضراء عند x / 2.
  • width_bits = 2: لكل قيمة x، حيث x ":" 0 (التعديل 4) يظهر رمز أخضر عند القيمة x في اثنين البت الأقل أهمية في القيمة الخضراء عند x / 4، والقيم الخضراء عند x + 1 إلى x + 3 في بالترتيب إلى وحدات البت الأكثر أهمية للقيمة الخضراء في س / 4.
  • width_bits = 3: لكل قيمة x، حيث x ≡ 0 (mod 8)، يتم وضع قيمة ملفّ رسومات متحرك في x في وحدات البت الأقل أهمية من قيمة ملفّ الرسومات المتحرك في x / 8، ويتم وضع القيم الخضراء في x + 1 إلى x + 7 بالترتيب إلى وحدات البت الأكثر أهمية من قيمة ملفّ الرسومات المتحرك في x / 8.

بعد قراءة هذا التحويل، تستند image_width إلى عيّنة فرعية من خلال width_bits. هذا النمط في حجم التحويلات اللاحقة. ويمكن حساب الحجم الجديد باستخدام DIV_ROUND_UP، كما هو محدّد سابقًا.

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

5 بيانات الصورة

بيانات الصور هي مصفوفة من قيم البكسل بترتيب خط المسح.

5.1 أدوار بيانات الصور

نستخدم بيانات الصور في خمسة أدوار مختلفة:

  1. صورة ARGB: لتخزين وحدات البكسل الفعلية للصورة.
  2. صورة معلومات المحتوى العشوائي: تخزِّن رموز البادئة الوصفية (راجِع "ترميز رموز البادئة الوصفية").
  3. صورة التنبؤ: لتخزين البيانات الوصفية لتحويل المتنبئ (راجع "تحويل أداة التوقّعات").
  4. صورة تحويل الألوان: تم إنشاؤها باستخدام ColorTransformElement قيمة (مُحدَّد في "تحويل الألوان") لمجموعات مختلفة من الصورة.
  5. صورة فهرسة الألوان: مصفوفة بحجم color_table_size (256 بحدّ أقصى) قيم ARGB) التي تخزن البيانات الوصفية لتحويل فهرسة الألوان (راجع "تحويل فهرسة الألوان").

5.2 ترميز بيانات الصور

يكون ترميز بيانات الصور مستقلاً عن دوره.

يتم تقسيم الصورة أولاً إلى مجموعة من الكتل ذات الحجم الثابت (عادةً ما تكون 16×16 كتلة). يتم وضع نماذج لكلّ من هذه الكتل باستخدام رموز المعلومات العشوائية الخاصة بها. كذلك، قد تشترك عدة كتل في نفس رموز الإنتروبيا.

الأسباب: ينطوي تخزين رمز قصور على تكلفة. ويمكن تقليل هذه التكلفة إلى أدنى حد إذا كانت الكتل المتشابهة إحصائيًا تشترك في رمز قصور، فإن ذلك يؤدي إلى تخزين هذا الرمز مرة واحدة فقط. على سبيل المثال، يمكن لبرنامج الترميز العثور على كتل متشابهة من خلال تجميعها باستخدام خصائصهما الإحصائية أو من خلال دمج زوج من القطع عشوائيًا مجموعات عنقودية محددة عندما يقلل من المقدار الكلي لوحدات البت اللازمة لتشفير الصورة.

يتم تشفير كل وحدة بكسل باستخدام إحدى الطرق الثلاث المحتملة:

  1. القيم الثابتة المُشفَّرة بالبادئة: يتم ترميز كل قناة (الأخضر والأحمر والأزرق والألفا) باستخدام ترميز الانتروبي بشكل مستقل.
  2. المرجع LZ77 الخلفي: يتم نسخ تسلسل من وحدات البكسل من أي مكان آخر في الصورة.
  3. رمز ذاكرة التخزين المؤقت للألوان: يتم استخدام رمز تجزئة قصير مضاعف (فهرس ذاكرة التخزين المؤقت للألوان) للون الذي تمّ عرضه مؤخرًا.

تصف الفقرات الفرعية التالية كلاً من هذه الخطوات بالتفصيل.

5.2.1 رموز حرفية مشفّرة ببادئة

يتم تخزين وحدة البكسل كقيم مرمزة كبادئة، وهي الأخضر والأحمر والأزرق وألفا (في هذا الطلب). راجع القسم 6.2.3 للحصول على التفاصيل.

5.2.2 LZ77 Backward Reference

المراجع السابقة هي صفوف الطول ورمز المسافة:

  • يشير "الطول" إلى عدد وحدات البكسل التي سيتم نسخها في سطر البحث.
  • رمز المسافة هو رقم يشير إلى موضع جهاز معروض من قبل الذي سيتم نسخ وحدات البكسل منه. التعيين الدقيق هو كما هو موضح أدناه.

يتم تخزين قيم الطول والمسافة باستخدام ترميز البادئة LZ77.

يقسّم ترميز البادئة LZ77 قيم الأعداد الصحيحة الكبيرة إلى جزأين: البادئة ووحدات البت الإضافية. يتم تخزين رمز البادئة باستخدام رمز القصور، بينما يتم تخزين وحدات البت الإضافية كما هي (بدون رمز قصور).

الأسباب: يؤدي هذا النهج إلى تقليل متطلبات مساحة التخزين للإنتروبيا. الرمز. كما أن القيم الكبيرة تكون نادرة عادةً، لذا يتم استخدام وحدات بت إضافية القيم القليلة في الصورة. وبالتالي، ينتج عن هذه الطريقة ضغط أفضل بوجه عام.

يوضح الجدول التالي رموز البادئات ووحدات البت الإضافية المستخدمة للتخزين نطاقات القيم المختلفة.

نطاق القيمة رمز البادئة معلومات إضافية
1 0 0
2 1 0
3 2 0
4 3 0
6.5 4 1
8.7 5 1
9..12 6 2
16/13 7 2
... ... ...
3072..4096 23 10
... ... ...
524289..786432 38 18
‎786433..1048576 39 18

يكون الكود الزائف للحصول على قيمة (الطول أو المسافة) من رمز البادئة على النحو التالي التالي:

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;
رسم خرائط المسافة

وكما أشرنا سلفًا، رمز المسافة هو رقم يشير إلى موضع البكسل الذي تم عرضه سابقًا، والذي سيتم نسخ وحدات البكسل منه. هذا القسم الفرعي يحدد هذا الخيار الربط بين رمز مسافة وموضع فاصلة سابقة pixel.

تشير رموز المسافة الأكبر من 120 إلى مسافة البكسل بترتيب خط البحث، تعويضًا بنسبة 120.

رموز المسافة الأصغر [1..120] هي رموز خاصة ويتم حجزها للإغلاق. بجوار البكسل الحالي. يتكون هذا الحي من 120 بكسل:

  • وحدات البكسل التي تزيد عن 8 إلى 7 صفوف فوق البكسل الحالي وبحد أقصى 8 أعمدة إلى اليسار أو ما يصل إلى 7 أعمدة على يمين وحدة البكسل الحالية. [الإجمالي وحدات البكسل = 7 * (8 + 1 + 7) = 112].
  • وحدات البكسل التي تكون في الصف نفسه الذي يتضمّن وحدات البكسل الحالية وتكون ضمن 8 أعمدة على يمين وحدات البكسل الحالية [8 بكسل من هذا النوع].

التعيين بين رمز المسافة distance_code والبكسل المجاور الإزاحة (xi, yi) هي كما يلي:

(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)

على سبيل المثال، يشير رمز المسافة 1 إلى إزاحة (0, 1) للبكسل المجاور، أيّ البكسل فوق البكسل الحالي (اختلاف 0 بكسل في اتجاه X واختلاف بكسل واحد في اتجاه Y). وبالمثل، يشير رمز المسافة 3 إلى وحدات البكسل في أعلى اليسار.

يمكن لأداة فك الترميز تحويل رمز المسافة distance_code إلى ترتيب الأسطر. المسافة dist على النحو التالي:

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

حيث distance_map هو التعيين المذكور أعلاه، وimage_width هو العرض الصورة بالبكسل.

5.2.3 ترميز ذاكرة التخزين المؤقت للألوان

تخزن ذاكرة التخزين المؤقت للألوان مجموعة من الألوان التي تم استخدامها مؤخرًا في الصورة.

الأسباب: بهذه الطريقة، يمكن أحيانًا الإشارة إلى الألوان المستخدَمة مؤخرًا. بكفاءة أكبر من إطلاقها باستخدام الطريقتين الأخريين (الموضحة في 5.2.1 و5.2.2).

يتم تخزين رموز ذاكرة التخزين المؤقت للألوان على النحو التالي. أولاً، هناك قيمة وحدة بت واحدة إلى ما إذا كان سيتم استخدام ذاكرة التخزين المؤقت للألوان. إذا كانت هذه البت هي 0، فلا توجد رموز ذاكرة التخزين المؤقت للألوان ولا يتم إرسالها في رمز البادئة الذي يفك ترميز الرمز ورموز بادئة الطول. ومع ذلك، إذا كان هذا البت هو 1، فإن ذاكرة التخزين المؤقت للألوان تتم قراءة الحجم بعد ذلك:

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

تحدد السمة color_cache_code_bits حجم ذاكرة التخزين المؤقت للألوان (1 << color_cache_code_bits). نطاق القيم المسموح بها color_cache_code_bits هو [1..11]. يجب أن تشير برامج فك الترميز المتوافقة إلى تدفق بت تالف للقيم الأخرى.

ذاكرة التخزين المؤقت للألوان هي مصفوفة بحجم color_cache_size. يخزِّن كل إدخال أحد قيم ARGB واحدة اللون. يتم البحث عن الألوان عن طريق فهرستها حسب (0x1e35a7bd * color) >> (32 - color_cache_code_bits). يتم إجراء عملية بحث واحدة فقط في ذاكرة التخزين المؤقت للألوان؛ لا يوجد وحل النزاعات.

في بداية فك ترميز الصورة أو ترميزها، تكون جميع الإدخالات بجميع الألوان يتم تعيين قيم ذاكرة التخزين المؤقت على صفر. يتم تحويل رمز ذاكرة التخزين المؤقت للألوان إلى هذا اللون في وقت معالجة الترميز. يتم الاحتفاظ بحالة ذاكرة التخزين المؤقت للألوان عن طريق إدخال كل pixel، سواء تم إنتاجه بالإشارة إلى الخلف أو كقيم حرفية، في ذاكرة التخزين المؤقت في بالترتيب الذي تظهر به في ساحة المشاركات.

رمز الإنتروبيا 6

6.1 نظرة عامة

ويتم ترميز معظم البيانات باستخدام رمز بادئة أساسي. وبالتالي، يتم نقل الرموز من خلال إرسال طول رموز البادئة، بدلاً من رموز البادئة الفعلية.

وعلى وجه الخصوص، يستخدم التنسيق ترميز بادئة الصيغة المكانية. بعبارة أخرى، يمكن أن تستخدِم أجزاء مختلفة من الصورة رموزًا مختلفة لقياس التشويش.

الأسباب: قد تكون للمناطق المختلفة من الصورة خصائص مختلفة. لذا فإن السماح لهم باستخدام رموز إنتروبيا مختلفة يوفر مزيدًا من المرونة من المحتمل أن يكون ضغطها أفضل.

6.2 التفاصيل

تتكوّن بيانات الصورة المشفَّرة من عدة أجزاء:

  1. فك ترميز رموز البادئة وإنشاؤها.
  2. رموز البادئات الوصفية.
  3. بيانات الصور المشفَّرة بالترميز العشوائي

بالنسبة لأي وحدة بكسل (x، y)، توجد مجموعة من خمسة رموز بادئة مرتبطة بها. هذه الرموز هي (بترتيب البث المباشر):

  • رمز البادئة رقم 1: يتم استخدامه للقناة الخضراء وطول المرجع السابق و ذاكرة التخزين المؤقت للألوان.
  • رمز البادئة رقم 2 و3 و4: يتم استخدامه لقنوات الأحمر والأزرق والإصدار الأولي، على التوالي.
  • رمز البادئة رقم 5: يتم استخدامه لمسافة المرجع القديم.

ومن الآن فصاعدًا، نشير إلى هذه المجموعة بأنّها مجموعة رموز بادئة.

6.2.1 فك الترميز وإنشاء رموز البادئة

يصف هذا القسم كيفية قراءة أطوال الرموز البادئة من بث البتات.

يمكن ترميز أطوال رموز البادئة بطريقتين. تم تحديد الطريقة المستخدمة بقيمة وحدة بت.

  • إذا كانت هذه البت هي 1، تكون رمز طول الرمز البسيط.
  • وإذا كانت هذه البت هي 0، فإنها تكون رمز طول الرمز العادي.

وفي كلتا الحالتين، يمكن أن تكون هناك أطوال رموز غير مستخدمة لا تزال جزءًا من دفق. قد لا يكون هذا الإجراء فعّالاً، ولكنّه مسموح به بموجب التنسيق. يجب أن تكون الشجرة الموصوفة شجرة ثنائية كاملة. العقدة الطرفية المفردة هي تعتبر شجرة ثنائية كاملة ويمكن تشفيرها باستخدام إما رمز طول الرمز أو رمز طول الرمز العادي. عند ترميز ملف واحد للعقدة باستخدام رمز طول الرمز العادي، تكون جميع أطوال الرموز صفرًا باستثناء طول رمز واحد، ويتم وضع علامة على قيمة الملف الواحد للعقدة بطول 1، حتى في حال عدم استخدام أي بتات عند استخدام شجرة الملف الواحد للعقدة.

رمز طول الرمز البسيط

يتم استخدام هذه الصيغة في الحالة الخاصة عندما يكون هناك رمز واحد أو رمزين من البادئة فقط. النطاق [0..255] مع طول الرمز 1. جميع أطوال رموز البادئة الأخرى تكون صفرًا ضمنيًا.

يشير البت الأول إلى عدد الرموز:

int num_symbols = ReadBits(1) + 1;

فيما يلي هي قيم الرموز.

يتم ترميز هذا الرمز الأول باستخدام بت واحد أو 8 بتات، حسب قيمة is_first_8bits. ويكون النطاق [0..1] أو [0..255] على التوالي. يُفترض دائمًا أنّ الرمز الثاني، في حال توفّره، يقع ضمن النطاق [0..255] ويتم ترميزه باستخدام 8 بت.

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;
}

يجب أن يكون الرمزان مختلفين. يُسمح باستخدام الرموز المكرّرة، ولكنها غير فعّالة.

ملاحظة: هناك حالة خاصة أخرى عندما تكون جميع أطوال رموز البادئة أصفار (أي رمز البادئة الفارغ). على سبيل المثال، يمكن ترك رمز بادئة للمسافة فارغًا إذا لا توجد مراجع خلفية. وبالمثل، يمكن أن تكون رموز البادئة للألوان ألفا والأحمر والأزرق فارغة إذا تم إنشاء جميع وحدات البكسل ضمن رمز البادئة التعريفية نفسه باستخدام ذاكرة التخزين المؤقت للألوان. ومع ذلك، لا تحتاج هذه الحالة إلى معالجة خاصة، حيث ويمكن ترميز رموز البادئات الفارغة مثل تلك التي تحتوي على الرمز الواحد 0.

رمز طول الرمز العادي

ويتناسب أطوال رمز البادئة مع 8 بتات وتتم قراءتها على النحو التالي. أولاً، تحدّد السمة num_code_lengths عدد أطوال الرموز.

int num_code_lengths = 4 + ReadBits(4);

ويتم ترميز أطوال الرموز نفسها باستخدام رموز بادئة، رمز من المستوى الأدنى الأطوال، code_length_code_lengths، يجب قراءتها أولاً. بقية هذه code_length_code_lengths (وفقًا للطلب في kCodeLengthCodeOrder) هي أصفار.

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);
}

بعد ذلك، إذا كان ReadBits(1) == 0، يتم ضبط الحد الأقصى لعدد الرموز المختلفة التي يتم قراءتها (max_symbol) لكل نوع رمز (A وR وG وB والمسافة) على حجم الأبجدية:

  • قناة G: 256 + 24 + color_cache_size
  • القيم الحرفية الأخرى (A وR وB): 256
  • رمز المسافة: 40

وبخلاف ذلك، يتم تعريفه على أنه:

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

إذا كان max_symbol أكبر من حجم الأبجدية لنوع الرمز، يكون البثّ غير صالح.

بعد ذلك، يتم إنشاء جدول بادئة من code_length_code_lengths ويتم استخدامه لقراءة أطوال الرموز التي تصل إلى max_symbol.

  • يشير الرمز [0..15] إلى أطوال الرموز الحرفية.
    • تعني القيمة 0 أنّه لم يتم ترميز أي رموز.
    • تشير القيم [1..15] إلى طول بت الرمز المعني.
  • يكرر الرمز 16 القيمة السابقة غير الصفرية [3..6] مرات، وهي، 3 + ReadBits(2) مرّة في حال استخدام الرمز 16 قبل بث قيمة غير صفرية، تتم إعادة قيمة 8.
  • ينتج عن الرمز 17 سلسلة أصفار بطول [3..10]، أي 3 + ReadBits(3) مرة.
  • ينبعث الرمز 18 سلسلة من أصفار طولها [11..138]، أي 11 + ReadBits(7) مرّة

بمجرد قراءة أطوال الرموز، كود بادئة لكل نوع من أنواع الرموز (A، وR، وG، وB، المسافة) باستخدام أحجام الأبجدية لكل منها.

ويجب أن يُرمز رمز طول الرمز العادي إلى شجرة قرارات كاملة، بمعنى أن يكون مجموع يجب أن تكون قيمة 2 ^ (-length) لكل الرموز غير الصفرية رقمًا واحدًا بالضبط. هناك مع ذلك استثناء واحد لهذه القاعدة، وهو شجرة العقدة الورقية الواحدة، حيث يتم وضع علامة على قيمة العقدة الورقية بالقيمة 1 والقيم الأخرى هي 0.

6.2.2 فك ترميز رموز البادئة الوصفية

وكما أشرنا سلفًا، يسمح التنسيق باستخدام رموز بادئة مختلفة كتل مختلفة من الصورة. رموز البادئة الوصفية هي فهارس تحدّد رموز بادئة لاستخدامها في أجزاء مختلفة من الصورة.

يمكن استخدام رموز بادئة العناصر الوصفية فقط عند استخدام الصورة في دور صورة ARGB.

هناك احتمالان لرموز البادئة الوصفية، يُشار إليها بقيمة وحدة بت القيمة:

  • إذا كانت قيمة البت هذه صفرًا، يتم استخدام رمز بادئة وصفية واحد فقط في كل مكان في الصورة. ولا يتم تخزين المزيد من البيانات.
  • إذا كانت هذه البت واحدًا، فإن الصورة تستخدم العديد من رموز البادئات الوصفية. يتم تخزين رموز البادئة هذه كـ صورة معلوماتية (موضحة أدناه).

يحدد كل من المكونات الحمراء والخضراء للبكسل رمز بادئة تعريفية 16 بت يُستخدم في كتلة معينة من صورة ARGB.

صورة إنتروبيا

تحدد صورة القصور أي رموز بادئة يتم استخدامها في أجزاء مختلفة من .

تحتوي أول 3 وحدات بت على القيمة prefix_bits. أبعاد القصور الصورة مشتقة من prefix_bits:

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);

حيث تم تحديد DIV_ROUND_UP كما هو سابق.

تحتوي وحدات البت التالية على صورة قصور بالعرض والارتفاع prefix_image_width. prefix_image_height

تفسير رموز البادئات الوصفية

يمكن الحصول على عدد مجموعات رموز البادئة في صورة ARGB من خلال العثور على أكبر رمز بادئة وصفية من صورة التشويش:

int num_prefix_groups = max(entropy image) + 1;

حيث يشير max(entropy image) إلى أكبر رمز بادئة تم تخزينه في صورة إنتروبيا.

ونظرًا لأن كل مجموعة رموز بادئة تحتوي على خمسة رموز بادئات، فإن العدد الإجمالي للبادئة الرموز هي:

int num_prefix_codes = 5 * num_prefix_groups;

بناءً على وحدة البكسل (x، y) في صورة ARGB، يمكننا الحصول على البادئة المقابلة الرموز التي سيتم استخدامها على النحو التالي:

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];

حيث افترضنا وجود بنية PrefixCodeGroup، التي ويمثل مجموعة من خمسة رموز بادئة. بالإضافة إلى ذلك، prefix_code_groups هي صفيف من PrefixCodeGroup (بحجم num_prefix_groups).

يستخدم برنامج فك الترميز بعد ذلك مجموعة رموز البادئة prefix_group لفك ترميز وحدة البكسل. (س، ص)، كما هو موضح في "فك ترميز الصورة المشفرة بالإنتروبيا". البيانات".

6.2.3 فك ترميز بيانات الصور المُشفَّرة بالترميز العشوائي

بالنسبة إلى الموضع الحالي (س، ص) في الصورة، يحدد برنامج فك الترميز أولاً مجموعة رموز البادئة المقابلة (كما هو موضّح في القسم الأخير). استنادًا إلى مجموعة رمز البادئة، تتم قراءة وحدة البكسل وفك ترميزها على النحو التالي.

بعد ذلك، اقرأ الرمز S من مصدر البيانات البت باستخدام رمز البادئة رقم 1. لاحظ أن S هي أي عدد صحيح في النطاق من 0 إلى (256 + 24 + color_cache_size- 1)

يعتمد تفسير S على قيمته:

  1. إذا كانت S < 256
    1. استخدِم S كمكوّن اللون الأخضر.
    2. اقرأ اللون الأحمر من بث البيانات البتية باستخدام رمز البادئة رقم 2.
    3. اقرأ اللون الأزرق من مصدر البيانات البت باستخدام رمز البادئة رقم 3.
    4. اقرأ ألفا من مصدر البيانات البت باستخدام رمز البادئة رقم 4.
  2. إذا كانت S >= 256 & S < 256 + 24
    1. استخدِم S - 256 كرمز لبادئة الطول.
    2. يمكنك قراءة وحدات بت إضافية للطول من البث المباشر للبيانات.
    3. حدد طول المرجع السابق L من رمز بادئة الطول قراءة وحدات البت الإضافية.
    4. اقرأ رمز بادئة المسافة من مصدر البيانات البتّي باستخدام رمز البادئة رقم 5.
    5. قراءة وحدات بت إضافية عن المسافة من مصدر البيانات
    6. حدِّد المسافة D للإشارة إلى المحتوى السابق من رمز بادئة المسافة والبتات الإضافية التي تم قراءتها.
    7. انسخ L بكسل (بترتيب سطر المسح) من تسلسل وحدات البكسل بدءًا من في الموضع الحالي مطروحًا منه D بكسل.
  3. إذا كانت S >= 256 + 24
    1. استخدِم S - (256 + 24) كفهرس في ذاكرة التخزين المؤقت للألوان.
    2. يمكنك الحصول على ألوان ARGB من ذاكرة التخزين المؤقت للألوان على هذا الفهرس.

7 البنية العامة للتنسيق

في ما يلي نظرة على التنسيق بتنسيق "صيغة باكوس ناور المعزّزة" (ABNF) RFC 5234 RFC 7405. ولا تشمل جميع التفاصيل. نهاية الصورة (EOI) لا يتم ترميزها بشكل ضمني إلا بعدد وحدات البكسل (image_width * image_height).

يُرجى العِلم أنّ السمة *element تعني أنّه يمكن تكرار الحقل element 0 مرة أو أكثر. 5element تعني أنّ السمة element تتكرّر 5 مرات بالضبط. يمثّل الرمز %b قيمة ثنائية.

7.1 البنية الأساسية

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 بنية التحويلات

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 بنية بيانات الصور

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)

في ما يلي مثال محتمل على التسلسل:

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