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.");