shithub: jbig2

Download patch

ref: c4b1d31271695d1eeda60abcd3fd540dd24d4cc0
parent: 36eea46cc5e00f504952353091210b095c7587f7
author: Sebastian Rasmussen <sebras@gmail.com>
date: Tue Apr 24 22:47:39 EDT 2018

jbig2dec: Share arithmetic/huffman decoding contexts/tables.

Previously text regions had their own arithmetic/huffman
decoding contexts/tables, separate from those used to decode
fields in the symbol dictionary itself. This is incorrect.

Annex E.3.7 describes how to reset the arithmetic coding
contexts. Only the top-level symbol dictionary decoding
procedure described in chapter 7.4.2.2 references this
annex.

Neither the symbol dictionary decoding procedure outlined
in chapter 6.5 in the specification, nor chapter 6.5.8
describing how to decode the symbol bitmap itself (and
thereby implicitly chapter 6.2 describing the generic
region decoding procedure, 6.4 explaining the text
region decoding procedure and 6.5.8.2.2 describing how to
decode bitmaps with only one symbol in the
refinement/aggregate coding) refer to annex E.3.7.

It is therefore incorrect to separate the arithmetic
integer decoding contexts from the ones used to parse
the symbol dictionary fields as the specification calls
for these to be reused.

This created a problem when decoding page 3 in the sample
bitstream in Annex H.1. More specifically in Annex H.1,
step 37 (f) xi E where the refinement flag was decoded as
3 instead of the expected 0. This was because the IAID
arithmetic coding context used in step 37 (f) xi D had
not been shared with that in step 37 (f) v as is expected
in the specification. The result was that page 3 of the
sample bitstream was never decoded. Potentially this may
also have affected other JBIG2 bitstreams.

Sharing the arithmetic coding contexts between the symbol
dictionary decoding procedure and the text region decoder
resolves the issue

--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -239,17 +239,11 @@
     int SBSYMCODELEN = 0;
     Jbig2WordStream *ws = NULL;
     Jbig2HuffmanState *hs = NULL;
-    Jbig2HuffmanTable *SDHUFFRDX = NULL;
-    Jbig2HuffmanTable *SDHUFFRDY = NULL;
-    Jbig2HuffmanTable *SBHUFFRSIZE = NULL;
     Jbig2ArithState *as = NULL;
     Jbig2ArithIntCtx *IADH = NULL;
     Jbig2ArithIntCtx *IADW = NULL;
     Jbig2ArithIntCtx *IAEX = NULL;
     Jbig2ArithIntCtx *IAAI = NULL;
-    Jbig2ArithIaidCtx *IAID = NULL;
-    Jbig2ArithIntCtx *IARDX = NULL;
-    Jbig2ArithIntCtx *IARDY = NULL;
     int code = 0;
     Jbig2SymbolDict **refagg_dicts = NULL;
     uint32_t i;
@@ -279,10 +273,11 @@
     if (params->SDHUFF) {
         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded symbol dictionary");
         hs = jbig2_huffman_new(ctx, ws);
-        SDHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
-        SDHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
-        SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
-        if (hs == NULL || SDHUFFRDX == NULL || SDHUFFRDY == NULL || SBHUFFRSIZE == NULL) {
+        tparams.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
+        tparams.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
+        tparams.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A); /* Table B.1 */
+        if (hs == NULL || tparams.SBHUFFRDX == NULL ||
+                tparams.SBHUFFRDY == NULL || tparams.SBHUFFRSIZE == NULL) {
             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate storage for symbol bitmap");
             goto cleanup;
         }
@@ -292,6 +287,18 @@
                 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not allocate storage for (%u) symbol widths", params->SDNUMNEWSYMS);
                 goto cleanup;
             }
+        } else {
+            tparams.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F);    /* Table B.6 */
+            tparams.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H);    /* Table B.8 */
+            tparams.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K);    /* Table B.11 */
+            tparams.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
+            tparams.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
+            if (tparams.SBHUFFFS == NULL || tparams.SBHUFFDS == NULL ||
+                    tparams.SBHUFFDT == NULL || tparams.SBHUFFRDW == NULL ||
+                    tparams.SBHUFFRDH == NULL) {
+                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region huffman decoder entries");
+                goto cleanup;
+            }
         }
     } else {
         IADH = jbig2_arith_int_ctx_new(ctx);
@@ -302,61 +309,33 @@
             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate storage for symbol bitmap");
             goto cleanup;
         }
-        if (params->SDREFAGG) {
-            int64_t tmp = params->SDNUMINSYMS + params->SDNUMNEWSYMS;
-
-            for (SBSYMCODELEN = 0; ((int64_t) 1 << SBSYMCODELEN) < tmp; SBSYMCODELEN++);
-            IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
-            IARDX = jbig2_arith_int_ctx_new(ctx);
-            IARDY = jbig2_arith_int_ctx_new(ctx);
-            if (IAID == NULL || IARDX == NULL || IARDY == NULL) {
-                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate storage for symbol bitmap");
-                goto cleanup;
-            }
-        }
-    }
-
-    /* First time through, we need to initialise the */
-    /* various tables for Huffman or adaptive encoding */
-    /* as well as the text region parameters structure */
-    if (params->SDHUFF) {
-        tparams.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F);    /* Table B.6 */
-        tparams.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H);    /* Table B.8 */
-        tparams.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K);    /* Table B.11 */
-        tparams.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
-        tparams.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
-        tparams.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
-        tparams.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
-        tparams.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A); /* Table B.1 */
-        if (tparams.SBHUFFFS == NULL || tparams.SBHUFFDS == NULL ||
-                tparams.SBHUFFDT == NULL || tparams.SBHUFFRDW == NULL ||
-                tparams.SBHUFFRDH == NULL || tparams.SBHUFFRDX == NULL ||
-                tparams.SBHUFFRDY == NULL || tparams.SBHUFFRSIZE == NULL) {
-            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region huffman decoder entries");
-            goto cleanup;
-        }
-    } else {
-        /* Values from Table 17, section 6.5.8.2 (2) */
-        tparams.IADT = jbig2_arith_int_ctx_new(ctx);
-        tparams.IAFS = jbig2_arith_int_ctx_new(ctx);
-        tparams.IADS = jbig2_arith_int_ctx_new(ctx);
-        tparams.IAIT = jbig2_arith_int_ctx_new(ctx);
-        /* Table 31 */
         for (SBSYMCODELEN = 0; ((uint64_t) 1 << SBSYMCODELEN) < ((uint64_t) params->SDNUMINSYMS + params->SDNUMNEWSYMS); SBSYMCODELEN++);
         tparams.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
-        tparams.IARI = jbig2_arith_int_ctx_new(ctx);
-        tparams.IARDW = jbig2_arith_int_ctx_new(ctx);
-        tparams.IARDH = jbig2_arith_int_ctx_new(ctx);
         tparams.IARDX = jbig2_arith_int_ctx_new(ctx);
         tparams.IARDY = jbig2_arith_int_ctx_new(ctx);
-        if (tparams.IADT == NULL || tparams.IAFS == NULL ||
-                tparams.IADS == NULL || tparams.IAIT == NULL ||
-                tparams.IAID == NULL || tparams.IARI == NULL ||
-                tparams.IARDW == NULL || tparams.IARDH == NULL ||
-                tparams.IARDX == NULL || tparams.IARDY == NULL) {
+        if (tparams.IAID == NULL || tparams.IARDX == NULL ||
+                tparams.IARDY == NULL) {
             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region arith decoder entries");
             goto cleanup;
         }
+        if (params->SDREFAGG) {
+            /* Values from Table 17, section 6.5.8.2 (2) */
+            tparams.IADT = jbig2_arith_int_ctx_new(ctx);
+            tparams.IAFS = jbig2_arith_int_ctx_new(ctx);
+            tparams.IADS = jbig2_arith_int_ctx_new(ctx);
+            tparams.IAIT = jbig2_arith_int_ctx_new(ctx);
+            /* Table 31 */
+            tparams.IARI = jbig2_arith_int_ctx_new(ctx);
+            tparams.IARDW = jbig2_arith_int_ctx_new(ctx);
+            tparams.IARDH = jbig2_arith_int_ctx_new(ctx);
+            if (tparams.IADT == NULL || tparams.IAFS == NULL ||
+                    tparams.IADS == NULL || tparams.IAIT == NULL ||
+                    tparams.IARI == NULL || tparams.IARDW == NULL ||
+                    tparams.IARDH == NULL) {
+                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "out of memory creating text region arith decoder entries");
+                goto cleanup;
+            }
+        }
     }
     tparams.SBHUFF = params->SDHUFF;
     tparams.SBREFINE = 1;
@@ -368,7 +347,6 @@
     tparams.SBDSOFFSET = 0;
     tparams.SBRTEMPLATE = params->SDRTEMPLATE;
 
-
     SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
     if (SDNEWSYMS == NULL) {
         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "could not allocate storage for (%u) new symbols", params->SDNUMNEWSYMS);
@@ -554,14 +532,14 @@
                         /* 6.5.8.2.2 (2, 3, 4, 5) */
                         if (params->SDHUFF) {
                             ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN, &code1);
-                            RDX = jbig2_huffman_get(hs, SDHUFFRDX, &code2);
-                            RDY = jbig2_huffman_get(hs, SDHUFFRDY, &code3);
-                            BMSIZE = jbig2_huffman_get(hs, SBHUFFRSIZE, &code4);
+                            RDX = jbig2_huffman_get(hs, tparams.SBHUFFRDX, &code2);
+                            RDY = jbig2_huffman_get(hs, tparams.SBHUFFRDY, &code3);
+                            BMSIZE = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code4);
                             code5 = jbig2_huffman_skip(hs);
                         } else {
-                            code1 = jbig2_arith_iaid_decode(ctx, IAID, as, (int32_t *) & ID);
-                            code2 = jbig2_arith_int_decode(ctx, IARDX, as, &RDX);
-                            code3 = jbig2_arith_int_decode(ctx, IARDY, as, &RDY);
+                            code1 = jbig2_arith_iaid_decode(ctx, tparams.IAID, as, (int32_t *) & ID);
+                            code2 = jbig2_arith_int_decode(ctx, tparams.IARDX, as, &RDX);
+                            code3 = jbig2_arith_int_decode(ctx, tparams.IARDY, as, &RDY);
                         }
 
                         if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0) {
@@ -771,7 +749,7 @@
 
         while (i < limit) {
             if (params->SDHUFF)
-                EXRUNLENGTH = jbig2_huffman_get(hs, SBHUFFRSIZE, &code);
+                EXRUNLENGTH = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code);
             else
                 code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *) &EXRUNLENGTH);
             if (code < 0) {
@@ -816,6 +794,13 @@
 cleanup:
     jbig2_image_release(ctx, glyph);
     jbig2_image_release(ctx, image);
+    if (refagg_dicts != NULL) {
+        if (refagg_dicts[0] != NULL)
+            jbig2_sd_release(ctx, refagg_dicts[0]);
+        /* skip releasing refagg_dicts[1] as that is the same as SDNEWSYMS */
+        jbig2_free(ctx->allocator, refagg_dicts);
+    }
+    jbig2_sd_release(ctx, SDNEWSYMS);
     if (params->SDHUFF) {
         jbig2_release_huffman_table(ctx, tparams.SBHUFFRSIZE);
         jbig2_release_huffman_table(ctx, tparams.SBHUFFRDY);
@@ -825,6 +810,10 @@
         jbig2_release_huffman_table(ctx, tparams.SBHUFFDT);
         jbig2_release_huffman_table(ctx, tparams.SBHUFFDS);
         jbig2_release_huffman_table(ctx, tparams.SBHUFFFS);
+        if (!params->SDREFAGG) {
+            jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
+        }
+        jbig2_huffman_free(ctx, hs);
     } else {
         jbig2_arith_int_ctx_free(ctx, tparams.IARDY);
         jbig2_arith_int_ctx_free(ctx, tparams.IARDX);
@@ -836,28 +825,6 @@
         jbig2_arith_int_ctx_free(ctx, tparams.IADS);
         jbig2_arith_int_ctx_free(ctx, tparams.IAFS);
         jbig2_arith_int_ctx_free(ctx, tparams.IADT);
-    }
-    if (refagg_dicts != NULL) {
-        if (refagg_dicts[0] != NULL)
-            jbig2_sd_release(ctx, refagg_dicts[0]);
-        /* skip releasing refagg_dicts[1] as that is the same as SDNEWSYMS */
-        jbig2_free(ctx->allocator, refagg_dicts);
-    }
-    jbig2_sd_release(ctx, SDNEWSYMS);
-    if (params->SDHUFF) {
-        if (!params->SDREFAGG) {
-            jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
-        }
-        jbig2_release_huffman_table(ctx, SBHUFFRSIZE);
-        jbig2_release_huffman_table(ctx, SDHUFFRDY);
-        jbig2_release_huffman_table(ctx, SDHUFFRDX);
-        jbig2_huffman_free(ctx, hs);
-    } else {
-        if (params->SDREFAGG) {
-            jbig2_arith_iaid_ctx_free(ctx, IAID);
-            jbig2_arith_int_ctx_free(ctx, IARDX);
-            jbig2_arith_int_ctx_free(ctx, IARDY);
-        }
         jbig2_arith_int_ctx_free(ctx, IAAI);
         jbig2_arith_int_ctx_free(ctx, IAEX);
         jbig2_arith_int_ctx_free(ctx, IADW);