| //======================================================================== |
| // |
| // JArithmeticDecoder.cc |
| // |
| // Copyright 2002-2004 Glyph & Cog, LLC |
| // |
| //======================================================================== |
| |
| #include <config.h> |
| |
| #include "Object.h" |
| #include "Stream.h" |
| #include "JArithmeticDecoder.h" |
| |
| //------------------------------------------------------------------------ |
| // JArithmeticDecoderStates |
| //------------------------------------------------------------------------ |
| |
| JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) { |
| contextSize = contextSizeA; |
| cxTab = (unsigned char *)gmallocn(contextSize, sizeof(unsigned char)); |
| reset(); |
| } |
| |
| JArithmeticDecoderStats::~JArithmeticDecoderStats() { |
| gfree(cxTab); |
| } |
| |
| JArithmeticDecoderStats *JArithmeticDecoderStats::copy() { |
| JArithmeticDecoderStats *stats; |
| |
| stats = new JArithmeticDecoderStats(contextSize); |
| memcpy(stats->cxTab, cxTab, contextSize); |
| return stats; |
| } |
| |
| void JArithmeticDecoderStats::reset() { |
| memset(cxTab, 0, contextSize); |
| } |
| |
| void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) { |
| memcpy(cxTab, stats->cxTab, contextSize); |
| } |
| |
| void JArithmeticDecoderStats::setEntry(unsigned int cx, int i, int mps) { |
| cxTab[cx] = (i << 1) + mps; |
| } |
| |
| //------------------------------------------------------------------------ |
| // JArithmeticDecoder |
| //------------------------------------------------------------------------ |
| |
| unsigned int JArithmeticDecoder::qeTab[47] = { |
| 0x56010000, 0x34010000, 0x18010000, 0x0AC10000, |
| 0x05210000, 0x02210000, 0x56010000, 0x54010000, |
| 0x48010000, 0x38010000, 0x30010000, 0x24010000, |
| 0x1C010000, 0x16010000, 0x56010000, 0x54010000, |
| 0x51010000, 0x48010000, 0x38010000, 0x34010000, |
| 0x30010000, 0x28010000, 0x24010000, 0x22010000, |
| 0x1C010000, 0x18010000, 0x16010000, 0x14010000, |
| 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000, |
| 0x08A10000, 0x05210000, 0x04410000, 0x02A10000, |
| 0x02210000, 0x01410000, 0x01110000, 0x00850000, |
| 0x00490000, 0x00250000, 0x00150000, 0x00090000, |
| 0x00050000, 0x00010000, 0x56010000 |
| }; |
| |
| int JArithmeticDecoder::nmpsTab[47] = { |
| 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16, |
| 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, |
| 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46 |
| }; |
| |
| int JArithmeticDecoder::nlpsTab[47] = { |
| 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, |
| 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, |
| 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46 |
| }; |
| |
| int JArithmeticDecoder::switchTab[47] = { |
| 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| JArithmeticDecoder::JArithmeticDecoder() { |
| str = nullptr; |
| dataLen = 0; |
| limitStream = false; |
| nBytesRead = 0; |
| } |
| |
| inline unsigned int JArithmeticDecoder::readByte() { |
| if (limitStream) { |
| --dataLen; |
| if (dataLen < 0) { |
| return 0xff; |
| } |
| } |
| ++nBytesRead; |
| return (unsigned int)str->getChar() & 0xff; |
| } |
| |
| JArithmeticDecoder::~JArithmeticDecoder() { |
| cleanup(); |
| } |
| |
| void JArithmeticDecoder::start() { |
| buf0 = readByte(); |
| buf1 = readByte(); |
| |
| // INITDEC |
| c = (buf0 ^ 0xff) << 16; |
| byteIn(); |
| c <<= 7; |
| ct -= 7; |
| a = 0x80000000; |
| } |
| |
| void JArithmeticDecoder::restart(int dataLenA) { |
| unsigned int cAdd; |
| bool prevFF; |
| int k, nBits; |
| |
| if (dataLen >= 0) { |
| dataLen = dataLenA; |
| } else if (dataLen == -1) { |
| dataLen = dataLenA; |
| buf1 = readByte(); |
| } else { |
| k = (-dataLen - 1) * 8 - ct; |
| dataLen = dataLenA; |
| cAdd = 0; |
| prevFF = false; |
| while (k > 0) { |
| buf0 = readByte(); |
| if (prevFF) { |
| cAdd += 0xfe00 - (buf0 << 9); |
| nBits = 7; |
| } else { |
| cAdd += 0xff00 - (buf0 << 8); |
| nBits = 8; |
| } |
| prevFF = buf0 == 0xff; |
| if (k > nBits) { |
| cAdd <<= nBits; |
| k -= nBits; |
| } else { |
| cAdd <<= k; |
| ct = nBits - k; |
| k = 0; |
| } |
| } |
| c += cAdd; |
| buf1 = readByte(); |
| } |
| } |
| |
| void JArithmeticDecoder::cleanup() { |
| if (limitStream) { |
| while (dataLen > 0) { |
| buf0 = buf1; |
| buf1 = readByte(); |
| } |
| } |
| } |
| |
| int JArithmeticDecoder::decodeBit(unsigned int context, |
| JArithmeticDecoderStats *stats) { |
| int bit; |
| unsigned int qe; |
| int iCX, mpsCX; |
| |
| iCX = stats->cxTab[context] >> 1; |
| mpsCX = stats->cxTab[context] & 1; |
| qe = qeTab[iCX]; |
| a -= qe; |
| if (c < a) { |
| if (a & 0x80000000) { |
| bit = mpsCX; |
| } else { |
| // MPS_EXCHANGE |
| if (a < qe) { |
| bit = 1 - mpsCX; |
| if (switchTab[iCX]) { |
| stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); |
| } else { |
| stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; |
| } |
| } else { |
| bit = mpsCX; |
| stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; |
| } |
| // RENORMD |
| do { |
| if (ct == 0) { |
| byteIn(); |
| } |
| a <<= 1; |
| c <<= 1; |
| --ct; |
| } while (!(a & 0x80000000)); |
| } |
| } else { |
| c -= a; |
| // LPS_EXCHANGE |
| if (a < qe) { |
| bit = mpsCX; |
| stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; |
| } else { |
| bit = 1 - mpsCX; |
| if (switchTab[iCX]) { |
| stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); |
| } else { |
| stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; |
| } |
| } |
| a = qe; |
| // RENORMD |
| do { |
| if (ct == 0) { |
| byteIn(); |
| } |
| a <<= 1; |
| c <<= 1; |
| --ct; |
| } while (!(a & 0x80000000)); |
| } |
| return bit; |
| } |
| |
| int JArithmeticDecoder::decodeByte(unsigned int context, |
| JArithmeticDecoderStats *stats) { |
| int byte; |
| int i; |
| |
| byte = 0; |
| for (i = 0; i < 8; ++i) { |
| byte = (byte << 1) | decodeBit(context, stats); |
| } |
| return byte; |
| } |
| |
| bool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) { |
| int s; |
| unsigned int v; |
| int i; |
| |
| prev = 1; |
| s = decodeIntBit(stats); |
| if (decodeIntBit(stats)) { |
| if (decodeIntBit(stats)) { |
| if (decodeIntBit(stats)) { |
| if (decodeIntBit(stats)) { |
| if (decodeIntBit(stats)) { |
| v = 0; |
| for (i = 0; i < 32; ++i) { |
| v = (v << 1) | decodeIntBit(stats); |
| } |
| v += 4436; |
| } else { |
| v = 0; |
| for (i = 0; i < 12; ++i) { |
| v = (v << 1) | decodeIntBit(stats); |
| } |
| v += 340; |
| } |
| } else { |
| v = 0; |
| for (i = 0; i < 8; ++i) { |
| v = (v << 1) | decodeIntBit(stats); |
| } |
| v += 84; |
| } |
| } else { |
| v = 0; |
| for (i = 0; i < 6; ++i) { |
| v = (v << 1) | decodeIntBit(stats); |
| } |
| v += 20; |
| } |
| } else { |
| v = decodeIntBit(stats); |
| v = (v << 1) | decodeIntBit(stats); |
| v = (v << 1) | decodeIntBit(stats); |
| v = (v << 1) | decodeIntBit(stats); |
| v += 4; |
| } |
| } else { |
| v = decodeIntBit(stats); |
| v = (v << 1) | decodeIntBit(stats); |
| } |
| |
| if (s) { |
| if (v == 0) { |
| return false; |
| } |
| *x = -(int)v; |
| } else { |
| *x = (int)v; |
| } |
| return true; |
| } |
| |
| int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) { |
| int bit; |
| |
| bit = decodeBit(prev, stats); |
| if (prev < 0x100) { |
| prev = (prev << 1) | bit; |
| } else { |
| prev = (((prev << 1) | bit) & 0x1ff) | 0x100; |
| } |
| return bit; |
| } |
| |
| unsigned int JArithmeticDecoder::decodeIAID(unsigned int codeLen, |
| JArithmeticDecoderStats *stats) { |
| unsigned int i; |
| int bit; |
| |
| prev = 1; |
| for (i = 0; i < codeLen; ++i) { |
| bit = decodeBit(prev, stats); |
| prev = (prev << 1) | bit; |
| } |
| return prev - (1 << codeLen); |
| } |
| |
| void JArithmeticDecoder::byteIn() { |
| if (buf0 == 0xff) { |
| if (buf1 > 0x8f) { |
| if (limitStream) { |
| buf0 = buf1; |
| buf1 = readByte(); |
| c = c + 0xff00 - (buf0 << 8); |
| } |
| ct = 8; |
| } else { |
| buf0 = buf1; |
| buf1 = readByte(); |
| c = c + 0xfe00 - (buf0 << 9); |
| ct = 7; |
| } |
| } else { |
| buf0 = buf1; |
| buf1 = readByte(); |
| c = c + 0xff00 - (buf0 << 8); |
| ct = 8; |
| } |
| } |