1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <algorithm>
8 #include <memory>
9 #include <vector>
10
11 #include "core/fxcodec/codec/codec_int.h"
12 #include "core/fxcodec/fx_codec.h"
13 #include "core/fxcrt/fx_memory.h"
14 #include "third_party/base/ptr_util.h"
15
16 namespace {
17
18 const uint8_t OneLeadPos[256] = {
19 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
20 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
21 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
22 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
23 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
24 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 };
31 const uint8_t ZeroLeadPos[256] = {
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
38 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
39 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
41 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
42 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
43 };
44
45 // Limit of image dimension, an arbitrary large number.
46 const int kMaxImageDimension = 0x01FFFF;
47
FindBit(const uint8_t * data_buf,int max_pos,int start_pos,int bit)48 int FindBit(const uint8_t* data_buf, int max_pos, int start_pos, int bit) {
49 ASSERT(start_pos >= 0);
50 if (start_pos >= max_pos)
51 return max_pos;
52
53 const uint8_t* leading_pos = bit ? OneLeadPos : ZeroLeadPos;
54 if (start_pos % 8) {
55 uint8_t data = data_buf[start_pos / 8];
56 if (bit)
57 data &= 0xff >> (start_pos % 8);
58 else
59 data |= 0xff << (8 - start_pos % 8);
60
61 if (leading_pos[data] < 8)
62 return start_pos / 8 * 8 + leading_pos[data];
63
64 start_pos += 7;
65 }
66 uint8_t skip = bit ? 0x00 : 0xff;
67 int byte_pos = start_pos / 8;
68 int max_byte = (max_pos + 7) / 8;
69 while (byte_pos < max_byte) {
70 if (data_buf[byte_pos] != skip)
71 break;
72
73 ++byte_pos;
74 }
75 if (byte_pos == max_byte)
76 return max_pos;
77
78 return std::min(leading_pos[data_buf[byte_pos]] + byte_pos * 8, max_pos);
79 }
80
FaxG4FindB1B2(const std::vector<uint8_t> & ref_buf,int columns,int a0,bool a0color,int * b1,int * b2)81 void FaxG4FindB1B2(const std::vector<uint8_t>& ref_buf,
82 int columns,
83 int a0,
84 bool a0color,
85 int* b1,
86 int* b2) {
87 uint8_t first_bit =
88 (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
89 *b1 = FindBit(ref_buf.data(), columns, a0 + 1, !first_bit);
90 if (*b1 >= columns) {
91 *b1 = *b2 = columns;
92 return;
93 }
94 if (first_bit == !a0color) {
95 *b1 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
96 first_bit = !first_bit;
97 }
98 if (*b1 >= columns) {
99 *b1 = *b2 = columns;
100 return;
101 }
102 *b2 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
103 }
104
FaxFillBits(uint8_t * dest_buf,int columns,int startpos,int endpos)105 void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
106 startpos = std::max(startpos, 0);
107 endpos = std::min(std::max(endpos, 0), columns);
108 if (startpos >= endpos)
109 return;
110
111 int first_byte = startpos / 8;
112 int last_byte = (endpos - 1) / 8;
113 if (first_byte == last_byte) {
114 for (int i = startpos % 8; i <= (endpos - 1) % 8; ++i)
115 dest_buf[first_byte] -= 1 << (7 - i);
116 return;
117 }
118
119 for (int i = startpos % 8; i < 8; ++i)
120 dest_buf[first_byte] -= 1 << (7 - i);
121 for (int i = 0; i <= (endpos - 1) % 8; ++i)
122 dest_buf[last_byte] -= 1 << (7 - i);
123
124 if (last_byte > first_byte + 1)
125 FXSYS_memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
126 }
127
NextBit(const uint8_t * src_buf,int * bitpos)128 inline bool NextBit(const uint8_t* src_buf, int* bitpos) {
129 int pos = (*bitpos)++;
130 return !!(src_buf[pos / 8] & (1 << (7 - pos % 8)));
131 }
132
133 const uint8_t FaxBlackRunIns[] = {
134 0, 2, 0x02, 3, 0, 0x03,
135 2, 0, 2, 0x02, 1, 0,
136 0x03, 4, 0, 2, 0x02, 6,
137 0, 0x03, 5, 0, 1, 0x03,
138 7, 0, 2, 0x04, 9, 0,
139 0x05, 8, 0, 3, 0x04, 10,
140 0, 0x05, 11, 0, 0x07, 12,
141 0, 2, 0x04, 13, 0, 0x07,
142 14, 0, 1, 0x18, 15, 0,
143 5, 0x08, 18, 0, 0x0f, 64,
144 0, 0x17, 16, 0, 0x18, 17,
145 0, 0x37, 0, 0, 10, 0x08,
146 0x00, 0x07, 0x0c, 0x40, 0x07, 0x0d,
147 0x80, 0x07, 0x17, 24, 0, 0x18,
148 25, 0, 0x28, 23, 0, 0x37,
149 22, 0, 0x67, 19, 0, 0x68,
150 20, 0, 0x6c, 21, 0, 54,
151 0x12, 1984 % 256, 1984 / 256, 0x13, 2048 % 256, 2048 / 256,
152 0x14, 2112 % 256, 2112 / 256, 0x15, 2176 % 256, 2176 / 256,
153 0x16, 2240 % 256, 2240 / 256, 0x17, 2304 % 256, 2304 / 256,
154 0x1c, 2368 % 256, 2368 / 256, 0x1d, 2432 % 256, 2432 / 256,
155 0x1e, 2496 % 256, 2496 / 256, 0x1f, 2560 % 256, 2560 / 256,
156 0x24, 52, 0, 0x27, 55, 0,
157 0x28, 56, 0, 0x2b, 59, 0,
158 0x2c, 60, 0, 0x33, 320 % 256, 320 / 256,
159 0x34, 384 % 256, 384 / 256, 0x35, 448 % 256, 448 / 256,
160 0x37, 53, 0, 0x38, 54, 0,
161 0x52, 50, 0, 0x53, 51, 0,
162 0x54, 44, 0, 0x55, 45, 0,
163 0x56, 46, 0, 0x57, 47, 0,
164 0x58, 57, 0, 0x59, 58, 0,
165 0x5a, 61, 0, 0x5b, 256 % 256, 256 / 256,
166 0x64, 48, 0, 0x65, 49, 0,
167 0x66, 62, 0, 0x67, 63, 0,
168 0x68, 30, 0, 0x69, 31, 0,
169 0x6a, 32, 0, 0x6b, 33, 0,
170 0x6c, 40, 0, 0x6d, 41, 0,
171 0xc8, 128, 0, 0xc9, 192, 0,
172 0xca, 26, 0, 0xcb, 27, 0,
173 0xcc, 28, 0, 0xcd, 29, 0,
174 0xd2, 34, 0, 0xd3, 35, 0,
175 0xd4, 36, 0, 0xd5, 37, 0,
176 0xd6, 38, 0, 0xd7, 39, 0,
177 0xda, 42, 0, 0xdb, 43, 0,
178 20, 0x4a, 640 % 256, 640 / 256, 0x4b, 704 % 256,
179 704 / 256, 0x4c, 768 % 256, 768 / 256, 0x4d, 832 % 256,
180 832 / 256, 0x52, 1280 % 256, 1280 / 256, 0x53, 1344 % 256,
181 1344 / 256, 0x54, 1408 % 256, 1408 / 256, 0x55, 1472 % 256,
182 1472 / 256, 0x5a, 1536 % 256, 1536 / 256, 0x5b, 1600 % 256,
183 1600 / 256, 0x64, 1664 % 256, 1664 / 256, 0x65, 1728 % 256,
184 1728 / 256, 0x6c, 512 % 256, 512 / 256, 0x6d, 576 % 256,
185 576 / 256, 0x72, 896 % 256, 896 / 256, 0x73, 960 % 256,
186 960 / 256, 0x74, 1024 % 256, 1024 / 256, 0x75, 1088 % 256,
187 1088 / 256, 0x76, 1152 % 256, 1152 / 256, 0x77, 1216 % 256,
188 1216 / 256, 0xff};
189
190 const uint8_t FaxWhiteRunIns[] = {
191 0, 0, 0, 6, 0x07, 2,
192 0, 0x08, 3, 0, 0x0B, 4,
193 0, 0x0C, 5, 0, 0x0E, 6,
194 0, 0x0F, 7, 0, 6, 0x07,
195 10, 0, 0x08, 11, 0, 0x12,
196 128, 0, 0x13, 8, 0, 0x14,
197 9, 0, 0x1b, 64, 0, 9,
198 0x03, 13, 0, 0x07, 1, 0,
199 0x08, 12, 0, 0x17, 192, 0,
200 0x18, 1664 % 256, 1664 / 256, 0x2a, 16, 0,
201 0x2B, 17, 0, 0x34, 14, 0,
202 0x35, 15, 0, 12, 0x03, 22,
203 0, 0x04, 23, 0, 0x08, 20,
204 0, 0x0c, 19, 0, 0x13, 26,
205 0, 0x17, 21, 0, 0x18, 28,
206 0, 0x24, 27, 0, 0x27, 18,
207 0, 0x28, 24, 0, 0x2B, 25,
208 0, 0x37, 256 % 256, 256 / 256, 42, 0x02,
209 29, 0, 0x03, 30, 0, 0x04,
210 45, 0, 0x05, 46, 0, 0x0a,
211 47, 0, 0x0b, 48, 0, 0x12,
212 33, 0, 0x13, 34, 0, 0x14,
213 35, 0, 0x15, 36, 0, 0x16,
214 37, 0, 0x17, 38, 0, 0x1a,
215 31, 0, 0x1b, 32, 0, 0x24,
216 53, 0, 0x25, 54, 0, 0x28,
217 39, 0, 0x29, 40, 0, 0x2a,
218 41, 0, 0x2b, 42, 0, 0x2c,
219 43, 0, 0x2d, 44, 0, 0x32,
220 61, 0, 0x33, 62, 0, 0x34,
221 63, 0, 0x35, 0, 0, 0x36,
222 320 % 256, 320 / 256, 0x37, 384 % 256, 384 / 256, 0x4a,
223 59, 0, 0x4b, 60, 0, 0x52,
224 49, 0, 0x53, 50, 0, 0x54,
225 51, 0, 0x55, 52, 0, 0x58,
226 55, 0, 0x59, 56, 0, 0x5a,
227 57, 0, 0x5b, 58, 0, 0x64,
228 448 % 256, 448 / 256, 0x65, 512 % 256, 512 / 256, 0x67,
229 640 % 256, 640 / 256, 0x68, 576 % 256, 576 / 256, 16,
230 0x98, 1472 % 256, 1472 / 256, 0x99, 1536 % 256, 1536 / 256,
231 0x9a, 1600 % 256, 1600 / 256, 0x9b, 1728 % 256, 1728 / 256,
232 0xcc, 704 % 256, 704 / 256, 0xcd, 768 % 256, 768 / 256,
233 0xd2, 832 % 256, 832 / 256, 0xd3, 896 % 256, 896 / 256,
234 0xd4, 960 % 256, 960 / 256, 0xd5, 1024 % 256, 1024 / 256,
235 0xd6, 1088 % 256, 1088 / 256, 0xd7, 1152 % 256, 1152 / 256,
236 0xd8, 1216 % 256, 1216 / 256, 0xd9, 1280 % 256, 1280 / 256,
237 0xda, 1344 % 256, 1344 / 256, 0xdb, 1408 % 256, 1408 / 256,
238 0, 3, 0x08, 1792 % 256, 1792 / 256, 0x0c,
239 1856 % 256, 1856 / 256, 0x0d, 1920 % 256, 1920 / 256, 10,
240 0x12, 1984 % 256, 1984 / 256, 0x13, 2048 % 256, 2048 / 256,
241 0x14, 2112 % 256, 2112 / 256, 0x15, 2176 % 256, 2176 / 256,
242 0x16, 2240 % 256, 2240 / 256, 0x17, 2304 % 256, 2304 / 256,
243 0x1c, 2368 % 256, 2368 / 256, 0x1d, 2432 % 256, 2432 / 256,
244 0x1e, 2496 % 256, 2496 / 256, 0x1f, 2560 % 256, 2560 / 256,
245 0xff,
246 };
247
FaxGetRun(const uint8_t * ins_array,const uint8_t * src_buf,int * bitpos,int bitsize)248 int FaxGetRun(const uint8_t* ins_array,
249 const uint8_t* src_buf,
250 int* bitpos,
251 int bitsize) {
252 uint32_t code = 0;
253 int ins_off = 0;
254 while (1) {
255 uint8_t ins = ins_array[ins_off++];
256 if (ins == 0xff)
257 return -1;
258
259 if (*bitpos >= bitsize)
260 return -1;
261
262 code <<= 1;
263 if (src_buf[*bitpos / 8] & (1 << (7 - *bitpos % 8)))
264 ++code;
265
266 ++(*bitpos);
267 int next_off = ins_off + ins * 3;
268 for (; ins_off < next_off; ins_off += 3) {
269 if (ins_array[ins_off] == code) {
270 return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256;
271 }
272 }
273 }
274 }
275
FaxG4GetRow(const uint8_t * src_buf,int bitsize,int * bitpos,uint8_t * dest_buf,const std::vector<uint8_t> & ref_buf,int columns)276 bool FaxG4GetRow(const uint8_t* src_buf,
277 int bitsize,
278 int* bitpos,
279 uint8_t* dest_buf,
280 const std::vector<uint8_t>& ref_buf,
281 int columns) {
282 int a0 = -1;
283 bool a0color = true;
284 while (1) {
285 if (*bitpos >= bitsize)
286 return false;
287
288 int a1;
289 int a2;
290 int b1;
291 int b2;
292 FaxG4FindB1B2(ref_buf, columns, a0, a0color, &b1, &b2);
293
294 int v_delta = 0;
295 if (!NextBit(src_buf, bitpos)) {
296 if (*bitpos >= bitsize)
297 return false;
298
299 bool bit1 = NextBit(src_buf, bitpos);
300 if (*bitpos >= bitsize)
301 return false;
302
303 bool bit2 = NextBit(src_buf, bitpos);
304 if (bit1) {
305 v_delta = bit2 ? 1 : -1;
306 } else if (bit2) {
307 int run_len1 = 0;
308 while (1) {
309 int run = FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns,
310 src_buf, bitpos, bitsize);
311 run_len1 += run;
312 if (run < 64) {
313 break;
314 }
315 }
316 if (a0 < 0)
317 ++run_len1;
318
319 a1 = a0 + run_len1;
320 if (!a0color)
321 FaxFillBits(dest_buf, columns, a0, a1);
322
323 int run_len2 = 0;
324 while (1) {
325 int run = FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns,
326 src_buf, bitpos, bitsize);
327 run_len2 += run;
328 if (run < 64) {
329 break;
330 }
331 }
332 a2 = a1 + run_len2;
333 if (a0color)
334 FaxFillBits(dest_buf, columns, a1, a2);
335
336 a0 = a2;
337 if (a0 < columns)
338 continue;
339
340 return true;
341 } else {
342 if (*bitpos >= bitsize)
343 return false;
344
345 if (NextBit(src_buf, bitpos)) {
346 if (!a0color)
347 FaxFillBits(dest_buf, columns, a0, b2);
348
349 if (b2 >= columns)
350 return true;
351
352 a0 = b2;
353 continue;
354 }
355
356 if (*bitpos >= bitsize)
357 return false;
358
359 bool next_bit1 = NextBit(src_buf, bitpos);
360 if (*bitpos >= bitsize)
361 return false;
362
363 bool next_bit2 = NextBit(src_buf, bitpos);
364 if (next_bit1) {
365 v_delta = next_bit2 ? 2 : -2;
366 } else if (next_bit2) {
367 if (*bitpos >= bitsize)
368 return false;
369
370 v_delta = NextBit(src_buf, bitpos) ? 3 : -3;
371 } else {
372 if (*bitpos >= bitsize)
373 return false;
374
375 if (NextBit(src_buf, bitpos)) {
376 *bitpos += 3;
377 continue;
378 }
379 *bitpos += 5;
380 return true;
381 }
382 }
383 }
384 a1 = b1 + v_delta;
385 if (!a0color)
386 FaxFillBits(dest_buf, columns, a0, a1);
387
388 if (a1 >= columns)
389 return true;
390
391 // The position of picture element must be monotonic increasing.
392 if (a0 >= a1)
393 return false;
394
395 a0 = a1;
396 a0color = !a0color;
397 }
398 }
399
FaxSkipEOL(const uint8_t * src_buf,int bitsize,int * bitpos)400 bool FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) {
401 int startbit = *bitpos;
402 while (*bitpos < bitsize) {
403 if (!NextBit(src_buf, bitpos))
404 continue;
405 if (*bitpos - startbit <= 11)
406 *bitpos = startbit;
407 return true;
408 }
409 return false;
410 }
411
FaxGet1DLine(const uint8_t * src_buf,int bitsize,int * bitpos,std::vector<uint8_t> * dest_buf,int columns)412 bool FaxGet1DLine(const uint8_t* src_buf,
413 int bitsize,
414 int* bitpos,
415 std::vector<uint8_t>* dest_buf,
416 int columns) {
417 bool color = true;
418 int startpos = 0;
419 while (1) {
420 if (*bitpos >= bitsize)
421 return false;
422
423 int run_len = 0;
424 while (1) {
425 int run = FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf,
426 bitpos, bitsize);
427 if (run < 0) {
428 while (*bitpos < bitsize) {
429 if (NextBit(src_buf, bitpos))
430 return true;
431 }
432 return false;
433 }
434 run_len += run;
435 if (run < 64) {
436 break;
437 }
438 }
439 if (!color)
440 FaxFillBits(dest_buf->data(), columns, startpos, startpos + run_len);
441
442 startpos += run_len;
443 if (startpos >= columns)
444 break;
445
446 color = !color;
447 }
448 return true;
449 }
450
451 } // namespace
452
453 class CCodec_FaxDecoder : public CCodec_ScanlineDecoder {
454 public:
455 CCodec_FaxDecoder(const uint8_t* src_buf,
456 uint32_t src_size,
457 int width,
458 int height,
459 uint32_t pitch,
460 int K,
461 bool EndOfLine,
462 bool EncodedByteAlign,
463 bool BlackIs1);
464 ~CCodec_FaxDecoder() override;
465
466 // CCodec_ScanlineDecoder
467 bool v_Rewind() override;
468 uint8_t* v_GetNextLine() override;
469 uint32_t GetSrcOffset() override;
470
471 private:
472 const int m_Encoding;
473 int m_bitpos;
474 bool m_bByteAlign;
475 const bool m_bEndOfLine;
476 const bool m_bBlack;
477 const uint32_t m_SrcSize;
478 const uint8_t* const m_pSrcBuf;
479 std::vector<uint8_t> m_ScanlineBuf;
480 std::vector<uint8_t> m_RefBuf;
481 };
482
CCodec_FaxDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,uint32_t pitch,int K,bool EndOfLine,bool EncodedByteAlign,bool BlackIs1)483 CCodec_FaxDecoder::CCodec_FaxDecoder(const uint8_t* src_buf,
484 uint32_t src_size,
485 int width,
486 int height,
487 uint32_t pitch,
488 int K,
489 bool EndOfLine,
490 bool EncodedByteAlign,
491 bool BlackIs1)
492 : CCodec_ScanlineDecoder(width, height, width, height, 1, 1, pitch),
493 m_Encoding(K),
494 m_bitpos(0),
495 m_bByteAlign(EncodedByteAlign),
496 m_bEndOfLine(EndOfLine),
497 m_bBlack(BlackIs1),
498 m_SrcSize(src_size),
499 m_pSrcBuf(src_buf),
500 m_ScanlineBuf(pitch),
501 m_RefBuf(pitch) {}
502
~CCodec_FaxDecoder()503 CCodec_FaxDecoder::~CCodec_FaxDecoder() {}
504
v_Rewind()505 bool CCodec_FaxDecoder::v_Rewind() {
506 FXSYS_memset(m_RefBuf.data(), 0xff, m_RefBuf.size());
507 m_bitpos = 0;
508 return true;
509 }
510
v_GetNextLine()511 uint8_t* CCodec_FaxDecoder::v_GetNextLine() {
512 int bitsize = m_SrcSize * 8;
513 FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
514 if (m_bitpos >= bitsize)
515 return nullptr;
516
517 FXSYS_memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size());
518 if (m_Encoding < 0) {
519 FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
520 m_OrigWidth);
521 m_RefBuf = m_ScanlineBuf;
522 } else if (m_Encoding == 0) {
523 FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
524 } else {
525 if (NextBit(m_pSrcBuf, &m_bitpos)) {
526 FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
527 } else {
528 FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
529 m_OrigWidth);
530 }
531 m_RefBuf = m_ScanlineBuf;
532 }
533 if (m_bEndOfLine)
534 FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
535
536 if (m_bByteAlign && m_bitpos < bitsize) {
537 int bitpos0 = m_bitpos;
538 int bitpos1 = (m_bitpos + 7) / 8 * 8;
539 while (m_bByteAlign && bitpos0 < bitpos1) {
540 int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
541 if (bit != 0) {
542 m_bByteAlign = false;
543 } else {
544 ++bitpos0;
545 }
546 }
547 if (m_bByteAlign)
548 m_bitpos = bitpos1;
549 }
550 if (m_bBlack) {
551 for (uint32_t i = 0; i < m_Pitch; ++i) {
552 m_ScanlineBuf[i] = ~m_ScanlineBuf[i];
553 }
554 }
555 return m_ScanlineBuf.data();
556 }
557
GetSrcOffset()558 uint32_t CCodec_FaxDecoder::GetSrcOffset() {
559 return std::min(static_cast<uint32_t>((m_bitpos + 7) / 8), m_SrcSize);
560 }
561
FaxG4Decode(const uint8_t * src_buf,uint32_t src_size,int * pbitpos,uint8_t * dest_buf,int width,int height,int pitch)562 void FaxG4Decode(const uint8_t* src_buf,
563 uint32_t src_size,
564 int* pbitpos,
565 uint8_t* dest_buf,
566 int width,
567 int height,
568 int pitch) {
569 if (pitch == 0)
570 pitch = (width + 7) / 8;
571
572 std::vector<uint8_t> ref_buf(pitch, 0xff);
573 int bitpos = *pbitpos;
574 for (int iRow = 0; iRow < height; iRow++) {
575 uint8_t* line_buf = dest_buf + iRow * pitch;
576 FXSYS_memset(line_buf, 0xff, pitch);
577 FaxG4GetRow(src_buf, src_size << 3, &bitpos, line_buf, ref_buf, width);
578 FXSYS_memcpy(ref_buf.data(), line_buf, pitch);
579 }
580 *pbitpos = bitpos;
581 }
582
CreateDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,int K,bool EndOfLine,bool EncodedByteAlign,bool BlackIs1,int Columns,int Rows)583 std::unique_ptr<CCodec_ScanlineDecoder> CCodec_FaxModule::CreateDecoder(
584 const uint8_t* src_buf,
585 uint32_t src_size,
586 int width,
587 int height,
588 int K,
589 bool EndOfLine,
590 bool EncodedByteAlign,
591 bool BlackIs1,
592 int Columns,
593 int Rows) {
594 int actual_width = Columns ? Columns : width;
595 int actual_height = Rows ? Rows : height;
596
597 // Reject invalid values.
598 if (actual_width <= 0 || actual_height <= 0)
599 return nullptr;
600
601 // Reject unreasonable large input.
602 if (actual_width > kMaxImageDimension || actual_height > kMaxImageDimension)
603 return nullptr;
604
605 uint32_t pitch = (static_cast<uint32_t>(actual_width) + 31) / 32 * 4;
606 return pdfium::MakeUnique<CCodec_FaxDecoder>(
607 src_buf, src_size, actual_width, actual_height, pitch, K, EndOfLine,
608 EncodedByteAlign, BlackIs1);
609 }
610
611 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
612 namespace {
613 const uint8_t BlackRunTerminator[128] = {
614 0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4,
615 0x03, 5, 0x05, 6, 0x04, 6, 0x04, 7, 0x05, 7, 0x07, 7, 0x04, 8,
616 0x07, 8, 0x18, 9, 0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11,
617 0x6c, 11, 0x37, 11, 0x28, 11, 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12,
618 0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 0x6a, 12, 0x6b, 12, 0xd2, 12,
619 0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 0x6c, 12, 0x6d, 12,
620 0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 0x64, 12,
621 0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
622 0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12,
623 0x67, 12,
624 };
625
626 const uint8_t BlackRunMarkup[80] = {
627 0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12,
628 0x6c, 13, 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13,
629 0x73, 13, 0x74, 13, 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13,
630 0x54, 13, 0x55, 13, 0x5a, 13, 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11,
631 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
632 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
633 };
634
635 const uint8_t WhiteRunTerminator[128] = {
636 0x35, 8, 0x07, 6, 0x07, 4, 0x08, 4, 0x0B, 4, 0x0C, 4, 0x0E, 4, 0x0F, 4,
637 0x13, 5, 0x14, 5, 0x07, 5, 0x08, 5, 0x08, 6, 0x03, 6, 0x34, 6, 0x35, 6,
638 0x2a, 6, 0x2B, 6, 0x27, 7, 0x0c, 7, 0x08, 7, 0x17, 7, 0x03, 7, 0x04, 7,
639 0x28, 7, 0x2B, 7, 0x13, 7, 0x24, 7, 0x18, 7, 0x02, 8, 0x03, 8, 0x1a, 8,
640 0x1b, 8, 0x12, 8, 0x13, 8, 0x14, 8, 0x15, 8, 0x16, 8, 0x17, 8, 0x28, 8,
641 0x29, 8, 0x2a, 8, 0x2b, 8, 0x2c, 8, 0x2d, 8, 0x04, 8, 0x05, 8, 0x0a, 8,
642 0x0b, 8, 0x52, 8, 0x53, 8, 0x54, 8, 0x55, 8, 0x24, 8, 0x25, 8, 0x58, 8,
643 0x59, 8, 0x5a, 8, 0x5b, 8, 0x4a, 8, 0x4b, 8, 0x32, 8, 0x33, 8, 0x34, 8,
644 };
645
646 const uint8_t WhiteRunMarkup[80] = {
647 0x1b, 5, 0x12, 5, 0x17, 6, 0x37, 7, 0x36, 8, 0x37, 8, 0x64, 8,
648 0x65, 8, 0x68, 8, 0x67, 8, 0xcc, 9, 0xcd, 9, 0xd2, 9, 0xd3, 9,
649 0xd4, 9, 0xd5, 9, 0xd6, 9, 0xd7, 9, 0xd8, 9, 0xd9, 9, 0xda, 9,
650 0xdb, 9, 0x98, 9, 0x99, 9, 0x9a, 9, 0x18, 6, 0x9b, 9, 0x08, 11,
651 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
652 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
653 };
654
AddBitStream(uint8_t * dest_buf,int * dest_bitpos,int data,int bitlen)655 void AddBitStream(uint8_t* dest_buf, int* dest_bitpos, int data, int bitlen) {
656 for (int i = bitlen - 1; i >= 0; i--) {
657 if (data & (1 << i)) {
658 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
659 }
660 (*dest_bitpos)++;
661 }
662 }
663
FaxEncodeRun(uint8_t * dest_buf,int * dest_bitpos,int run,bool bWhite)664 void FaxEncodeRun(uint8_t* dest_buf, int* dest_bitpos, int run, bool bWhite) {
665 while (run >= 2560) {
666 AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
667 run -= 2560;
668 }
669 if (run >= 64) {
670 int markup = run - run % 64;
671 const uint8_t* p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
672 p += (markup / 64 - 1) * 2;
673 AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
674 }
675 run %= 64;
676 const uint8_t* p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
677 p += run * 2;
678 AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
679 }
680
FaxEncode2DLine(uint8_t * dest_buf,int * dest_bitpos,const uint8_t * src_buf,const std::vector<uint8_t> & ref_buf,int cols)681 void FaxEncode2DLine(uint8_t* dest_buf,
682 int* dest_bitpos,
683 const uint8_t* src_buf,
684 const std::vector<uint8_t>& ref_buf,
685 int cols) {
686 int a0 = -1;
687 bool a0color = true;
688 while (1) {
689 int a1 = FindBit(src_buf, cols, a0 + 1, !a0color);
690 int b1;
691 int b2;
692 FaxG4FindB1B2(ref_buf, cols, a0, a0color, &b1, &b2);
693 if (b2 < a1) {
694 *dest_bitpos += 3;
695 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
696 (*dest_bitpos)++;
697 a0 = b2;
698 } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
699 int delta = a1 - b1;
700 switch (delta) {
701 case 0:
702 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
703 break;
704 case 1:
705 case 2:
706 case 3:
707 *dest_bitpos += delta == 1 ? 1 : delta + 2;
708 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
709 (*dest_bitpos)++;
710 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
711 break;
712 case -1:
713 case -2:
714 case -3:
715 *dest_bitpos += delta == -1 ? 1 : -delta + 2;
716 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
717 (*dest_bitpos)++;
718 break;
719 }
720 (*dest_bitpos)++;
721 a0 = a1;
722 a0color = !a0color;
723 } else {
724 int a2 = FindBit(src_buf, cols, a1 + 1, a0color);
725 (*dest_bitpos)++;
726 (*dest_bitpos)++;
727 dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
728 (*dest_bitpos)++;
729 if (a0 < 0) {
730 a0 = 0;
731 }
732 FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
733 FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, !a0color);
734 a0 = a2;
735 }
736 if (a0 >= cols) {
737 return;
738 }
739 }
740 }
741
742 class CCodec_FaxEncoder {
743 public:
744 CCodec_FaxEncoder(const uint8_t* src_buf, int width, int height, int pitch);
745 ~CCodec_FaxEncoder();
746 void Encode(std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
747 uint32_t* dest_size);
748
749 private:
750 CFX_BinaryBuf m_DestBuf;
751 std::vector<uint8_t> m_RefLine;
752 uint8_t* m_pLineBuf;
753 const int m_Cols;
754 const int m_Rows;
755 const int m_Pitch;
756 const uint8_t* m_pSrcBuf;
757 };
758
CCodec_FaxEncoder(const uint8_t * src_buf,int width,int height,int pitch)759 CCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf,
760 int width,
761 int height,
762 int pitch)
763 : m_Cols(width), m_Rows(height), m_Pitch(pitch), m_pSrcBuf(src_buf) {
764 m_RefLine.resize(m_Pitch);
765 FXSYS_memset(m_RefLine.data(), 0xff, m_Pitch);
766 m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
767 m_DestBuf.EstimateSize(0, 10240);
768 }
769
~CCodec_FaxEncoder()770 CCodec_FaxEncoder::~CCodec_FaxEncoder() {
771 FX_Free(m_pLineBuf);
772 }
773
Encode(std::unique_ptr<uint8_t,FxFreeDeleter> * dest_buf,uint32_t * dest_size)774 void CCodec_FaxEncoder::Encode(
775 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
776 uint32_t* dest_size) {
777 int dest_bitpos = 0;
778 uint8_t last_byte = 0;
779 for (int i = 0; i < m_Rows; i++) {
780 const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch;
781 FXSYS_memset(m_pLineBuf, 0, m_Pitch * 8);
782 m_pLineBuf[0] = last_byte;
783 FaxEncode2DLine(m_pLineBuf, &dest_bitpos, scan_line, m_RefLine, m_Cols);
784 m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
785 last_byte = m_pLineBuf[dest_bitpos / 8];
786 dest_bitpos %= 8;
787 FXSYS_memcpy(m_RefLine.data(), scan_line, m_Pitch);
788 }
789 if (dest_bitpos) {
790 m_DestBuf.AppendByte(last_byte);
791 }
792 *dest_size = m_DestBuf.GetSize();
793 *dest_buf = m_DestBuf.DetachBuffer();
794 }
795
796 } // namespace
797
FaxEncode(const uint8_t * src_buf,int width,int height,int pitch,std::unique_ptr<uint8_t,FxFreeDeleter> * dest_buf,uint32_t * dest_size)798 void CCodec_FaxModule::FaxEncode(
799 const uint8_t* src_buf,
800 int width,
801 int height,
802 int pitch,
803 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
804 uint32_t* dest_size) {
805 CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
806 encoder.Encode(dest_buf, dest_size);
807 }
808
809 #endif
810