/* * Copyright (c) 2022, yzrh * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include static const uint16_t _LSZ[0x71] = { 0x5a1d, 0x2586, 0x1114, 0x080b, 0x03d8, 0x01da, 0x00e5, 0x006f, 0x0036, 0x001a, 0x000d, 0x0006, 0x0003, 0x0001, 0x5a7f, 0x3f25, 0x2cf2, 0x207c, 0x17b9, 0x1182, 0x0cef, 0x09a1, 0x072f, 0x055c, 0x0406, 0x0303, 0x0240, 0x01b1, 0x0144, 0x00f5, 0x00b7, 0x008a, 0x0068, 0x004e, 0x003b, 0x002c, 0x5ae1, 0x484c, 0x3a0d, 0x2ef1, 0x261f, 0x1f33, 0x19a8, 0x1518, 0x1177, 0x0e74, 0x0bfb, 0x09f8, 0x0861, 0x0706, 0x05cd, 0x04de, 0x040f, 0x0363, 0x02d4, 0x025c, 0x01f8, 0x01a4, 0x0160, 0x0125, 0x00f6, 0x00cb, 0x00ab, 0x008f, 0x5b12, 0x4d04, 0x412c, 0x37d8, 0x2fe8, 0x293c, 0x2379, 0x1edf, 0x1aa9, 0x174e, 0x1424, 0x119c, 0x0f6b, 0x0d51, 0x0bb6, 0x0a40, 0x5832, 0x4d1c, 0x438e, 0x3bdd, 0x34ee, 0x2eae, 0x299a, 0x2516, 0x5570, 0x4ca9, 0x44d9, 0x3e22, 0x3824, 0x32b4, 0x2e17, 0x56a8, 0x4f46, 0x47e5, 0x41cf, 0x3c3d, 0x375e, 0x5231, 0x4c0f, 0x4639, 0x415e, 0x5627, 0x50e7, 0x4b85, 0x5597, 0x504f, 0x5a10, 0x5522, 0x59eb }; static const uint8_t _NLPS[0x71] = { 1, 14, 16, 18, 20, 23, 25, 28, 30, 33, 35, 9, 10, 12, 15, 36, 38, 39, 40, 42, 43, 45, 46, 48, 49, 51, 52, 54, 56, 57, 59, 60, 62, 63, 32, 33, 37, 64, 65, 67, 68, 69, 70, 72, 73, 74, 75, 77, 78, 79, 48, 50, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 61, 61, 65, 80, 81, 82, 83, 84, 86, 87, 87, 72, 72, 74, 74, 75, 77, 77, 80, 88, 89, 90, 91, 92, 93, 86, 88, 95, 96, 97, 99, 99, 93, 95, 101, 102, 103, 104, 99, 105, 106, 107, 103, 105, 108, 109, 110, 111, 110, 112, 112 }; static const uint8_t _NMPS[0x71] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 9, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 32, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 48, 81, 82, 83, 84, 85, 86, 87, 71, 89, 90, 91, 92, 93, 94, 86, 96, 97, 98, 99, 100, 93, 102, 103, 104, 99, 106, 107, 103, 109, 107, 111, 109, 111 }; static const bool _SWTCH[0x71] = { 1, 0, 0, 0, 0, 0, 0, 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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1 }; static uint8_t _ct; static uint8_t _pix; static uint16_t _reg_a; static uint32_t _reg_c; static uint8_t _mps[0x1000]; static uint8_t _st[0x1000]; static int _width; static int _height; static int _width_padded; static int _ret_pos; static unsigned char *_ret; static int _scd_size; static unsigned char *_scd; static void _bytein(void) { if (_ret_pos < _scd_size) _reg_c += _scd[_ret_pos++] << 8; _ct = 8; } static void _initdec(void) { memset(_mps, 0, 0x1000); memset(_st, 0, 0x1000); _reg_c = 0; _bytein(); _reg_c <<= 8; _bytein(); _reg_c <<= 8; _bytein(); _reg_a = 0x0000; } static void _exchange_lps(uint16_t cx) { uint8_t st_cx = _st[cx]; uint16_t lsz_st_cx = _LSZ[_st[cx]]; if (_reg_a < lsz_st_cx) { _pix = _mps[cx]; _st[cx] = _NMPS[st_cx]; } else { _pix = 1 - _mps[cx]; if (_SWTCH[st_cx]) _mps[cx] = _pix; _st[cx] = _NLPS[st_cx]; } _reg_c -= _reg_a << 16; _reg_a = lsz_st_cx; } static void _exchange_mps(uint16_t cx) { uint8_t st_cx = _st[cx]; uint16_t lsz_st_cx = _LSZ[_st[cx]]; if (_reg_a < lsz_st_cx) { _pix = 1 - _mps[cx]; if (_SWTCH[st_cx]) _mps[cx] = _pix; _st[cx] = _NLPS[st_cx]; } else { _pix = _mps[cx]; _st[cx] = _NMPS[st_cx]; } } static void _renormd(void) { do { if (_ct == 0) _bytein(); _reg_a <<= 1; _reg_c <<= 1; _ct--; } while (_reg_a < 0x8000); if (_ct == 0) _bytein(); } static void _decode(uint16_t cx) { _reg_a -= _LSZ[_st[cx]]; if (_reg_a > _reg_c >> 16) { if (_reg_a < 0x8000) { _exchange_mps(cx); _renormd(); } else { _pix = _mps[cx]; } } else { _exchange_lps(cx); _renormd(); } } static void _procline(int line, char *a, char *b, char *c) { /* The encoder must be erroneous */ uint16_t cx = 0; if (line > 0) { cx += (_ret[_width_padded * (_height - line)] & 0x20) << 2; cx += _ret[_width_padded * (_height - line)] & 0x40; cx += (_ret[_width_padded * (_height - line)] & 0x80) >> 2; } if (line > 1) { cx += (_ret[_width_padded * (_height - line + 1)] & 0x40) >> 4; cx += (_ret[_width_padded * (_height - line + 1)] & 0x80) >> 6; } for (int i = 0; i < _width; i++) { _decode(cx); cx >>= 1; if (_pix == 1) { _ret[_width_padded * (_height - line - 1) + i / 8] |= _pix << (7 - (i & 0x07)); c[i] = 1; cx |= 0x0200; } else { cx &= 0xfdff; } if (i + 2 < _width && a[i + 2] == 1) cx |= 0x0004; else cx &= 0xfffb; if (i + 3 < _width && b[i + 3] == 1) cx |= 0x0080; else cx &= 0xff7f; } } static int _procstripe(void) { if (_height <= 0 || _width_padded <= 0) return 1; int pix_size = 8 * _width_padded; char *buf = malloc(3 * pix_size); if (buf == NULL) return 1; memset(buf, 0, 3 * pix_size); char *a = buf; char *b = a + pix_size; char *c = b + pix_size; char *z; for (int i = 0; i < _height; i++) { _decode(0x029c); if (_pix == 1) { if (i > 0) memcpy(_ret + _width_padded * (_height - i - 1), _ret + _width_padded * (_height - i), _width_padded); memcpy(c, b, pix_size); } else { /* line atypical */ memset(c, 0, pix_size); _procline(i, a, b, c); } z = a; a = b; b = c; c = z; } free(buf); return 0; } int strdec_jbig(char **bitmap, int width, int height, const char * restrict jbig, int jbig_size) { _width = width; _height = height; _width_padded = (_width + 7) / 8; memset(*bitmap, 0, _height * _width_padded); _ret_pos = 0; _ret = (unsigned char *) *bitmap; _scd_size = jbig_size; _scd = (unsigned char *) jbig; _initdec(); return _procstripe(); }