#include "stdafx.h" #include "jbig2arith.h" #include #include #define u64 uint64_t #define u32 uint32_t #define u16 uint16_t #define u8 uint8_t // C++ doesn't have C99 restricted pointers, but GCC does allow __restrict__ #if !defined(WIN32) #define restrict __restrict__ #else #define restrict #endif // ----------------------------------------------------------------------------- // This the structure for a single state of the adaptive arithmetic compressor // ----------------------------------------------------------------------------- struct context { u16 qe; u8 mps, lps; }; // ----------------------------------------------------------------------------- // And this is the table of states for that adaptive compressor // ----------------------------------------------------------------------------- struct context ctbl[] = { // This is the standard state table from // Table E.1 of the standard. The switch has been omitted and // those states are included below #define STATETABLE \ {0x5601, F( 1), SWITCH(F( 1))},\ {0x3401, F( 2), F( 6)},\ {0x1801, F( 3), F( 9)},\ {0x0ac1, F( 4), F(12)},\ {0x0521, F( 5), F(29)},\ {0x0221, F(38), F(33)},\ {0x5601, F( 7), SWITCH(F( 6))},\ {0x5401, F( 8), F(14)},\ {0x4801, F( 9), F(14)},\ {0x3801, F(10), F(14)},\ {0x3001, F(11), F(17)},\ {0x2401, F(12), F(18)},\ {0x1c01, F(13), F(20)},\ {0x1601, F(29), F(21)},\ {0x5601, F(15), SWITCH(F(14))},\ {0x5401, F(16), F(14)},\ {0x5101, F(17), F(15)},\ {0x4801, F(18), F(16)},\ {0x3801, F(19), F(17)},\ {0x3401, F(20), F(18)},\ {0x3001, F(21), F(19)},\ {0x2801, F(22), F(19)},\ {0x2401, F(23), F(20)},\ {0x2201, F(24), F(21)},\ {0x1c01, F(25), F(22)},\ {0x1801, F(26), F(23)},\ {0x1601, F(27), F(24)},\ {0x1401, F(28), F(25)},\ {0x1201, F(29), F(26)},\ {0x1101, F(30), F(27)},\ {0x0ac1, F(31), F(28)},\ {0x09c1, F(32), F(29)},\ {0x08a1, F(33), F(30)},\ {0x0521, F(34), F(31)},\ {0x0441, F(35), F(32)},\ {0x02a1, F(36), F(33)},\ {0x0221, F(37), F(34)},\ {0x0141, F(38), F(35)},\ {0x0111, F(39), F(36)},\ {0x0085, F(40), F(37)},\ {0x0049, F(41), F(38)},\ {0x0025, F(42), F(39)},\ {0x0015, F(43), F(40)},\ {0x0009, F(44), F(41)},\ {0x0005, F(45), F(42)},\ {0x0001, F(45), F(43)}, #undef F #define F(x) x #define SWITCH(x) (x + 46) STATETABLE #undef SWITCH #undef F #define F(x) (x + 46) #define SWITCH(x) ((x) - 46) STATETABLE #undef SWITCH #undef F }; #if __GNUC__ >= 4 #define BRANCH_OPT #endif // GCC peephole optimisations #ifdef BRANCH_OPT #define likely(x) __builtin_expect((x),1) #define unlikely(x) __builtin_expect((x),0) #else #define likely(x) x #define unlikely(x) x #endif // see comments in .h file void jbig2enc_init(struct jbig2enc_ctx *ctx) { memset(ctx->context, 0, JBIG2_MAX_CTX); memset(ctx->intctx, 0, 13 * 512); ctx->a = 0x8000; ctx->c = 0; ctx->ct = 12; ctx->bp = -1; ctx->b = 0; ctx->outbuf_used = 0; ctx->outbuf = (u8 *) malloc(JBIG2_OUTPUTBUFFER_SIZE); ctx->output_chunks = new std::vector; ctx->iaidctx = NULL; } // see comments in .h file void jbig2enc_reset(struct jbig2enc_ctx *ctx) { ctx->a = 0x8000; ctx->c = 0; ctx->ct = 12; ctx->bp = -1; ctx->b = 0; free(ctx->iaidctx); ctx->iaidctx = NULL; memset(ctx->context, 0, JBIG2_MAX_CTX); memset(ctx->intctx, 0, 13 * 512); } // see comments in .h file void jbig2enc_flush(struct jbig2enc_ctx *ctx) { ctx->outbuf_used = 0; for (std::vector::iterator i = ctx->output_chunks->begin(); i != ctx->output_chunks->end(); ++i) { free(*i); } ctx->output_chunks->clear(); ctx->bp = -1; } // see comments in .h file void jbig2enc_dealloc(struct jbig2enc_ctx *ctx) { for (std::vector::iterator i = ctx->output_chunks->begin(); i != ctx->output_chunks->end(); ++i) { free(*i); } delete ctx->output_chunks; free(ctx->outbuf); free(ctx->iaidctx); } // ----------------------------------------------------------------------------- // Emit a byte from the compressor by appending to the current output buffer. // If the buffer is full, allocate a new one // ----------------------------------------------------------------------------- static void inline emit(struct jbig2enc_ctx *restrict ctx) { if (unlikely(ctx->outbuf_used == JBIG2_OUTPUTBUFFER_SIZE)) { ctx->output_chunks->push_back(ctx->outbuf); ctx->outbuf = (u8 *) malloc(JBIG2_OUTPUTBUFFER_SIZE); ctx->outbuf_used = 0; } ctx->outbuf[ctx->outbuf_used++] = ctx->b; } // ----------------------------------------------------------------------------- // The BYTEOUT procedure from the standard // ----------------------------------------------------------------------------- static void byteout(struct jbig2enc_ctx *restrict ctx) { if (ctx->b == 0xff) goto rblock; if (ctx->c < 0x8000000) goto lblock; ctx->b += 1; if (ctx->b != 0xff) goto lblock; ctx->c &= 0x7ffffff; rblock: if (ctx->bp >= 0) { #ifdef TRACE printf("emit %x\n", ctx->b); #endif emit(ctx); } ctx->b = ctx->c >> 20; ctx->bp++; ctx->c &= 0xfffff; ctx->ct = 7; return; lblock: if (ctx->bp >= 0) { #ifdef TRACE printf("emit %x\n", ctx->b); #endif emit(ctx); } ctx->b = ctx->c >> 19; ctx->bp++; ctx->c &= 0x7ffff; ctx->ct = 8; return; } // ----------------------------------------------------------------------------- // A merging of the ENCODE, CODELPS and CODEMPS procedures from the standard // ----------------------------------------------------------------------------- static void encode_bit(struct jbig2enc_ctx *restrict ctx, u8 *restrict context, u32 ctxnum, u8 d) { const u8 i = context[ctxnum]; const u8 mps = i > 46 ? 1 : 0; const u16 qe = ctbl[i].qe; #ifdef CODER_DEBUGGING fprintf(stderr, "B: %d %d %d %d\n", ctxnum, qe, ctx->a, d); #endif #ifdef TRACE static int ec = 0; printf("%d\t%d %d %x %x %x %d %x %d\n", ec++, i, mps, qe, ctx->a, ctx->c, ctx->ct, ctx->b, ctx->bp); #endif if (unlikely(d != mps)) goto codelps; #ifdef SURPRISE_MAP { u8 b = static_cast (((static_cast(qe) / 0xac02) * 255)); write(3, &b, 1); } #endif ctx->a -= qe; if (unlikely((ctx->a & 0x8000) == 0)) { if (unlikely(ctx->a < qe)) { ctx->a = qe; } else { ctx->c += qe; } context[ctxnum] = ctbl[i].mps; goto renorme; } else { ctx->c += qe; } return; codelps: #ifdef SURPRISE_MAP { u8 b = static_cast ((1.0f - (static_cast(qe) / 0xac02)) * 255); write(3, &b, 1); } #endif ctx->a -= qe; if (ctx->a < qe) { ctx->c += qe; } else { ctx->a = qe; } context[ctxnum] = ctbl[i].lps; renorme: do { ctx->a <<= 1; ctx->c <<= 1; ctx->ct -= 1; if (unlikely(!ctx->ct)) { byteout(ctx); } } while ((ctx->a & 0x8000) == 0); } // ----------------------------------------------------------------------------- // The FINALISE procudure from the standard // ----------------------------------------------------------------------------- static void encode_final(struct jbig2enc_ctx *restrict ctx) { // SETBITS const u32 tempc = ctx->c + ctx->a; ctx->c |= 0xffff; if (ctx->c >= tempc) { ctx->c -= 0x8000; } ctx->c <<= ctx->ct; byteout(ctx); ctx->c <<= ctx->ct; byteout(ctx); emit(ctx); if (ctx->b != 0xff) { #ifdef TRACE printf("emit 0xff\n"); #endif ctx->b = 0xff; emit(ctx); } #ifdef TRACE printf("emit 0xac\n"); #endif ctx->b = 0xac; emit(ctx); } // see comments in .h file void jbig2enc_final(struct jbig2enc_ctx *restrict ctx) { encode_final(ctx); } // ----------------------------------------------------------------------------- // When encoding integers there are a number of different cases. This structure // contains all the information for one of those cases // ----------------------------------------------------------------------------- struct intencrange_s { int bot, top; // the range of numbers for which this is valid u8 data, bits; // the bits of data to write first, and the number which are valid // These bits are taken from the bottom of the u8, in reverse order u16 delta; // the amount to subtract from the value before encoding it u8 intbits; // number of bits to use to encode the integer }; // table for how to encode integers of a given range static struct intencrange_s intencrange[] = { {0, 3, 0, 2, 0, 2}, {-1, -1, 9, 4, 0, 0}, {-3, -2, 5, 3, 2, 1}, {4, 19, 2, 3, 4, 4}, {-19,-4, 3, 3, 4, 4}, {20, 83, 6, 4, 20, 6}, {-83,-20, 7, 4, 20, 6}, {84, 339, 14,5, 84, 8}, {-339,-84,15,5, 84, 8}, {340,4435,30,6, 340, 12}, {-4435,-340,31,6,340, 12}, {4436,2000000000,62,6,4436, 32}, {-2000000000,-4436,63,6,4436, 32} }; // see comments in .h file void jbig2enc_oob(struct jbig2enc_ctx *restrict ctx, int proc) { u8 *const context = ctx->intctx[proc]; encode_bit(ctx, context, 1, 1); encode_bit(ctx, context, 3, 0); encode_bit(ctx, context, 6, 0); encode_bit(ctx, context, 12, 0); } // see comments in .h file void jbig2enc_int(struct jbig2enc_ctx *restrict ctx, int proc, int value) { u8 *const context = ctx->intctx[proc]; int i; if (value > 2000000000 || value < -2000000000) abort(); u32 prev = 1; for (i = 0; ; ++i) { if (intencrange[i].bot <= value && intencrange[i].top >= value) break; } if (value < 0) value = -value; value -= intencrange[i].delta; u8 data = intencrange[i].data; for (int j = 0; j < intencrange[i].bits; ++j) { const u8 v = data & 1; encode_bit(ctx, context, prev, v); data >>= 1; if (prev & 0x100) { // prev > 256 prev = (((prev << 1) | v) & 0x1ff) | 0x100; } else { prev = (prev << 1) | v; } } // move the data in value to the top of the word value <<= (32 - intencrange[i].intbits); for (int j = 0; j < intencrange[i].intbits; ++j) { const u8 v = (value & 0x80000000) >> 31; encode_bit(ctx, context, prev, v); // roll the next bit into place value <<= 1; if (prev & 0x100) { // prev > 256 prev = (((prev << 1) | v) & 0x1ff) | 0x100; } else { prev = (prev << 1) | v; } } } // see comments in .h file void jbig2enc_iaid(struct jbig2enc_ctx *restrict ctx, int symcodelen, int value) { if (!ctx->iaidctx) { // we've not yet allocated the context index buffer for this ctx->iaidctx = (u8 *) malloc(1 << symcodelen); memset(ctx->iaidctx, 0, 1 << symcodelen); } const u32 mask = (1 << (symcodelen + 1)) - 1; value <<= (32 - symcodelen); // roll the data to the top of the word u32 prev = 1; for (int i = 0; i < symcodelen; ++i) { const u32 tval = prev & mask; const u8 v = (value & 0x80000000) >> 31; encode_bit(ctx, ctx->iaidctx, tval, v); prev = (prev << 1) | v; value <<= 1; } } // This is the test input to the coder as given in the standard (H.2) static const u8 input[] = { 0, 2, 0, 0x51, 0, 0, 0, 0xc0, 0x03, 0x52, 0x87, 0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0x82, 0xc0, 0x20, 0, 0xfc, 0xd7, 0x9e, 0xf6, 0xbf, 0x7f, 0xed, 0x90, 0x4f, 0x46, 0xa3, 0xbf } ; // ----------------------------------------------------------------------------- // This function is used by jbig2enc_image to fetch values from the image and // to automatically extend the range of the image on three sides with zero's // ----------------------------------------------------------------------------- static u8 image_get(const u8 *restrict image, int x, int y, int mx, int my) { if (y < 0) return 0; if (x >= mx) return 0; if (y >= my) return 0; return image[mx * y + x]; } // see comments in .h file unsigned jbig2enc_datasize(const struct jbig2enc_ctx *ctx) { return JBIG2_OUTPUTBUFFER_SIZE * ctx->output_chunks->size() + ctx->outbuf_used; } // see comments in .h file void jbig2enc_tobuffer(const struct jbig2enc_ctx *restrict ctx, u8 *restrict buffer) { int j = 0; for (std::vector::const_iterator i = ctx->output_chunks->begin(); i != ctx->output_chunks->end(); ++i) { memcpy(&buffer[j], *i, JBIG2_OUTPUTBUFFER_SIZE); j += JBIG2_OUTPUTBUFFER_SIZE; } memcpy(&buffer[j], ctx->outbuf, ctx->outbuf_used); } // This is the context used for the TPGD bits #define TPGDCTX 0x9b25 // ----------------------------------------------------------------------------- // This is designed for Leptonica's 1bpp packed format images. Each row is some // number of 32-bit words. Pixels are in native-byte-order in each word. // ----------------------------------------------------------------------------- void jbig2enc_bitimage(struct jbig2enc_ctx *restrict ctx, const u8 *restrict idata, int mx, int my, bool duplicate_line_removal) { const u32 *restrict data = (u32 *) idata; u8 *const context = ctx->context; const unsigned words_per_row = (mx + 31) / 32; const unsigned bytes_per_row = words_per_row * 4; u8 ltp = 0, sltp = 0; for (int y = 0; y < my; ++y) { int x = 0; // the c* values store the context bits for each row. The template is fixed // as template 0 with the floating bits in the default locations. u16 c1, c2, c3; // the w* values contain words from each of the rows: w1 is from two rows // up etc. The next bit to roll onto the context values are kept at the top // of these words. u32 w1, w2, w3; w1 = w2 = w3 = 0; if (y >= 2) w1 = data[(y - 2) * words_per_row]; if (y >= 1) { w2 = data[(y - 1) * words_per_row]; if (duplicate_line_removal) { // it's possible that the last row was the same as this row if (memcmp(&data[y * words_per_row], &data[(y - 1) * words_per_row], bytes_per_row) == 0) { sltp = ltp ^ 1; ltp = 1; } else { sltp = ltp; ltp = 0; } } } if (duplicate_line_removal) { encode_bit(ctx, context, TPGDCTX, sltp); if (ltp) continue; } w3 = data[y * words_per_row]; // the top three bits are the start of the context c1 c1 = w1 >> 29; c2 = w2 >> 28; // and we need to remove the used bits from the w* vars w1 <<= 3; w2 <<= 4; c3 = 0; for (x = 0; x < mx; ++x) { const u16 tval = (c1 << 11) | (c2 << 4) | c3; const u8 v = (w3 & 0x80000000) >> 31; //fprintf(stderr, "%d %d %d %d\n", x, y, tval, v); encode_bit(ctx, context, tval, v); c1 <<= 1; c2 <<= 1; c3 <<= 1; c1 |= (w1 & 0x80000000) >> 31; c2 |= (w2 & 0x80000000) >> 31; c3 |= v; const int m = x % 32; if (m == 28 && y >= 2) { // need to roll in another word from two lines up const unsigned wordno = (x / 32) + 1; if (wordno >= words_per_row) { w1 = 0; } else { w1 = data[(y - 2) * words_per_row + wordno]; } } else { w1 <<= 1; } if (m == 27 && y >= 1) { // need to roll in another word from the last line const unsigned wordno = (x / 32) + 1; if (wordno >= words_per_row) { w2 = 0; } else { w2 = data[(y - 1) * words_per_row + wordno]; } } else { w2 <<= 1; } if (m == 31) { // need to roll in another word from this line const unsigned wordno = (x / 32) + 1; if (wordno >= words_per_row) { w3 = 0; } else { w3 = data[y * words_per_row + wordno]; } } else { w3 <<= 1; } c1 &= 31; c2 &= 127; c3 &= 15; } } } void jbig2enc_refine(struct jbig2enc_ctx *__restrict__ ctx, const uint8_t *__restrict__ itempl, int tx, int ty, const uint8_t *__restrict__ itarget, int mx, int my, int ox, int oy) { const u32 *restrict templdata = (u32 *) itempl; const u32 *restrict data = (u32 *) itarget; u8 *restrict const context = ctx->context; static int image_counter = 0; image_counter++; #ifdef SYM_DEBUGGING fprintf(stderr, "refine:%d %d %d %d\n", tx, ty, mx, my); #endif const unsigned templwords_per_row = (tx + 31) / 32; const unsigned words_per_row = (mx + 31) / 32; for (int y = 0; y < my; ++y) { int x; const int temply = y + oy; // the template is fixed to the 13 pixel template with the floating bits in // the default locations. // we have 5 words of context. The first three are the last, current and // next rows of the template. The last two are the last and current rows of // the target. // To form the 14 bits of content these are packed from the least // significant bits rightward. u16 c1, c2, c3, c4, c5; // the w* values contain words from each of the corresponding rows. The // next bit to be part of the context is kept at the top of these words u32 w1, w2, w3, w4, w5; w1 = w2 = w3 = w4 = w5 = 0; if (temply >= 1 && (temply - 1) < ty) w1 = templdata[(temply - 1) * templwords_per_row]; if (temply >= 0 && temply < ty) w2 = templdata[temply * templwords_per_row]; if (temply >= -1 && temply + 1 < ty) w3 = templdata[(temply + 1) * templwords_per_row]; // the x offset prevents a hassel because we are dealing with bits. Thus we // restrict it to being {-1, 0, 1}. if (y >= 1) w4 = data[(y - 1) * words_per_row]; w5 = data[y * words_per_row]; const int shiftoffset = 30 + ox; c1 = w1 >> shiftoffset; c2 = w2 >> shiftoffset; c3 = w3 >> shiftoffset; c4 = w4 >> 30; c5 = 0; // the w* should contain the next bit to be included in the context, in the // MSB position. Thus we need to roll the used bits out of the way. const int bits_to_trim = 2 - ox; w1 <<= bits_to_trim; w2 <<= bits_to_trim; w3 <<= bits_to_trim; w4 <<= 2; for (x = 0; x < mx; ++x) { const u16 tval = (c1 << 10) | (c2 << 7) | (c3 << 4) | (c4 << 1) | c5; const u8 v = w5 >> 31; #ifdef SYM_DEBUGGING fprintf(stderr, "%d %d %d %d\n", x, y, tval, v); #endif encode_bit(ctx, context, tval, v); c1 <<= 1; c2 <<= 1; c3 <<= 1; c4 <<= 1; c1 |= w1 >> 31; c2 |= w2 >> 31; c3 |= w3 >> 31; c4 |= w4 >> 31; c5 = v; const int m = x % 32; const unsigned wordno = (x / 32) + 1; if (m == 29 + ox) { // have run out of bits in the w[123] values. Need to get more. if (wordno >= templwords_per_row) { w1 = w2 = w3 = 0; } else { if (temply >= 1 && (temply - 1 < ty)) { w1 = templdata[(temply - 1) * templwords_per_row + wordno]; } else { w1 = 0; } if (temply >= 0 && temply < ty) { w2 = templdata[temply * templwords_per_row + wordno]; } else { w2 = 0; } if (temply >= -1 && (temply + 1) < ty) { w3 = templdata[(temply + 1) * templwords_per_row + wordno]; } else { w3 = 0; } } } else { w1 <<= 1; w2 <<= 1; w3 <<= 1; } if (m == 29 && y >= 1) { // run out of data from w4 if (wordno >= words_per_row) { w4 = 0; } else { w4 = data[(y - 1) * words_per_row + wordno]; } } else { w4 <<= 1; } if (m == 31) { // run out of data from w5 if (wordno >= words_per_row) { w5 = 0; } else { w5 = data[y * words_per_row + wordno]; } } else { w5 <<= 1; } c1 &= 7; c2 &= 7; c3 &= 7; c4 &= 7; } } } // see comments in .h file void jbig2enc_image(struct jbig2enc_ctx *restrict ctx, const u8 *restrict data, int mx, int my, bool duplicate_line_removal) { u8 *const context = ctx->context; u8 ltp = 0; u8 sltp = 0; for (int y = 0; y < my; ++y) { int x = 0; u16 c1 = (image_get(data, x, y - 2, mx, my) << 2) | (image_get(data, x + 1, y - 2, mx, my) << 1) | (image_get(data, x + 2, y - 2, mx, my)); u16 c2 = (image_get(data, x, y - 1, mx, my) << 3) | (image_get(data, x + 1, y - 1, mx, my) << 2) | (image_get(data, x + 2, y - 1, mx, my) << 1) | (image_get(data, x + 3, y - 1, mx, my)); u16 c3 = 0; if (y > 0) { // it's possible that the last row was the same as this row if (memcmp(&data[y * mx], &data[(y - 1) * mx], mx) == 0) { sltp = ltp ^ 1; ltp = 1; } else { sltp = ltp; ltp = 0; } } if (duplicate_line_removal) { encode_bit(ctx, context, TPGDCTX, sltp); if (ltp) continue; } for (x = 0; x < mx; ++x) { const u16 tval = (c1 << 11) | (c2 << 4) | c3; const u8 v = image_get(data, x, y, mx, my); encode_bit(ctx, context, tval, v); c1 <<= 1; c2 <<= 1; c3 <<= 1; c1 |= image_get(data, x + 3, y - 2, mx, my); c2 |= image_get(data, x + 4, y - 1, mx, my); c3 |= v; c1 &= 31; c2 &= 127; c3 &= 15; } } }