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 */