مواصفات تقنية 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 بدون فقدان البيانات بحجم 16384ADGROUPS16384 بكسل

البت 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 متوسط2(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-pixel.

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

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 نقطة ثابتة وقناة ألوان تستند إلى نموذج أحمر أخضر أزرق بترميز 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 (التعديل 2) رمز أخضر يتم وضع القيمة عند س في وحدات البت الأربعة الأقل أهمية القيمة الخضراء عند x / 2، والقيمة الخضراء عند x + 1 في 4 أهم وحدات بت للقيمة الخضراء بـ x / 2.
  • width_bits = 2: لكل قيمة x، حيث x ":" 0 (التعديل 4) يظهر رمز أخضر عند القيمة x في اثنين البت الأقل أهمية في القيمة الخضراء عند x / 4، والقيم الخضراء عند x + 1 إلى x + 3 في بالترتيب إلى وحدات البت الأكثر أهمية للقيمة الخضراء في س / 4.
  • width_bits = 3: لكل قيمة x، حيث x ":" 0 (التعديل 8) يظهر رمز أخضر يتم وضع القيمة عند س في أقل وحدة بت من اللون الأخضر القيمة على 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 المرجع السابق

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

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

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

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

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

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

نطاق القيمة رمز البادئة وحدات بت إضافية
1 0 0
2 1 0
3 2 0
4 3 0
6.5 4 1
8.7 5 1
12.9. 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 بكسل) الفرق في الاتجاه س وفرق 1 بكسل في الاتجاه ص). وبالمثل، يشير رمز المسافة 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;

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

ويتم ترميز هذا الرمز الأول باستخدام 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