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 &&