OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "JBig2_HuffmanTable.h" | 7 #include "core/src/fxcodec/jbig2/JBig2_HuffmanTable.h" |
8 | 8 |
9 #include <string.h> | 9 #include <algorithm> |
10 | |
11 #include <vector> | 10 #include <vector> |
12 | 11 |
13 #include "JBig2_BitStream.h" | |
14 #include "JBig2_Define.h" | |
15 #include "core/include/fxcrt/fx_memory.h" | 12 #include "core/include/fxcrt/fx_memory.h" |
| 13 #include "core/src/fxcodec/jbig2/JBig2_BitStream.h" |
| 14 #include "core/src/fxcodec/jbig2/JBig2_Define.h" |
| 15 #include "core/src/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h" |
16 | 16 |
17 CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine* pTable, | 17 CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine* pTable, |
18 int nLines, | 18 FX_DWORD nLines, |
19 FX_BOOL bHTOOB) { | 19 bool bHTOOB) |
20 init(); | 20 : m_bOK(true), HTOOB(bHTOOB), NTEMP(nLines) { |
21 m_bOK = parseFromStandardTable(pTable, nLines, bHTOOB); | 21 ParseFromStandardTable(pTable); |
22 } | 22 } |
23 | 23 |
24 CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream* pStream) { | 24 CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream* pStream) |
25 init(); | 25 : HTOOB(false), NTEMP(0) { |
26 m_bOK = parseFromCodedBuffer(pStream); | 26 m_bOK = ParseFromCodedBuffer(pStream); |
27 } | 27 } |
28 | 28 |
29 CJBig2_HuffmanTable::~CJBig2_HuffmanTable() { | 29 CJBig2_HuffmanTable::~CJBig2_HuffmanTable() { |
30 FX_Free(CODES); | |
31 FX_Free(PREFLEN); | |
32 FX_Free(RANGELEN); | |
33 FX_Free(RANGELOW); | |
34 } | 30 } |
35 void CJBig2_HuffmanTable::init() { | 31 |
36 HTOOB = FALSE; | 32 void CJBig2_HuffmanTable::ParseFromStandardTable(const JBig2TableLine* pTable) { |
37 NTEMP = 0; | 33 PREFLEN.resize(NTEMP); |
38 CODES = nullptr; | 34 RANGELEN.resize(NTEMP); |
39 PREFLEN = nullptr; | 35 RANGELOW.resize(NTEMP); |
40 RANGELEN = nullptr; | |
41 RANGELOW = nullptr; | |
42 } | |
43 int CJBig2_HuffmanTable::parseFromStandardTable(const JBig2TableLine* pTable, | |
44 int nLines, | |
45 FX_BOOL bHTOOB) { | |
46 HTOOB = bHTOOB; | |
47 NTEMP = nLines; | |
48 CODES = FX_Alloc(int, NTEMP); | |
49 PREFLEN = FX_Alloc(int, NTEMP); | |
50 RANGELEN = FX_Alloc(int, NTEMP); | |
51 RANGELOW = FX_Alloc(int, NTEMP); | |
52 int LENMAX = 0; | |
53 for (FX_DWORD i = 0; i < NTEMP; ++i) { | 36 for (FX_DWORD i = 0; i < NTEMP; ++i) { |
54 PREFLEN[i] = pTable[i].PREFLEN; | 37 PREFLEN[i] = pTable[i].PREFLEN; |
55 RANGELEN[i] = pTable[i].RANDELEN; | 38 RANGELEN[i] = pTable[i].RANDELEN; |
56 RANGELOW[i] = pTable[i].RANGELOW; | 39 RANGELOW[i] = pTable[i].RANGELOW; |
57 if (PREFLEN[i] > LENMAX) { | |
58 LENMAX = PREFLEN[i]; | |
59 } | |
60 } | 40 } |
61 int* LENCOUNT = FX_Alloc(int, LENMAX + 1); | 41 InitCodes(); |
62 JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1)); | |
63 int* FIRSTCODE = FX_Alloc(int, LENMAX + 1); | |
64 for (FX_DWORD i = 0; i < NTEMP; ++i) | |
65 ++LENCOUNT[PREFLEN[i]]; | |
66 | |
67 int CURLEN = 1; | |
68 FIRSTCODE[0] = 0; | |
69 LENCOUNT[0] = 0; | |
70 while (CURLEN <= LENMAX) { | |
71 FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1; | |
72 int CURCODE = FIRSTCODE[CURLEN]; | |
73 FX_DWORD CURTEMP = 0; | |
74 while (CURTEMP < NTEMP) { | |
75 if (PREFLEN[CURTEMP] == CURLEN) { | |
76 CODES[CURTEMP] = CURCODE; | |
77 CURCODE = CURCODE + 1; | |
78 } | |
79 CURTEMP = CURTEMP + 1; | |
80 } | |
81 CURLEN = CURLEN + 1; | |
82 } | |
83 FX_Free(LENCOUNT); | |
84 FX_Free(FIRSTCODE); | |
85 return 1; | |
86 } | 42 } |
87 | 43 |
88 #define HT_CHECK_MEMORY_ADJUST \ | 44 bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) { |
89 if (NTEMP >= nSize) { \ | |
90 nSize += 16; \ | |
91 PREFLEN = FX_Realloc(int, PREFLEN, nSize); \ | |
92 RANGELEN = FX_Realloc(int, RANGELEN, nSize); \ | |
93 RANGELOW = FX_Realloc(int, RANGELOW, nSize); \ | |
94 } | |
95 int CJBig2_HuffmanTable::parseFromCodedBuffer(CJBig2_BitStream* pStream) { | |
96 unsigned char cTemp; | 45 unsigned char cTemp; |
97 if (pStream->read1Byte(&cTemp) == -1) | 46 if (pStream->read1Byte(&cTemp) == -1) |
98 return FALSE; | 47 return false; |
99 | 48 |
100 HTOOB = cTemp & 0x01; | 49 HTOOB = !!(cTemp & 0x01); |
101 unsigned char HTPS = ((cTemp >> 1) & 0x07) + 1; | 50 unsigned char HTPS = ((cTemp >> 1) & 0x07) + 1; |
102 unsigned char HTRS = ((cTemp >> 4) & 0x07) + 1; | 51 unsigned char HTRS = ((cTemp >> 4) & 0x07) + 1; |
103 FX_DWORD HTLOW; | 52 FX_DWORD HTLOW; |
104 FX_DWORD HTHIGH; | 53 FX_DWORD HTHIGH; |
105 if (pStream->readInteger(&HTLOW) == -1 || | 54 if (pStream->readInteger(&HTLOW) == -1 || |
106 pStream->readInteger(&HTHIGH) == -1) { | 55 pStream->readInteger(&HTHIGH) == -1) { |
107 return FALSE; | 56 return false; |
108 } | 57 } |
109 | 58 |
110 const int low = static_cast<int>(HTLOW); | 59 const int low = static_cast<int>(HTLOW); |
111 const int high = static_cast<int>(HTHIGH); | 60 const int high = static_cast<int>(HTHIGH); |
112 if (low > high) | 61 if (low > high) |
113 return false; | 62 return false; |
114 | 63 |
115 FX_DWORD nSize = 16; | 64 ExtendBuffers(false); |
116 PREFLEN = FX_Alloc(int, nSize); | |
117 RANGELEN = FX_Alloc(int, nSize); | |
118 RANGELOW = FX_Alloc(int, nSize); | |
119 int cur_low = low; | 65 int cur_low = low; |
120 NTEMP = 0; | |
121 do { | 66 do { |
122 HT_CHECK_MEMORY_ADJUST | |
123 if ((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) || | 67 if ((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) || |
124 (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1)) { | 68 (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1)) { |
125 return FALSE; | 69 return false; |
126 } | 70 } |
127 RANGELOW[NTEMP] = cur_low; | 71 RANGELOW[NTEMP] = cur_low; |
128 cur_low += (1 << RANGELEN[NTEMP]); | 72 cur_low += (1 << RANGELEN[NTEMP]); |
129 NTEMP = NTEMP + 1; | 73 ExtendBuffers(true); |
130 } while (cur_low < high); | 74 } while (cur_low < high); |
131 HT_CHECK_MEMORY_ADJUST | 75 |
132 if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) | 76 if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) |
133 return FALSE; | 77 return false; |
134 | 78 |
135 RANGELEN[NTEMP] = 32; | 79 RANGELEN[NTEMP] = 32; |
136 RANGELOW[NTEMP] = low - 1; | 80 RANGELOW[NTEMP] = low - 1; |
137 ++NTEMP; | 81 ExtendBuffers(true); |
138 HT_CHECK_MEMORY_ADJUST | 82 |
139 if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) | 83 if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) |
140 return FALSE; | 84 return false; |
141 | 85 |
142 RANGELEN[NTEMP] = 32; | 86 RANGELEN[NTEMP] = 32; |
143 RANGELOW[NTEMP] = high; | 87 RANGELOW[NTEMP] = high; |
144 NTEMP = NTEMP + 1; | 88 ExtendBuffers(true); |
| 89 |
145 if (HTOOB) { | 90 if (HTOOB) { |
146 HT_CHECK_MEMORY_ADJUST | |
147 if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) | 91 if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) |
148 return FALSE; | 92 return false; |
149 | 93 |
150 ++NTEMP; | 94 ++NTEMP; |
151 } | 95 } |
152 CODES = FX_Alloc(int, NTEMP); | 96 |
153 int LENMAX = 0; | 97 InitCodes(); |
| 98 return true; |
| 99 } |
| 100 |
| 101 void CJBig2_HuffmanTable::InitCodes() { |
| 102 int lenmax = 0; |
154 for (FX_DWORD i = 0; i < NTEMP; ++i) | 103 for (FX_DWORD i = 0; i < NTEMP; ++i) |
155 LENMAX = std::max(PREFLEN[i], LENMAX); | 104 lenmax = std::max(PREFLEN[i], lenmax); |
156 | 105 |
157 std::vector<int> LENCOUNT(LENMAX + 1); | 106 CODES.resize(NTEMP); |
158 for (FX_DWORD i = 0; i < NTEMP; ++i) | 107 std::vector<int> LENCOUNT(lenmax + 1); |
159 LENCOUNT[PREFLEN[i]]++; | 108 std::vector<int> FIRSTCODE(lenmax + 1); |
| 109 for (int len : PREFLEN) |
| 110 ++LENCOUNT[len]; |
| 111 |
| 112 FIRSTCODE[0] = 0; |
160 LENCOUNT[0] = 0; | 113 LENCOUNT[0] = 0; |
161 | 114 for (int i = 1; i <= lenmax; ++i) { |
162 std::vector<int> FIRSTCODE(LENMAX + 1); | |
163 FIRSTCODE[0] = 0; | |
164 for (int i = 1; i <= LENMAX; ++i) { | |
165 FIRSTCODE[i] = (FIRSTCODE[i - 1] + LENCOUNT[i - 1]) << 1; | 115 FIRSTCODE[i] = (FIRSTCODE[i - 1] + LENCOUNT[i - 1]) << 1; |
166 int CURCODE = FIRSTCODE[i]; | 116 int CURCODE = FIRSTCODE[i]; |
167 for (FX_DWORD j = 0; j < NTEMP; ++j) { | 117 for (FX_DWORD j = 0; j < NTEMP; ++j) { |
168 if (PREFLEN[j] == i) | 118 if (PREFLEN[j] == i) |
169 CODES[j] = CURCODE++; | 119 CODES[j] = CURCODE++; |
170 } | 120 } |
171 } | 121 } |
172 return TRUE; | |
173 } | 122 } |
| 123 |
| 124 void CJBig2_HuffmanTable::ExtendBuffers(bool increment) { |
| 125 if (increment) |
| 126 ++NTEMP; |
| 127 |
| 128 size_t size = PREFLEN.size(); |
| 129 if (NTEMP < size) |
| 130 return; |
| 131 |
| 132 size += 16; |
| 133 ASSERT(NTEMP < size); |
| 134 PREFLEN.resize(size); |
| 135 RANGELEN.resize(size); |
| 136 RANGELOW.resize(size); |
| 137 } |
OLD | NEW |