Bug 690913 - Unhandled typical prediction in a generic region decoding procedure.
Summary: Unhandled typical prediction in a generic region decoding procedure.
Status: RESOLVED DUPLICATE of bug 690791
Alias: None
Product: jbig2dec
Classification: Unclassified
Component: Parsing (show other bugs)
Version: unspecified
Hardware: PC Windows XP
: P4 normal
Assignee: Ralph Giles
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-11-12 17:47 UTC by gorac
Modified: 2009-11-23 17:35 UTC (History)
0 users

See Also:
Customer:
Word Size: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gorac 2009-11-12 17:47:54 UTC
current implementation of jbig2_decode_generic_region() ignores the case 
           TPGDON == TRUE 
This produces garbage as we can exercise with test stream 042_8.jb2.

We can solve this problem with following simple additions.

A) add this line as first one in jbig2_decode_generic_region() in jbig2_generic.c:
 
  if (!params->MMR && params->TPGDON) 
     return jbig2_decode_generic_region_TPGDON( ctx, segment, params, as, image,
GB_stats );


B) add this code to the same file:

static void copy_prev_row( Jbig2Image *image, int row )
{
  if (!row)
  { // no previous  row
    memset( image->data, 0, image->stride );
  }
  else
  {
    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;
}

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); break;
    case 1: return jbig2_decode_generic_template1_TPGDON(ctx, segment, params,
as, image, GB_stats); break;
    case 2: return jbig2_decode_generic_template2_TPGDON(ctx, segment, params,
as, image, GB_stats); break;
    case 3: return jbig2_decode_generic_template3_TPGDON(ctx, segment, params,
as, image, GB_stats); break;
  }
  return -1;
}
Comment 1 Ralph Giles 2009-11-20 10:20:23 UTC
Thanks for the patch. It works great, giving correct rendering on 042_8.jb2 and
the problem file in bug 690791.

As a substantial contribution, we require copyright assignment before we can
take the patch. Are you willing to do that?
Comment 2 gorac 2009-11-23 15:37:21 UTC
I agree to assign you the copyright of this solution.
Comment 3 Ralph Giles 2009-11-23 17:35:49 UTC
Thanks for the contribution! I've pushed a version of the patch, edited for
coding style to git, and committed the same to the gs svn tree r10372.

*** This bug has been marked as a duplicate of 690791 ***