Actually typical prediction in generic refinement region decoding procedure is not yet implemented in jbig2dec (case TPGRON == TRUE, reference: 042_24.jb2 test stream). The following simple code, added to jbig2_refinement.c, implements this case. 1) in routine jbig2_decode_refinement_region() change the statement at second line: if (params->TPGRON) return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "decode_refinement_region: typical prediction coding NYI"); with this one: if (params->TPGRON) return jbig2_decode_refinement_TPGRON(params, as, image, GR_stats); 2) add to the same source file the following code: typedef uint32_t (*ContextBuilder)(const Jbig2RefinementRegionParams *, Jbig2Image *, int, int); static int implicit_value( const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y ) { Jbig2Image *ref = params->reference; int i = x - params->DX; int j = y - params->DY; int m = jbig2_image_get_pixel(ref, i, j); return ( (jbig2_image_get_pixel(ref, i - 1, j - 1) == m) && (jbig2_image_get_pixel(ref, i , j - 1) == m) && (jbig2_image_get_pixel(ref, i + 1, j - 1) == m) && (jbig2_image_get_pixel(ref, i - 1, j ) == m) && (jbig2_image_get_pixel(ref, i + 1, j ) == m) && (jbig2_image_get_pixel(ref, i - 1, j + 1) == m) && (jbig2_image_get_pixel(ref, i , j + 1) == m) && (jbig2_image_get_pixel(ref, i + 1, j + 1) == m) )? m : -1; } static uint32_t mkctx0( const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y ) { const int dx = params->DX; const int dy = params->DY; Jbig2Image *ref = params->reference; uint32_t CONTEXT; CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0); CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1; CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2; CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5; CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8; CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12; return CONTEXT; } static uint32_t mkctx1( const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y ) { const int dx = params->DX; const int dy = params->DY; Jbig2Image *ref = params->reference; uint32_t CONTEXT; CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0); CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1; CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2; CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7; CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8; CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9; return CONTEXT; } static int jbig2_decode_refinement_TPGRON(const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats) { const int GRW = image->width; const int GRH = image->height; const int dx = params->DX; const int dy = params->DY; Jbig2Image *ref = params->reference; int x, y, iv, bit, LTP = 0; uint32_t start_context = (params->GRTEMPLATE? 0x40 : 0x100); ContextBuilder mkctx = (params->GRTEMPLATE? mkctx1 : mkctx0); for (y = 0; y < GRH; y++) { bit = jbig2_arith_decode(as, &GR_stats[start_context]); if (bit < 0) return -1; LTP = LTP ^ bit; if (!LTP) { for (x = 0; x < GRW; x++) { bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]); if (bit < 0) return -1; jbig2_image_set_pixel(image, x, y, bit); } } else { for (x = 0; x < GRW; x++) { iv = implicit_value(params, image, x, y); if (iv < 0) { bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]); if (bit < 0) return -1; jbig2_image_set_pixel(image, x, y, bit); } else jbig2_image_set_pixel(image, x, y, iv); } } } return 0; } That's all. In my test this implementation works fine and correctly decode the test stream cited. Gorac
Created attachment 8334 [details] Gorac's patch for Bug690974 This is Gorac's code in patch form, the cluster test shows that Jbig2_042_24.pdf now renders correctly and there are no new regressions.
(In reply to comment #1) > Created an attachment (id=8334) [details] > Gorac's patch for Bug690974 > > This is Gorac's code in patch form, the cluster test shows that > Jbig2_042_24.pdf now renders correctly and there are no new regressions. Gorac and the staff had difficulty communicating and we don't expect to hear from him, let's take his post to be implicit approval to include his code under Artifex and GPL license. If he objects we'll pull it out and do an original implementation.
*** Bug 691245 has been marked as a duplicate of this bug. ***
Patch committed in 082c31b99fd38ebb1a9bc678d06ac9791db2e222