shithub: jbig2

Download patch

ref: 14ae8a7fc45563b7623d96fb22e4003ae665a093
parent: 786e185f8b438dcc55fc77c2916dee33c519ce55
author: Sebastian Rasmussen <sebras@gmail.com>
date: Sun Apr 22 21:25:34 EDT 2018

jbig2dec: Handle non-nominal adaptive pixel locations in template 2.

Optimized generic region decoders can only handle nominal
adaptive pixel locations, while the unoptimized generic region
decoders can handle them being located at any location.

Previously the optimized decode was always used regardless of the
locations of the adaptive pixels, possibly causing decoding
issues. Now an unoptimized decoder is added for template 2 and is
being used whenever the adaptive pixel locations are at non-nominal
locations.

--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -272,65 +272,41 @@
 }
 
 static int
-jbig2_decode_generic_template2(Jbig2Ctx *ctx,
+jbig2_decode_generic_template2_unopt(Jbig2Ctx *ctx,
                                Jbig2Segment *segment,
                                const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
 {
     const int GBW = image->width;
     const int GBH = image->height;
-    const int rowstride = image->stride;
+    uint32_t CONTEXT;
     int x, y;
-    byte *gbreg_line = (byte *) image->data;
+    bool bit;
     int code = 0;
 
-    /* todo: currently we only handle the nominal gbat location */
-    /* when resolved make sure to call jbig2_check_adaptive_pixel_in_field() */
+    if (pixel_outside_field(params->gbat[0], params->gbat[1]))
+        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+                           "adaptive template pixel is out of field");
 
-#ifdef OUTPUT_PBM
-    printf("P4\n%d %d\n", GBW, GBH);
-#endif
+    /* this version is generic and easy to understand, but very slow */
 
-    if (GBW <= 0)
-        return 0;
-
     for (y = 0; y < GBH; y++) {
-        uint32_t CONTEXT;
-        uint32_t line_m1;
-        uint32_t line_m2;
-        int padded_width = (GBW + 7) & -8;
-
-        line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
-        line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
-        CONTEXT = ((line_m1 >> 3) & 0x7c) | ((line_m2 >> 3) & 0x380);
-
-        /* 6.2.5.7 3d */
-        for (x = 0; x < padded_width; x += 8) {
-            byte result = 0;
-            int x_minor;
-            int minor_width = GBW - x > 8 ? 8 : GBW - x;
-
-            if (y >= 1)
-                line_m1 = (line_m1 << 8) | (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
-
-            if (y >= 2)
-                line_m2 = (line_m2 << 8) | (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4 : 0);
-
-            /* This is the speed-critical inner loop. */
-            for (x_minor = 0; x_minor < minor_width; x_minor++) {
-                bool bit;
-
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
-                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template2");
-                result |= bit << (7 - x_minor);
-                CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
-            }
-            gbreg_line[x >> 3] = result;
+        for (x = 0; x < GBW; x++) {
+            CONTEXT = 0;
+            CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
+            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 + 0, 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 + 0, y - 2) << 8;
+            CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
+            bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
+            if (code)
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling generic template0");
+            jbig2_image_set_pixel(image, x, y, bit);
         }
-#ifdef OUTPUT_PBM
-        fwrite(gbreg_line, 1, rowstride, stdout);
-#endif
-        gbreg_line += rowstride;
     }
 
     return 0;
@@ -337,7 +313,7 @@
 }
 
 static int
-jbig2_decode_generic_template2a(Jbig2Ctx *ctx,
+jbig2_decode_generic_template2(Jbig2Ctx *ctx,
                                 Jbig2Segment *segment,
                                 const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
 {
@@ -348,8 +324,6 @@
     byte *gbreg_line = (byte *) image->data;
     int code = 0;
 
-    /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
-
 #ifdef OUTPUT_PBM
     printf("P4\n%d %d\n", GBW, GBH);
 #endif
@@ -773,9 +747,9 @@
     }
     else if (!params->MMR && params->GBTEMPLATE == 2) {
         if (gbat[0] == 2 && gbat[1] == -1)
-            return jbig2_decode_generic_template2a(ctx, segment, params, as, image, GB_stats);
-        else
             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)
             return jbig2_decode_generic_template3_unopt(ctx, segment, params, as, image, GB_stats);