shithub: jbig2

Download patch

ref: a841c2481b35b7bf1bf5970a11ac750ff3a3ee2c
parent: ad742b847dbb39b1376664d77fae0f8b31ae65f0
author: Ralph Giles <giles@cirrus.local>
date: Mon Nov 23 11:49:06 EST 2009

Implement generic region decode with typical prediction.

Patch from Gorac. Ghostscript bugs 690791 and 690913.

--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -466,7 +466,222 @@
   return 0;
 }
 
+static void
+copy_prev_row(Jbig2Image *image, int row)
+{
+  if (!row) {
+    /* no previous row */
+    memset( image->data, 0, image->stride );
+  } else {
+    /* duplicate data from the previous row */
+    uint8_t *src = image->data + (row - 1) * image->stride;
+    memcpy( src + image->stride, src, image->stride );
+  }
+}
 
+static int
+jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
+				Jbig2Segment *segment,
+				const Jbig2GenericRegionParams *params, 
+				Jbig2ArithState *as,
+				Jbig2Image *image,
+				Jbig2ArithCx *GB_stats)
+{
+  const int GBW = image->width;
+  const int GBH = image->height;
+  uint32_t CONTEXT;
+  int x, y;
+  bool bit;
+  int LTP = 0;
+
+  for (y = 0; y < GBH; y++)
+  {
+    LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25]);
+    if (!LTP) {
+      for (x = 0; x < GBW; x++) {
+        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
+					y + params->gbat[1]) << 4;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 7;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
+					y + params->gbat[3]) << 10;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
+					y + params->gbat[5]) << 11;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 13;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
+					y + params->gbat[7]) << 15;
+        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+        jbig2_image_set_pixel(image, x, y, bit);
+      }
+    } else {
+      copy_prev_row(image, y);
+    }
+  }
+
+  return 0;
+}
+
+static int
+jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx, 
+				Jbig2Segment *segment,
+				const Jbig2GenericRegionParams *params, 
+				Jbig2ArithState *as,
+				Jbig2Image *image,
+				Jbig2ArithCx *GB_stats)
+{
+  const int GBW = image->width;
+  const int GBH = image->height;
+  uint32_t CONTEXT;
+  int x, y;
+  bool bit;
+  int LTP = 0;
+
+  for (y = 0; y < GBH; y++) {
+    LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795]);
+    if (!LTP) {
+      for (x = 0; x < GBW; x++) {
+        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
+					y + params->gbat[1]) << 3;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 6;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 11;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
+        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+        jbig2_image_set_pixel(image, x, y, bit);
+      }
+    } else {
+      copy_prev_row(image, y);
+    }
+  }
+
+  return 0;
+}
+
+static int
+jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx, 
+				Jbig2Segment *segment,
+				const Jbig2GenericRegionParams *params,
+				Jbig2ArithState *as,
+				Jbig2Image *image,
+				Jbig2ArithCx *GB_stats)
+{
+  const int GBW = image->width;
+  const int GBH = image->height;
+  uint32_t CONTEXT;
+  int x, y;
+  bool bit;
+  int LTP = 0;
+
+  for (y = 0; y < GBH; y++) {
+    LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5]);
+    if (!LTP) {
+      for (x = 0; x < GBW; x++) {
+        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
+					y + params->gbat[1]) << 2;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 4;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 8;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
+        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+        jbig2_image_set_pixel(image, x, y, bit);
+      }
+    } else {
+      copy_prev_row(image, y);
+    }
+  }
+
+  return 0;
+}
+
+static int
+jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx, 
+				Jbig2Segment *segment,
+				const Jbig2GenericRegionParams *params,
+				Jbig2ArithState *as,
+				Jbig2Image *image,
+				Jbig2ArithCx *GB_stats)
+{
+  const int GBW = image->width;
+  const int GBH = image->height;
+  uint32_t CONTEXT;
+  int x, y;
+  bool bit;
+  int LTP = 0;
+
+  for (y = 0; y < GBH; y++) {
+    LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195]);
+    if (!LTP) {
+      for (x = 0; x < GBW; x++) {
+        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
+        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
+					y + params->gbat[1]) << 4;
+        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
+        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 6;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
+        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
+        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+        jbig2_image_set_pixel(image, x, y, bit);
+      }
+    } else {
+      copy_prev_row(image, y);
+    }
+  }
+
+  return 0;
+}
+
+static int
+jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx,
+				Jbig2Segment *segment,
+				const Jbig2GenericRegionParams *params, 
+				Jbig2ArithState *as,
+				Jbig2Image *image,
+				Jbig2ArithCx *GB_stats)
+{
+  switch (params->GBTEMPLATE) {
+    case 0:
+      return jbig2_decode_generic_template0_TPGDON(ctx, segment, 
+			params, as, image, GB_stats);
+    case 1:
+      return jbig2_decode_generic_template1_TPGDON(ctx, segment, 
+			params, as, image, GB_stats);
+    case 2:
+      return jbig2_decode_generic_template2_TPGDON(ctx, segment, 
+			params, as, image, GB_stats);
+    case 3:
+      return jbig2_decode_generic_template3_TPGDON(ctx, segment, 
+			params, as, image, GB_stats);
+  }
+
+  return -1;
+}
+
 /**
  * jbig2_decode_generic_region: Decode a generic region.
  * @ctx: The context for allocation and error reporting.
@@ -494,10 +709,9 @@
 {
   const int8_t *gbat = params->gbat;
 
-  if (!params->MMR && params->TPGDON) {
-    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
-	"NYI: typical prediction in a generic region\n");
-  }
+  if (!params->MMR && params->TPGDON) 
+     return jbig2_decode_generic_region_TPGDON(ctx, segment, params, 
+		as, image, GB_stats);
 
   if (!params->MMR && params->GBTEMPLATE == 0) {
     if (gbat[0] == +3 && gbat[1] == -1 &&