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