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