shithub: jbig2

Download patch

ref: cc3a563ea709064bf47147bd817a962e368a5c2a
parent: 34b95add346fa8b27064e007da4e86eadc466bbd
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Wed May 11 03:14:25 EDT 2005

Export the pre-defined huffman tables for external use.

Read the huffman fields of the symbol dictionary header and allocate
appropriate tables and decoder context. This is a prerequisite for
handling huffman-coded symbol dicts.i

Part of the fix for bug 688009.


git-svn-id: http://svn.ghostscript.com/jbig2dec/trunk@405 ded80894-8fb9-0310-811b-c03f3676ab4d

--- a/jbig2_huffman.c
+++ b/jbig2_huffman.c
@@ -17,7 +17,7 @@
 */
 
 /* Huffman table decoding procedures 
-    -- See Annex B of the JBIG2 draft spec */
+    -- See Annex B of the JBIG2 specification */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -164,6 +164,9 @@
 
 #define LOG_TABLE_SIZE_MAX 8
 
+/** Build an in-memory representation of a Huffman table from the
+ *  set of template params provided by the spec or a table segment
+ */ 
 Jbig2HuffmanTable *
 jbig2_build_huffman_table (Jbig2Ctx *ctx, const Jbig2HuffmanParams *params)
 {
@@ -263,6 +266,17 @@
     }
 
   return result;
+}
+
+/** Free the memory associated with the representation of table */
+void
+jbig2_release_huffman_table (Jbig2Ctx *ctx, Jbig2HuffmanTable *table)
+{
+  if (table != NULL) {
+      jbig2_free(ctx->allocator, table->entries);
+      jbig2_free(ctx->allocator, table);
+  }
+  return;
 }
 
 #ifdef TEST
--- a/jbig2_huffman.h
+++ b/jbig2_huffman.h
@@ -26,6 +26,35 @@
 typedef struct _Jbig2HuffmanTable Jbig2HuffmanTable;
 typedef struct _Jbig2HuffmanParams Jbig2HuffmanParams;
 
+struct _Jbig2HuffmanEntry {
+  union {
+    int32_t RANGELOW;
+    Jbig2HuffmanTable *ext_table;
+  } u;
+  byte PREFLEN;
+  byte RANGELEN;
+  byte flags;
+};
+
+struct _Jbig2HuffmanTable {
+  int log_table_size;
+  Jbig2HuffmanEntry *entries;
+};
+
+typedef struct _Jbig2HuffmanLine Jbig2HuffmanLine;
+
+struct _Jbig2HuffmanLine {
+  int PREFLEN;
+  int RANGELEN;
+  int RANGELOW;
+};
+
+struct _Jbig2HuffmanParams {
+  bool HTOOB;
+  int n_lines;
+  const Jbig2HuffmanLine *lines;
+};
+
 Jbig2HuffmanState *
 jbig2_huffman_new (Jbig2Ctx *ctx, Jbig2WordStream *ws);
 
@@ -37,7 +66,27 @@
 		   const Jbig2HuffmanTable *table, bool *oob);
 
 Jbig2HuffmanTable *
-jbig2_build_huffman_table (Jbig2Ctx *ctx,
-			   const Jbig2HuffmanParams *params);
+jbig2_build_huffman_table (Jbig2Ctx *ctx, const Jbig2HuffmanParams *params);
+
+void
+jbig2_release_huffman_table (Jbig2Ctx *ctx, Jbig2HuffmanTable *table);
+
+/* standard Huffman templates defined by the specification */
+extern const Jbig2HuffmanParams jbig2_huffman_params_A; /* Table B.1  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_B; /* Table B.2  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_C; /* Table B.3  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_D; /* Table B.4  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_E; /* Table B.5  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_F; /* Table B.6  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_G; /* Table B.7  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_H; /* Table B.8  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_I; /* Table B.9  */
+extern const Jbig2HuffmanParams jbig2_huffman_params_J; /* Table B.10 */
+extern const Jbig2HuffmanParams jbig2_huffman_params_K; /* Table B.11 */
+extern const Jbig2HuffmanParams jbig2_huffman_params_L; /* Table B.12 */
+extern const Jbig2HuffmanParams jbig2_huffman_params_M; /* Table B.13 */
+extern const Jbig2HuffmanParams jbig2_huffman_params_J; /* Table B.14 */
+extern const Jbig2HuffmanParams jbig2_huffman_params_O; /* Table B.15 */
+
 
 #endif /* JBIG2_HUFFMAN_H */
--- a/jbig2_hufftab.h
+++ b/jbig2_hufftab.h
@@ -17,7 +17,7 @@
 */
 
 /* predefined Huffman table definitions 
-    -- See Annex B of the JBIG2 draft spec */
+    -- See Annex B of the JBIG2 specification */
 
 #ifndef JBIG2_HUFFTAB_H
 #define JBIG2_HUFFTAB_H
@@ -24,38 +24,10 @@
 
 /* types are in jbig2_huffman.h, you must include that first */
 
-struct _Jbig2HuffmanEntry {
-  union {
-    int32_t RANGELOW;
-    Jbig2HuffmanTable *ext_table;
-  } u;
-  byte PREFLEN;
-  byte RANGELEN;
-  byte flags;
-};
 
-struct _Jbig2HuffmanTable {
-  int log_table_size;
-  Jbig2HuffmanEntry *entries;
-};
-
-typedef struct _Jbig2HuffmanLine Jbig2HuffmanLine;
-
-struct _Jbig2HuffmanLine {
-  int PREFLEN;
-  int RANGELEN;
-  int RANGELOW;
-};
-
-struct _Jbig2HuffmanParams {
-  bool HTOOB;
-  int n_lines;
-  const Jbig2HuffmanLine *lines;
-};
-
 /* Table B.1 */
 const Jbig2HuffmanLine
-jbig_huffman_lines_A[] = {
+jbig2_huffman_lines_A[] = {
   { 1, 4, 0 },
   { 2, 8, 16 },
   { 3, 16, 272 },
@@ -64,11 +36,11 @@
 };
 
 const Jbig2HuffmanParams
-jbig_huffman_params_A = { FALSE, 5, jbig_huffman_lines_A };
+jbig2_huffman_params_A = { FALSE, 5, jbig2_huffman_lines_A };
 
 /* Table B.2 */
 const Jbig2HuffmanLine
-jbig_huffman_lines_B[] = {
+jbig2_huffman_lines_B[] = {
   { 1, 0, 0 },
   { 2, 0, 1 },
   { 3, 0, 2 },
@@ -80,11 +52,11 @@
 };
 
 const Jbig2HuffmanParams
-jbig_huffman_params_B = { TRUE, 8, jbig_huffman_lines_B };
+jbig2_huffman_params_B = { TRUE, 8, jbig2_huffman_lines_B };
 
 /* Table B.3 */
 const Jbig2HuffmanLine
-jbig_huffman_lines_C[] = {
+jbig2_huffman_lines_C[] = {
   { 8, 8, -256 },
   { 1, 0, 0 },
   { 2, 0, 1 },
@@ -97,11 +69,11 @@
 };
 
 const Jbig2HuffmanParams
-jbig_huffman_params_C = { TRUE, 9, jbig_huffman_lines_C };
+jbig2_huffman_params_C = { TRUE, 9, jbig2_huffman_lines_C };
 
 /* Table B.4 */
 const Jbig2HuffmanLine
-jbig_huffman_lines_D[] = {
+jbig2_huffman_lines_D[] = {
   { 1, 0, 1 },
   { 2, 0, 2 },
   { 3, 0, 3 },
@@ -112,11 +84,11 @@
 };
 
 const Jbig2HuffmanParams
-jbig_huffman_params_D = { FALSE, 7, jbig_huffman_lines_D };
+jbig2_huffman_params_D = { FALSE, 7, jbig2_huffman_lines_D };
 
 /* Table B.5 */
 const Jbig2HuffmanLine
-jbig_huffman_lines_E[] = {
+jbig2_huffman_lines_E[] = {
 	{7, 8, -255},
 	{1, 0, 1},
 	{2, 0, 2},
@@ -128,11 +100,11 @@
 };
 
 const Jbig2HuffmanParams
-jbig_huffman_params_E = { FALSE, 8, jbig_huffman_lines_E };
+jbig2_huffman_params_E = { FALSE, 8, jbig2_huffman_lines_E };
 
 /* Table B.14 */
 const Jbig2HuffmanLine
-jbig_huffman_lines_N[] = {
+jbig2_huffman_lines_N[] = {
   { 3, 0, -2 },
   { 3, 0, -1 },
   { 1, 0, 0 },
@@ -143,7 +115,7 @@
 };
 
 const Jbig2HuffmanParams
-jbig_huffman_params_N = { FALSE, 7, jbig_huffman_lines_N };
+jbig2_huffman_params_N = { FALSE, 7, jbig2_huffman_lines_N };
 
 
 #endif /* JBIG2_HUFFTAB_H */
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -48,10 +48,10 @@
   Jbig2SymbolDict *SDINSYMS;
   uint32_t SDNUMNEWSYMS;
   uint32_t SDNUMEXSYMS;
-  /* SDHUFFDH */
-  /* SDHUFFDW */
-  /* SDHUFFBMSIZE */
-  /* SDHUFFAGGINST */
+  Jbig2HuffmanTable *SDHUFFDH;
+  Jbig2HuffmanTable *SDHUFFDW;
+  Jbig2HuffmanTable *SDHUFFBMSIZE;
+  Jbig2HuffmanTable *SDHUFFAGGINST;
   int SDTEMPLATE;
   int8_t sdat[8];
   bool SDRTEMPLATE;
@@ -218,6 +218,7 @@
   uint32_t NSYMSDECODED;
   int32_t SYMWIDTH, TOTWIDTH;
   uint32_t HCFIRSTSYM;
+  uint32_t *SDNEWSYMWIDTHS = NULL;
   Jbig2WordStream *ws = NULL;
   Jbig2HuffmanState *hs = NULL;
   Jbig2ArithState *as = NULL;
@@ -254,6 +255,15 @@
       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
 	"huffman coded symbol dictionary");
       hs = jbig2_huffman_new(ctx, ws);
+      if (params->SDREFAGG) {
+	  SDNEWSYMWIDTHS = jbig2_alloc(ctx->allocator,
+		sizeof(*SDNEWSYMWIDTHS)*params->SDNUMNEWSYMS);
+	  if (SDNEWSYMWIDTHS == NULL) {
+	    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+		"could not allocate storage for symbol widths");
+	    return NULL;
+	  }
+      }
   }
 
   SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
@@ -503,6 +513,9 @@
       }
       jbig2_free(ctx->allocator, as);  
   } else {
+      if (params->SDREFAGG) {
+	jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
+      }
       jbig2_free(ctx->allocator, hs);
   }
 
@@ -533,22 +546,84 @@
   params.SDTEMPLATE = (flags >> 10) & 3;
   params.SDRTEMPLATE = (flags >> 12) & 1;
 
+  params.SDHUFFDH = NULL;
+  params.SDHUFFDW = NULL;
+  params.SDHUFFBMSIZE = NULL;
+  params.SDHUFFAGGINST = NULL;
+
   if (params.SDHUFF) {
     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
         "symbol dictionary uses the Huffman encoding variant (NYI)");
-    return 0;
+    switch ((flags & 0x000c) >> 2) {
+      case 0: /* Table B.4 */
+	params.SDHUFFDH = jbig2_build_huffman_table(ctx, 
+		                       &jbig2_huffman_params_D);
+	break;
+      case 1: /* Table B.5 */
+	params.SDHUFFDH = jbig2_build_huffman_table(ctx, 
+		                       &jbig2_huffman_params_E);
+	break;
+      case 3: /* Custom table from referred segment */
+	/* We handle this case later by leaving the table as NULL */
+	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+	    "symbol dictionary uses custom DH huffman table (NYI)");
+      case 2:
+      default:
+	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+	    "symbol dictionary specified invalid huffman table");
+	break;
+    }
+    switch ((flags & 0x0030) >> 4) {
+      case 0: /* Table B.2 */
+	params.SDHUFFDW = jbig2_build_huffman_table(ctx, 
+		                       &jbig2_huffman_params_B);
+	break;
+      case 1: /* Table B.3 */
+	params.SDHUFFDW = jbig2_build_huffman_table(ctx, 
+		                       &jbig2_huffman_params_C);
+	break;
+      case 3: /* Custom table from referred segment */
+	/* We handle this case later by leaving the table as NULL */
+	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+	    "symbol dictionary uses custom DW huffman table (NYI)");
+      case 2:
+      default:
+	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+	    "symbol dictionary specified invalid huffman table");
+	break;
+    }
+    if (flags & 0x0040) {
+        /* Custom table from referred segment */
+	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+	    "symbol dictionary uses custom BMSIZE huffman table (NYI)");
+    } else {
+	/* Table B.1 */
+	params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx,
+					&jbig2_huffman_params_A);
+    }
+    if (flags & 0x0080) { 
+        /* Custom table from referred segment */
+	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+	    "symbol dictionary uses custom REFAGG huffman table (NYI)");
+    } else {
+	/* Table B.1 */
+	params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx,
+					&jbig2_huffman_params_A);
+    }
   }
 
   /* FIXME: there are quite a few of these conditions to check */
   /* maybe #ifdef CONFORMANCE and a separate routine */
-  if(!params.SDHUFF && (flags & 0x000c)) {
+  if (!params.SDHUFF) {
+    if (flags & 0x000c) {
       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
 		  "SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
-  }
-  if(!params.SDHUFF && (flags & 0x0030)) {
+    }
+    if (flags & 0x0030) {
       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
 		  "SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
-  }
+    }
+  } 
 
   if (flags & 0x0080) {
       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
@@ -628,6 +703,13 @@
 #ifdef DUMP_SYMDICT
   if (segment->result) jbig2_dump_symbol_dict(ctx, segment);
 #endif
+
+  if (params.SDHUFF) {
+      jbig2_release_huffman_table(ctx, params.SDHUFFDH);
+      jbig2_release_huffman_table(ctx, params.SDHUFFDW);
+      jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
+      jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
+  }
 
   /* todo: retain or free GB_stats, GR_stats */