ref: 971100aa3b5f56756fbd31a03ca4212209881f09
parent: 98a2ac892b58569ae1a5a258c0b502fbf56da0b4
author: raph <raph@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Thu Apr 25 19:24:08 EDT 2002
Adds partial support for mmr (CCITT 2D fax) decoding. This commit can scan Huffman codes, but does not apply the logic to produce run lengths. git-svn-id: http://svn.ghostscript.com/jbig2dec/trunk@48 ded80894-8fb9-0310-811b-c03f3676ab4d
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -8,7 +8,7 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
- $Id: jbig2_generic.c,v 1.3 2002/02/19 07:09:16 giles Exp $
+ $Id: jbig2_generic.c,v 1.4 2002/04/25 23:24:08 raph Exp $
*/
/**
@@ -26,6 +26,7 @@
#include "jbig2_priv.h"
#include "jbig2_arith.h"
#include "jbig2_generic.h"
+#include "jbig2_mmr.h"
typedef struct {int32_t width;
@@ -171,19 +172,157 @@
return 0;
}
+static int
+jbig2_decode_generic_template2(Jbig2Ctx *ctx,
+ int32_t seg_number,
+ const Jbig2GenericRegionParams *params,
+ Jbig2ArithState *as,
+ byte *gbreg,
+ Jbig2ArithCx *GB_stats)
+{+ int GBW = params->GBW;
+ int rowstride = (GBW + 7) >> 3;
+ int x, y;
+ byte *gbreg_line = gbreg;
+ bool LTP = 0;
+
+ /* todo: currently we only handle the nominal gbat location */
+
+#ifdef OUTPUT_PBM
+ printf("P4\n%d %d\n", GBW, params->GBH);+#endif
+
+ for (y = 0; y < params->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]);
+ 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;
+ }
+#ifdef OUTPUT_PBM
+ fwrite(gbreg_line, 1, rowstride, stdout);
+#endif
+ gbreg_line += rowstride;
+ }
+
+ return 0;
+}
+
+static int
+jbig2_decode_generic_template2a(Jbig2Ctx *ctx,
+ int32_t seg_number,
+ const Jbig2GenericRegionParams *params,
+ Jbig2ArithState *as,
+ byte *gbreg,
+ Jbig2ArithCx *GB_stats)
+{+ int GBW = params->GBW;
+ int rowstride = (GBW + 7) >> 3;
+ int x, y;
+ byte *gbreg_line = gbreg;
+ bool LTP = 0;
+
+ /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
+
+#ifdef OUTPUT_PBM
+ printf("P4\n%d %d\n", GBW, params->GBH);+#endif
+
+ for (y = 0; y < params->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) & 0x78) | ((line_m1 >> 2) & 0x4) | ((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]);
+ result |= bit << (7 - x_minor);
+ CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
+ ((line_m1 >> (10 - x_minor)) & 0x8) |
+ ((line_m1 >> (9 - x_minor)) & 0x4) |
+ ((line_m2 >> (10 - x_minor)) & 0x80);
+ }
+ gbreg_line[x >> 3] = result;
+ }
+#ifdef OUTPUT_PBM
+ fwrite(gbreg_line, 1, rowstride, stdout);
+#endif
+ gbreg_line += rowstride;
+ }
+
+ return 0;
+}
+
/**
* jbig2_decode_generic_region: Decode a generic region.
* @ctx: The context for allocation and error reporting.
* @params: Parameters, as specified in Table 2.
- * @data: The input data.
- * @size: The size of the input data, in bytes.
+ * @as: Arithmetic decoder state.
* @gbreg: Where to store the decoded data.
+ * @GB_stats: Arithmetic stats.
*
* Decodes a generic region, according to section 6.2. The caller should
* have allocated the memory for @gbreg, which is packed 8 pixels to a
* byte, scanlines aligned to one byte boundaries.
*
- * Todo: I think the stats need to be an argument.
+ * Because this API is based on an arithmetic decoding state, it is
+ * not suitable for MMR decoding.
*
* Return code: 0 on success.
**/
@@ -201,6 +340,15 @@
else if (!params->MMR && params->GBTEMPLATE == 1)
return jbig2_decode_generic_template1(ctx, seg_number,
params, as, gbreg, GB_stats);
+ else if (!params->MMR && params->GBTEMPLATE == 2)
+ {+ if (params->gbat[0] == 3 && params->gbat[1] == 255)
+ return jbig2_decode_generic_template2a(ctx, seg_number,
+ params, as, gbreg, GB_stats);
+ else
+ return jbig2_decode_generic_template2(ctx, seg_number,
+ params, as, gbreg, GB_stats);
+ }
{int i;
for (i = 0; i < 8; i++)
@@ -284,21 +432,27 @@
gbreg = jbig2_alloc(ctx->allocator, ((rsi.width + 7) >> 3) * rsi.height);
- ws = jbig2_word_stream_buf_new(ctx,
- segment_data + offset,
- sh->data_length - offset);
- as = jbig2_arith_new(ctx, ws);
- if (!params.MMR)
+ if (params.MMR)
{+ code = jbig2_decode_generic_mmr(ctx, sh->segment_number, ¶ms,
+ segment_data + offset, sh->data_length - offset,
+ gbreg);
+ }
+ else
+ {int stats_size = params.GBTEMPLATE == 0 ? 65536 :
params.GBTEMPLATE == 1 ? 8192 : 1024;
GB_stats = jbig2_alloc(ctx->allocator, stats_size);
memset(GB_stats, 0, stats_size);
- }
- code = jbig2_decode_generic_region(ctx, sh->segment_number, ¶ms,
- as, gbreg, GB_stats);
+ ws = jbig2_word_stream_buf_new(ctx,
+ segment_data + offset,
+ sh->data_length - offset);
+ as = jbig2_arith_new(ctx, ws);
+ code = jbig2_decode_generic_region(ctx, sh->segment_number, ¶ms,
+ as, gbreg, GB_stats);
+ }
/* todo: stash gbreg as segment result */
/* todo: free ws, as */
--- /dev/null
+++ b/jbig2_mmr.c
@@ -1,0 +1,812 @@
+/* An implementation of MMR decoding. This is based on the implementation
+ in Ghostscript.
+*/
+
+#include <stdint.h>
+#include <stddef.h>
+#ifdef OUTPUT_PBM
+#include <stdio.h>
+#endif
+#include "jbig2.h"
+#include "jbig2_priv.h"
+#include "jbig2_arith.h"
+#include "jbig2_generic.h"
+#include "jbig2_mmr.h"
+
+typedef struct {+ int width;
+ int height;
+ const byte *data;
+ size_t size;
+ int data_index;
+ int bit_index;
+ uint32_t word;
+} Jbig2MmrCtx;
+
+
+static void
+jbig2_decode_mmr_init(Jbig2MmrCtx *mmr, int width, int height,
+ const byte *data, size_t size)
+{+ int i;
+ uint32_t word = 0;
+
+ mmr->width = width;
+ mmr->height = height;
+ mmr->data = data;
+ mmr->size = size;
+ mmr->data_index = 0;
+ mmr->bit_index = 0;
+ for (i = 0; i < size && i < 4; i++)
+ word |= (data[i] << ((3 - i) << 3));
+ mmr->word = word;
+
+}
+
+static void
+jbig2_decode_mmr_consume(Jbig2MmrCtx *mmr, int n_bits)
+{+ mmr->word <<= n_bits;
+ mmr->bit_index += n_bits;
+ while (mmr->bit_index >= 8)
+ {+ mmr->bit_index -= 8;
+ if (mmr->data_index + 4 < mmr->size)
+ mmr->word |= (mmr->data[mmr->data_index + 4] << mmr->bit_index);
+ mmr->data_index++;
+ }
+}
+
+typedef struct {+ int val;
+ int n_bits;
+} cfd_node;
+
+const cfd_node cf_white_decode[] = {+ { 256, 12 },+ { 272, 12 },+ { 29, 8 },+ { 30, 8 },+ { 45, 8 },+ { 46, 8 },+ { 22, 7 },+ { 22, 7 },+ { 23, 7 },+ { 23, 7 },+ { 47, 8 },+ { 48, 8 },+ { 13, 6 },+ { 13, 6 },+ { 13, 6 },+ { 13, 6 },+ { 20, 7 },+ { 20, 7 },+ { 33, 8 },+ { 34, 8 },+ { 35, 8 },+ { 36, 8 },+ { 37, 8 },+ { 38, 8 },+ { 19, 7 },+ { 19, 7 },+ { 31, 8 },+ { 32, 8 },+ { 1, 6 },+ { 1, 6 },+ { 1, 6 },+ { 1, 6 },+ { 12, 6 },+ { 12, 6 },+ { 12, 6 },+ { 12, 6 },+ { 53, 8 },+ { 54, 8 },+ { 26, 7 },+ { 26, 7 },+ { 39, 8 },+ { 40, 8 },+ { 41, 8 },+ { 42, 8 },+ { 43, 8 },+ { 44, 8 },+ { 21, 7 },+ { 21, 7 },+ { 28, 7 },+ { 28, 7 },+ { 61, 8 },+ { 62, 8 },+ { 63, 8 },+ { 0, 8 },+ { 320, 8 },+ { 384, 8 },+ { 10, 5 },+ { 10, 5 },+ { 10, 5 },+ { 10, 5 },+ { 10, 5 },+ { 10, 5 },+ { 10, 5 },+ { 10, 5 },+ { 11, 5 },+ { 11, 5 },+ { 11, 5 },+ { 11, 5 },+ { 11, 5 },+ { 11, 5 },+ { 11, 5 },+ { 11, 5 },+ { 27, 7 },+ { 27, 7 },+ { 59, 8 },+ { 60, 8 },+ { 288, 9 },+ { 290, 9 },+ { 18, 7 },+ { 18, 7 },+ { 24, 7 },+ { 24, 7 },+ { 49, 8 },+ { 50, 8 },+ { 51, 8 },+ { 52, 8 },+ { 25, 7 },+ { 25, 7 },+ { 55, 8 },+ { 56, 8 },+ { 57, 8 },+ { 58, 8 },+ { 192, 6 },+ { 192, 6 },+ { 192, 6 },+ { 192, 6 },+ { 1664, 6 },+ { 1664, 6 },+ { 1664, 6 },+ { 1664, 6 },+ { 448, 8 },+ { 512, 8 },+ { 292, 9 },+ { 640, 8 },+ { 576, 8 },+ { 294, 9 },+ { 296, 9 },+ { 298, 9 },+ { 300, 9 },+ { 302, 9 },+ { 256, 7 },+ { 256, 7 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 2, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 3, 4 },+ { 128, 5 },+ { 128, 5 },+ { 128, 5 },+ { 128, 5 },+ { 128, 5 },+ { 128, 5 },+ { 128, 5 },+ { 128, 5 },+ { 8, 5 },+ { 8, 5 },+ { 8, 5 },+ { 8, 5 },+ { 8, 5 },+ { 8, 5 },+ { 8, 5 },+ { 8, 5 },+ { 9, 5 },+ { 9, 5 },+ { 9, 5 },+ { 9, 5 },+ { 9, 5 },+ { 9, 5 },+ { 9, 5 },+ { 9, 5 },+ { 16, 6 },+ { 16, 6 },+ { 16, 6 },+ { 16, 6 },+ { 17, 6 },+ { 17, 6 },+ { 17, 6 },+ { 17, 6 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 4, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 14, 6 },+ { 14, 6 },+ { 14, 6 },+ { 14, 6 },+ { 15, 6 },+ { 15, 6 },+ { 15, 6 },+ { 15, 6 },+ { 64, 5 },+ { 64, 5 },+ { 64, 5 },+ { 64, 5 },+ { 64, 5 },+ { 64, 5 },+ { 64, 5 },+ { 64, 5 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { 7, 4 },+ { -2, 3 },+ { -2, 3 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -3, 4 },+ { 1792, 3 },+ { 1792, 3 },+ { 1984, 4 },+ { 2048, 4 },+ { 2112, 4 },+ { 2176, 4 },+ { 2240, 4 },+ { 2304, 4 },+ { 1856, 3 },+ { 1856, 3 },+ { 1920, 3 },+ { 1920, 3 },+ { 2368, 4 },+ { 2432, 4 },+ { 2496, 4 },+ { 2560, 4 },+ { 1472, 1 },+ { 1536, 1 },+ { 1600, 1 },+ { 1728, 1 },+ { 704, 1 },+ { 768, 1 },+ { 832, 1 },+ { 896, 1 },+ { 960, 1 },+ { 1024, 1 },+ { 1088, 1 },+ { 1152, 1 },+ { 1216, 1 },+ { 1280, 1 },+ { 1344, 1 },+ { 1408, 1 }+};
+
+/* Black decoding table. */
+const cfd_node cf_black_decode[] = {+ { 128, 12 },+ { 160, 13 },+ { 224, 12 },+ { 256, 12 },+ { 10, 7 },+ { 11, 7 },+ { 288, 12 },+ { 12, 7 },+ { 9, 6 },+ { 9, 6 },+ { 8, 6 },+ { 8, 6 },+ { 7, 5 },+ { 7, 5 },+ { 7, 5 },+ { 7, 5 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 6, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 5, 4 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 1, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 4, 3 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 3, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { 2, 2 },+ { -2, 4 },+ { -2, 4 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -1, 0 },+ { -3, 5 },+ { 1792, 4 },+ { 1792, 4 },+ { 1984, 5 },+ { 2048, 5 },+ { 2112, 5 },+ { 2176, 5 },+ { 2240, 5 },+ { 2304, 5 },+ { 1856, 4 },+ { 1856, 4 },+ { 1920, 4 },+ { 1920, 4 },+ { 2368, 5 },+ { 2432, 5 },+ { 2496, 5 },+ { 2560, 5 },+ { 18, 3 },+ { 18, 3 },+ { 18, 3 },+ { 18, 3 },+ { 18, 3 },+ { 18, 3 },+ { 18, 3 },+ { 18, 3 },+ { 52, 5 },+ { 52, 5 },+ { 640, 6 },+ { 704, 6 },+ { 768, 6 },+ { 832, 6 },+ { 55, 5 },+ { 55, 5 },+ { 56, 5 },+ { 56, 5 },+ { 1280, 6 },+ { 1344, 6 },+ { 1408, 6 },+ { 1472, 6 },+ { 59, 5 },+ { 59, 5 },+ { 60, 5 },+ { 60, 5 },+ { 1536, 6 },+ { 1600, 6 },+ { 24, 4 },+ { 24, 4 },+ { 24, 4 },+ { 24, 4 },+ { 25, 4 },+ { 25, 4 },+ { 25, 4 },+ { 25, 4 },+ { 1664, 6 },+ { 1728, 6 },+ { 320, 5 },+ { 320, 5 },+ { 384, 5 },+ { 384, 5 },+ { 448, 5 },+ { 448, 5 },+ { 512, 6 },+ { 576, 6 },+ { 53, 5 },+ { 53, 5 },+ { 54, 5 },+ { 54, 5 },+ { 896, 6 },+ { 960, 6 },+ { 1024, 6 },+ { 1088, 6 },+ { 1152, 6 },+ { 1216, 6 },+ { 64, 3 },+ { 64, 3 },+ { 64, 3 },+ { 64, 3 },+ { 64, 3 },+ { 64, 3 },+ { 64, 3 },+ { 64, 3 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 13, 1 },+ { 23, 4 },+ { 23, 4 },+ { 50, 5 },+ { 51, 5 },+ { 44, 5 },+ { 45, 5 },+ { 46, 5 },+ { 47, 5 },+ { 57, 5 },+ { 58, 5 },+ { 61, 5 },+ { 256, 5 },+ { 16, 3 },+ { 16, 3 },+ { 16, 3 },+ { 16, 3 },+ { 17, 3 },+ { 17, 3 },+ { 17, 3 },+ { 17, 3 },+ { 48, 5 },+ { 49, 5 },+ { 62, 5 },+ { 63, 5 },+ { 30, 5 },+ { 31, 5 },+ { 32, 5 },+ { 33, 5 },+ { 40, 5 },+ { 41, 5 },+ { 22, 4 },+ { 22, 4 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 14, 1 },+ { 15, 2 },+ { 15, 2 },+ { 15, 2 },+ { 15, 2 },+ { 15, 2 },+ { 15, 2 },+ { 15, 2 },+ { 15, 2 },+ { 128, 5 },+ { 192, 5 },+ { 26, 5 },+ { 27, 5 },+ { 28, 5 },+ { 29, 5 },+ { 19, 4 },+ { 19, 4 },+ { 20, 4 },+ { 20, 4 },+ { 34, 5 },+ { 35, 5 },+ { 36, 5 },+ { 37, 5 },+ { 38, 5 },+ { 39, 5 },+ { 21, 4 },+ { 21, 4 },+ { 42, 5 },+ { 43, 5 },+ { 0, 3 },+ { 0, 3 },+ { 0, 3 },+ { 0, 3 }+};
+
+static int
+jbig2_decode_get_code(Jbig2MmrCtx *mmr, const cfd_node *table, int initial_bits)
+{+ uint32_t word = mmr->word;
+ int table_ix = word >> (32 - initial_bits);
+ int val = table[table_ix].val;
+ int n_bits = table[table_ix].n_bits;
+
+ if (n_bits > 8)
+ {+ int mask = (1 << (32 - initial_bits)) - 1;
+ table_ix = val + ((word & mask) >> (32 - n_bits));
+ val = table[table_ix].val;
+ n_bits = 8 + table[table_ix].n_bits + 8;
+ }
+ jbig2_decode_mmr_consume(mmr, n_bits);
+ return val;
+}
+
+static int
+jbig2_decode_get_run(Jbig2MmrCtx *mmr, const cfd_node *table, int initial_bits)
+{+ int result = 0;
+ int val;
+
+ do
+ {+ val = jbig2_decode_get_code(mmr, table, initial_bits);
+ result += val;
+ }
+ while (val >= 64);
+ return result;
+}
+
+static void
+jbig2_decode_mmr_line(Jbig2MmrCtx *mmr, const byte *ref, byte *dst)
+{+ int a0 = 0;
+
+ while (1)
+ {+ uint32_t word = mmr->word;
+ printf ("%08x\n", word);+ if ((word >> (32 - 3)) == 1)
+ {+ int white_run, black_run;
+
+ jbig2_decode_mmr_consume(mmr, 3);
+ white_run = jbig2_decode_get_run(mmr, cf_white_decode, 8);
+ black_run = jbig2_decode_get_run(mmr, cf_black_decode, 7);
+ printf ("H %d %d\n", white_run, black_run);+ }
+ else if ((word >> (32 - 4)) == 1)
+ {+ printf ("P\n");+ jbig2_decode_mmr_consume(mmr, 3);
+ }
+ else if ((word >> (32 - 1)) == 1)
+ {+ printf ("V(0)\n");+ jbig2_decode_mmr_consume(mmr, 1);
+ }
+ else if ((word >> (32 - 3)) == 3)
+ {+ printf ("VR(1)\n");+ jbig2_decode_mmr_consume(mmr, 3);
+ }
+ else if ((word >> (32 - 6)) == 3)
+ {+ printf ("VR(2)\n");+ jbig2_decode_mmr_consume(mmr, 6);
+ }
+ else if ((word >> (32 - 7)) == 3)
+ {+ printf ("VR(3)\n");+ jbig2_decode_mmr_consume(mmr, 7);
+ }
+ else if ((word >> (32 - 3)) == 2)
+ {+ printf ("VL(1)\n");+ jbig2_decode_mmr_consume(mmr, 3);
+ }
+ else if ((word >> (32 - 6)) == 2)
+ {+ printf ("VL(2)\n");+ jbig2_decode_mmr_consume(mmr, 6);
+ }
+ else if ((word >> (32 - 7)) == 2)
+ {+ printf ("VL(3)\n");+ jbig2_decode_mmr_consume(mmr, 7);
+ }
+ else
+ break;
+ }
+}
+
+int
+jbig2_decode_generic_mmr(Jbig2Ctx *ctx,
+ int32_t seg_number,
+ const Jbig2GenericRegionParams *params,
+ const byte *data, size_t size,
+ byte *gbreg)
+{+ Jbig2MmrCtx mmr;
+ int rowstride = (params->GBW + 7) >> 3;
+ const byte *gbreg_line = gbreg;
+ int y;
+
+ jbig2_decode_mmr_init(&mmr, params->GBW, params->GBH, data, size);
+
+ for (y = 0; y < params->GBH; y++)
+ {+ jbig2_decode_mmr_line(&mmr, gbreg_line);
+ gbreg_line += rowstride;
+ }
+}
--- /dev/null
+++ b/jbig2_mmr.h
@@ -1,0 +1,7 @@
+int
+jbig2_decode_generic_mmr(Jbig2Ctx *ctx,
+ int32_t seg_number,
+ const Jbig2GenericRegionParams *params,
+ const byte *data, size_t size,
+ byte *gbreg);
+
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -135,6 +135,7 @@
/* 6.5.5 (4c.iv) */
NSYMSDECODED = NSYMSDECODED + 1;
+ printf ("%d of %d decoded\n", NSYMSDECODED, params->SDNUMNEWSYMS);}
}
@@ -164,14 +165,17 @@
params.SDTEMPLATE = (flags >> 10) & 3;
params.SDRTEMPLATE = (flags >> 12) & 1;
+ if (params.SDHUFF)
+ return 0;
+
/* FIXME: there are quite a few of these conditions to check */
/* maybe #ifdef CONFORMANCE and a separate routine */
- if(!params.SDHUFF && (flags & 0x0006))
+ if(!params.SDHUFF && (flags & 0x000c))
{jbig2_error(ctx, JBIG2_SEVERITY_WARNING, sh->segment_number,
"SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
}
- if(!params.SDHUFF && (flags & 0x0018))
+ if(!params.SDHUFF && (flags & 0x0030))
{jbig2_error(ctx, JBIG2_SEVERITY_WARNING, sh->segment_number,
"SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
--
⑨