ref: be7e85301ae58f21e9bbc60eb58ae58fc1217465
parent: e74ec354988c96bbc2320b0594a5b3eeb39ef1d3
author: Sebastian Rasmussen <sebras@gmail.com>
date: Tue Jul 3 16:02:04 EDT 2018
jbig2dec: Implement support for generic region pixel skipping.
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -148,6 +148,10 @@
for (y = 0; y < GBH; y++) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
CONTEXT = 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
@@ -194,6 +198,10 @@
for (y = 0; y < GBH; y++) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
CONTEXT = 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
@@ -303,6 +311,10 @@
for (y = 0; y < GBH; y++) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
CONTEXT = 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
@@ -469,6 +481,10 @@
for (y = 0; y < GBH; y++) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
CONTEXT = 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
@@ -529,6 +545,10 @@
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
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;
@@ -581,6 +601,10 @@
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
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;
@@ -630,6 +654,10 @@
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
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;
@@ -676,6 +704,10 @@
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON1");
if (!LTP) {
for (x = 0; x < GBW; x++) {
+ if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
+ jbig2_image_set_pixel(image, x, y, 0);
+ continue;
+ }
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;
@@ -750,23 +782,23 @@
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 && gbat[2] == -3 && gbat[3] == -1 && gbat[4] == +2 && gbat[5] == -2 && gbat[6] == -2 && gbat[7] == -2)
+ if (!params->USESKIP && gbat[0] == +3 && gbat[1] == -1 && gbat[2] == -3 && gbat[3] == -1 && gbat[4] == +2 && gbat[5] == -2 && gbat[6] == -2 && gbat[7] == -2)
return jbig2_decode_generic_template0(ctx, segment, params, as, image, GB_stats);
else
return jbig2_decode_generic_template0_unopt(ctx, segment, params, as, image, GB_stats);
} else if (!params->MMR && params->GBTEMPLATE == 1) {
- if (gbat[0] == +3 && gbat[1] == -1)
+ if (!params->USESKIP && gbat[0] == +3 && gbat[1] == -1)
return jbig2_decode_generic_template1(ctx, segment, params, as, image, GB_stats);
else
return jbig2_decode_generic_template1_unopt(ctx, segment, params, as, image, GB_stats);
}
else if (!params->MMR && params->GBTEMPLATE == 2) {
- if (gbat[0] == 2 && gbat[1] == -1)
+ if (!params->USESKIP && gbat[0] == 2 && gbat[1] == -1)
return jbig2_decode_generic_template2(ctx, segment, params, as, image, GB_stats);
else
return jbig2_decode_generic_template2_unopt(ctx, segment, params, as, image, GB_stats);
} else if (!params->MMR && params->GBTEMPLATE == 3) {
- if (gbat[0] == 2 && gbat[1] == -1)
+ if (!params->USESKIP && gbat[0] == 2 && gbat[1] == -1)
return jbig2_decode_generic_template3(ctx, segment, params, as, image, GB_stats);
else
return jbig2_decode_generic_template3_unopt(ctx, segment, params, as, image, GB_stats);
--- a/jbig2_generic.h
+++ b/jbig2_generic.h
@@ -32,7 +32,7 @@
int GBTEMPLATE;
bool TPGDON;
bool USESKIP;
- /* SKIP */
+ Jbig2Image *SKIP;
int8_t gbat[8];
} Jbig2GenericRegionParams;
--- a/jbig2_halftone.c
+++ b/jbig2_halftone.c
@@ -298,6 +298,7 @@
rparams.GBTEMPLATE = GSTEMPLATE;
rparams.TPGDON = 0;
rparams.USESKIP = GSUSESKIP;
+ rparams.SKIP = GSKIP;
rparams.gbat[0] = (GSTEMPLATE <= 1 ? 3 : 2);
rparams.gbat[1] = -1;
rparams.gbat[2] = -3;
@@ -453,33 +454,47 @@
{
uint32_t HBPP;
uint32_t HNUMPATS;
- uint8_t **GI;
+ uint8_t **GI = NULL;
Jbig2Image *HSKIP = NULL;
Jbig2PatternDict *HPATS;
uint32_t i;
- uint32_t mg, ng;
+ int32_t mg, ng;
int32_t x, y;
uint8_t gray_val;
- int code;
+ int code = 0;
+ /* We need the patterns used in this region, get them from the referred pattern dictionary */
+ HPATS = jbig2_decode_ht_region_get_hpats(ctx, segment);
+ if (!HPATS) {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "no pattern dictionary found, skipping halftone image");
+ goto cleanup;
+ }
+
/* 6.6.5 point 1. Fill bitmap with HDEFPIXEL */
memset(image->data, params->HDEFPIXEL, image->stride * image->height);
- /* 6.6.5 point 2. compute HSKIP */
+ /* 6.6.5 point 2. compute HSKIP according to 6.6.5.1 */
if (params->HENABLESKIP == 1) {
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unhandled option HENABLESKIP (NYI)");
- }
+ HSKIP = jbig2_image_new(ctx, params->HGW, params->HGH);
+ if (HSKIP == NULL)
+ return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate skip image");
- /* 6.6.5 point 3. set HBPP to ceil(log2(HNUMPATS)):
- * we need the number of patterns used in this region (HNUMPATS)
- * get it from referred pattern dictionary */
+ for (mg = 0; mg < params->HGH; ++mg) {
+ for (ng = 0; ng < params->HGW; ++ng) {
+ x = (params->HGX + mg * (int32_t) params->HRY + ng * (int32_t) params->HRX) >> 8;
+ y = (params->HGY + mg * (int32_t) params->HRX - ng * (int32_t) params->HRY) >> 8;
- HPATS = jbig2_decode_ht_region_get_hpats(ctx, segment);
- if (!HPATS)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "no pattern dictionary found, skipping halftone image");
- HNUMPATS = HPATS->n_patterns;
+ if (x + HPATS->HPW <= 0 || x >= (int32_t) image->width || y + HPATS->HPH <= 0 || y >= (int32_t) image->height) {
+ jbig2_image_set_pixel(HSKIP, ng, mg, 1);
+ } else {
+ jbig2_image_set_pixel(HSKIP, ng, mg, 0);
+ }
+ }
+ }
+ }
- /* calculate ceil(log2(HNUMPATS)) */
+ /* 6.6.5 point 3. set HBPP to ceil(log2(HNUMPATS)): */
+ HNUMPATS = HPATS->n_patterns;
HBPP = 0;
while (HNUMPATS > (1U << ++HBPP));
@@ -486,35 +501,42 @@
/* 6.6.5 point 4. decode gray-scale image as mentioned in annex C */
GI = jbig2_decode_gray_scale_image(ctx, segment, data, size,
params->HMMR, params->HGW, params->HGH, HBPP, params->HENABLESKIP, HSKIP, params->HTEMPLATE, GB_stats);
- if (!GI)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to acquire gray-scale image, skipping halftone image");
+ if (!GI) {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to acquire gray-scale image, skipping halftone image");
+ goto cleanup;
+ }
/* 6.6.5 point 5. place patterns with procedure mentioned in 6.6.5.2 */
for (mg = 0; mg < params->HGH; ++mg) {
for (ng = 0; ng < params->HGW; ++ng) {
- x = (params->HGX + mg * params->HRY + ng * params->HRX) >> 8;
- y = (params->HGY + mg * params->HRX - ng * params->HRY) >> 8;
+ x = (params->HGX + mg * (int32_t) params->HRY + ng * (int32_t) params->HRX) >> 8;
+ y = (params->HGY + mg * (int32_t) params->HRX - ng * (int32_t) params->HRY) >> 8;
/* prevent pattern index >= HNUMPATS */
gray_val = GI[ng][mg];
if (gray_val >= HNUMPATS) {
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "gray-scale image uses value %d which larger than pattern dictionary", gray_val);
+ jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "gray-scale index %d out of range, using largest index", gray_val);
/* use highest available pattern */
gray_val = HNUMPATS - 1;
}
code = jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
- if (code < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose pattern with gray-scale image");
+ if (code < 0) {
+ code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose pattern with gray-scale image");
+ goto cleanup;
+ }
}
}
- /* free GI */
- for (i = 0; i < params->HGW; ++i) {
- jbig2_free(ctx->allocator, GI[i]);
+cleanup:
+ if (GI) {
+ for (i = 0; i < params->HGW; ++i) {
+ jbig2_free(ctx->allocator, GI[i]);
+ }
}
jbig2_free(ctx->allocator, GI);
+ jbig2_image_release(ctx, HSKIP);
- return 0;
+ return code;
}
/**