ref: 6515f25ce92cb589a7ed16217dffcc012e08a4ea
dir: /jbig2_mmr.c/
/* 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, Jbig2Segment *segment, const Jbig2GenericRegionParams *params, const byte *data, size_t size, Jbig2Image *image) { Jbig2MmrCtx mmr; const int rowstride = image->stride; const byte *gbreg_line = (const byte *)image->data; int y; jbig2_decode_mmr_init(&mmr, image->width, image->height, data, size); for (y = 0; y < image->height; y++) { jbig2_decode_mmr_line(&mmr, gbreg_line, NULL); gbreg_line += rowstride; } }