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 "../../../include/fxcodec/fx_codec.h"
8 #include "codec_int.h"
9 const FX_BYTE OneLeadPos[256] = {
10 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
11 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
13 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
14 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24 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,
26 };
27 const FX_BYTE ZeroLeadPos[256] = {
28 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 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,
32 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,
34 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,
36 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
37 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,
39 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,
41 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
42 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
43 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
44 };
45
_FindBit(const FX_BYTE * data_buf,int max_pos,int start_pos,int bit)46 int _FindBit(const FX_BYTE* data_buf, int max_pos, int start_pos, int bit)
47 {
48 if (start_pos >= max_pos) {
49 return max_pos;
50 }
51 FX_LPCBYTE leading_pos = bit ? OneLeadPos : ZeroLeadPos;
52 if (start_pos % 8) {
53 FX_BYTE data = data_buf[start_pos / 8];
54 if (bit) {
55 data &= 0xff >> (start_pos % 8);
56 } else {
57 data |= 0xff << (8 - start_pos % 8);
58 }
59 if (leading_pos[data] < 8) {
60 return start_pos / 8 * 8 + leading_pos[data];
61 }
62 start_pos += 7;
63 }
64 FX_BYTE skip = bit ? 0x00 : 0xff;
65 int byte_pos = start_pos / 8;
66 int max_byte = (max_pos + 7) / 8;
67 while (byte_pos < max_byte) {
68 if (data_buf[byte_pos] != skip) {
69 break;
70 }
71 byte_pos ++;
72 }
73 if (byte_pos == max_byte) {
74 return max_pos;
75 }
76 int pos = leading_pos[data_buf[byte_pos]] + byte_pos * 8;
77 if (pos > max_pos) {
78 pos = max_pos;
79 }
80 return pos;
81 }
_FaxG4FindB1B2(const FX_BYTE * ref_buf,int columns,int a0,FX_BOOL a0color,int & b1,int & b2)82 void _FaxG4FindB1B2(const FX_BYTE* ref_buf, int columns, int a0, FX_BOOL a0color, int& b1, int& b2)
83 {
84 if (a0color) {
85 a0color = 1;
86 }
87 FX_BYTE first_bit = (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
88 b1 = _FindBit(ref_buf, columns, a0 + 1, !first_bit);
89 if (b1 >= columns) {
90 b1 = b2 = columns;
91 return;
92 }
93 if (first_bit == !a0color) {
94 b1 = _FindBit(ref_buf, columns, b1 + 1, first_bit);
95 first_bit = !first_bit;
96 }
97 if (b1 >= columns) {
98 b1 = b2 = columns;
99 return;
100 }
101 b2 = _FindBit(ref_buf, columns, b1 + 1, first_bit);
102 }
_FaxFillBits(FX_LPBYTE dest_buf,int columns,int startpos,int endpos)103 void _FaxFillBits(FX_LPBYTE dest_buf, int columns, int startpos, int endpos)
104 {
105 if (startpos < 0) {
106 startpos = 0;
107 }
108 if (endpos < 0) {
109 endpos = 0;
110 }
111 if (endpos >= columns) {
112 endpos = columns;
113 }
114 if (startpos >= endpos) {
115 return;
116 }
117 int first_byte = startpos / 8;
118 int last_byte = (endpos - 1) / 8;
119 if (first_byte == last_byte) {
120 for (int i = startpos % 8; i <= (endpos - 1) % 8; i ++) {
121 dest_buf[first_byte] -= 1 << (7 - i);
122 }
123 return;
124 }
125 int i;
126 for (i = startpos % 8; i < 8; i ++) {
127 dest_buf[first_byte] -= 1 << (7 - i);
128 }
129 for (i = 0; i <= (endpos - 1) % 8; i ++) {
130 dest_buf[last_byte] -= 1 << (7 - i);
131 }
132 if (last_byte > first_byte + 1) {
133 FXSYS_memset32(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
134 }
135 }
136 #define NEXTBIT src_buf[bitpos/8] & (1 << (7-bitpos%8)); bitpos ++;
137 #define ADDBIT(code, bit) code = code << 1; if (bit) code ++;
138 #define GETBIT(bitpos) src_buf[bitpos/8] & (1 << (7-bitpos%8))
139 static const FX_BYTE FaxBlackRunIns[] = {
140 0,
141 2,
142 0x02, 3, 0,
143 0x03, 2, 0,
144 2,
145 0x02, 1, 0,
146 0x03, 4, 0,
147 2,
148 0x02, 6, 0,
149 0x03, 5, 0,
150 1,
151 0x03, 7, 0,
152 2,
153 0x04, 9, 0,
154 0x05, 8, 0,
155 3,
156 0x04, 10, 0,
157 0x05, 11, 0,
158 0x07, 12, 0,
159 2,
160 0x04, 13, 0,
161 0x07, 14, 0,
162 1,
163 0x18, 15, 0,
164 5,
165 0x08, 18, 0,
166 0x0f, 64, 0,
167 0x17, 16, 0,
168 0x18, 17, 0,
169 0x37, 0, 0,
170 10,
171 0x08, 0x00, 0x07,
172 0x0c, 0x40, 0x07,
173 0x0d, 0x80, 0x07,
174 0x17, 24, 0,
175 0x18, 25, 0,
176 0x28, 23, 0,
177 0x37, 22, 0,
178 0x67, 19, 0,
179 0x68, 20, 0,
180 0x6c, 21, 0,
181 54,
182 0x12, 1984 % 256, 1984 / 256,
183 0x13, 2048 % 256, 2048 / 256,
184 0x14, 2112 % 256, 2112 / 256,
185 0x15, 2176 % 256, 2176 / 256,
186 0x16, 2240 % 256, 2240 / 256,
187 0x17, 2304 % 256, 2304 / 256,
188 0x1c, 2368 % 256, 2368 / 256,
189 0x1d, 2432 % 256, 2432 / 256,
190 0x1e, 2496 % 256, 2496 / 256,
191 0x1f, 2560 % 256, 2560 / 256,
192 0x24, 52, 0,
193 0x27, 55, 0,
194 0x28, 56, 0,
195 0x2b, 59, 0,
196 0x2c, 60, 0,
197 0x33, 320 % 256, 320 / 256,
198 0x34, 384 % 256, 384 / 256,
199 0x35, 448 % 256, 448 / 256,
200 0x37, 53, 0,
201 0x38, 54, 0,
202 0x52, 50, 0,
203 0x53, 51, 0,
204 0x54, 44, 0,
205 0x55, 45, 0,
206 0x56, 46, 0,
207 0x57, 47, 0,
208 0x58, 57, 0,
209 0x59, 58, 0,
210 0x5a, 61, 0,
211 0x5b, 256 % 256, 256 / 256,
212 0x64, 48, 0,
213 0x65, 49, 0,
214 0x66, 62, 0,
215 0x67, 63, 0,
216 0x68, 30, 0,
217 0x69, 31, 0,
218 0x6a, 32, 0,
219 0x6b, 33, 0,
220 0x6c, 40, 0,
221 0x6d, 41, 0,
222 0xc8, 128, 0,
223 0xc9, 192, 0,
224 0xca, 26, 0,
225 0xcb, 27, 0,
226 0xcc, 28, 0,
227 0xcd, 29, 0,
228 0xd2, 34, 0,
229 0xd3, 35, 0,
230 0xd4, 36, 0,
231 0xd5, 37, 0,
232 0xd6, 38, 0,
233 0xd7, 39, 0,
234 0xda, 42, 0,
235 0xdb, 43, 0,
236 20,
237 0x4a, 640 % 256, 640 / 256,
238 0x4b, 704 % 256, 704 / 256,
239 0x4c, 768 % 256, 768 / 256,
240 0x4d, 832 % 256, 832 / 256,
241 0x52, 1280 % 256, 1280 / 256,
242 0x53, 1344 % 256, 1344 / 256,
243 0x54, 1408 % 256, 1408 / 256,
244 0x55, 1472 % 256, 1472 / 256,
245 0x5a, 1536 % 256, 1536 / 256,
246 0x5b, 1600 % 256, 1600 / 256,
247 0x64, 1664 % 256, 1664 / 256,
248 0x65, 1728 % 256, 1728 / 256,
249 0x6c, 512 % 256, 512 / 256,
250 0x6d, 576 % 256, 576 / 256,
251 0x72, 896 % 256, 896 / 256,
252 0x73, 960 % 256, 960 / 256,
253 0x74, 1024 % 256, 1024 / 256,
254 0x75, 1088 % 256, 1088 / 256,
255 0x76, 1152 % 256, 1152 / 256,
256 0x77, 1216 % 256, 1216 / 256,
257 0xff
258 };
259 static const FX_BYTE FaxWhiteRunIns[] = {
260 0,
261 0,
262 0,
263 6,
264 0x07, 2, 0,
265 0x08, 3, 0,
266 0x0B, 4, 0,
267 0x0C, 5, 0,
268 0x0E, 6, 0,
269 0x0F, 7, 0,
270 6,
271 0x07, 10, 0,
272 0x08, 11, 0,
273 0x12, 128, 0,
274 0x13, 8, 0,
275 0x14, 9, 0,
276 0x1b, 64, 0,
277 9,
278 0x03, 13, 0,
279 0x07, 1, 0,
280 0x08, 12, 0,
281 0x17, 192, 0,
282 0x18, 1664 % 256, 1664 / 256,
283 0x2a, 16, 0,
284 0x2B, 17, 0,
285 0x34, 14, 0,
286 0x35, 15, 0,
287 12,
288 0x03, 22, 0,
289 0x04, 23, 0,
290 0x08, 20, 0,
291 0x0c, 19, 0,
292 0x13, 26, 0,
293 0x17, 21, 0,
294 0x18, 28, 0,
295 0x24, 27, 0,
296 0x27, 18, 0,
297 0x28, 24, 0,
298 0x2B, 25, 0,
299 0x37, 256 % 256, 256 / 256,
300 42,
301 0x02, 29, 0,
302 0x03, 30, 0,
303 0x04, 45, 0,
304 0x05, 46, 0,
305 0x0a, 47, 0,
306 0x0b, 48, 0,
307 0x12, 33, 0,
308 0x13, 34, 0,
309 0x14, 35, 0,
310 0x15, 36, 0,
311 0x16, 37, 0,
312 0x17, 38, 0,
313 0x1a, 31, 0,
314 0x1b, 32, 0,
315 0x24, 53, 0,
316 0x25, 54, 0,
317 0x28, 39, 0,
318 0x29, 40, 0,
319 0x2a, 41, 0,
320 0x2b, 42, 0,
321 0x2c, 43, 0,
322 0x2d, 44, 0,
323 0x32, 61, 0,
324 0x33, 62, 0,
325 0x34, 63, 0,
326 0x35, 0, 0,
327 0x36, 320 % 256, 320 / 256,
328 0x37, 384 % 256, 384 / 256,
329 0x4a, 59, 0,
330 0x4b, 60, 0,
331 0x52, 49, 0,
332 0x53, 50, 0,
333 0x54, 51, 0,
334 0x55, 52, 0,
335 0x58, 55, 0,
336 0x59, 56, 0,
337 0x5a, 57, 0,
338 0x5b, 58, 0,
339 0x64, 448 % 256, 448 / 256,
340 0x65, 512 % 256, 512 / 256,
341 0x67, 640 % 256, 640 / 256,
342 0x68, 576 % 256, 576 / 256,
343 16,
344 0x98, 1472 % 256, 1472 / 256,
345 0x99, 1536 % 256, 1536 / 256,
346 0x9a, 1600 % 256, 1600 / 256,
347 0x9b, 1728 % 256, 1728 / 256,
348 0xcc, 704 % 256, 704 / 256,
349 0xcd, 768 % 256, 768 / 256,
350 0xd2, 832 % 256, 832 / 256,
351 0xd3, 896 % 256, 896 / 256,
352 0xd4, 960 % 256, 960 / 256,
353 0xd5, 1024 % 256, 1024 / 256,
354 0xd6, 1088 % 256, 1088 / 256,
355 0xd7, 1152 % 256, 1152 / 256,
356 0xd8, 1216 % 256, 1216 / 256,
357 0xd9, 1280 % 256, 1280 / 256,
358 0xda, 1344 % 256, 1344 / 256,
359 0xdb, 1408 % 256, 1408 / 256,
360 0,
361 3,
362 0x08, 1792 % 256, 1792 / 256,
363 0x0c, 1856 % 256, 1856 / 256,
364 0x0d, 1920 % 256, 1920 / 256,
365 10,
366 0x12, 1984 % 256, 1984 / 256,
367 0x13, 2048 % 256, 2048 / 256,
368 0x14, 2112 % 256, 2112 / 256,
369 0x15, 2176 % 256, 2176 / 256,
370 0x16, 2240 % 256, 2240 / 256,
371 0x17, 2304 % 256, 2304 / 256,
372 0x1c, 2368 % 256, 2368 / 256,
373 0x1d, 2432 % 256, 2432 / 256,
374 0x1e, 2496 % 256, 2496 / 256,
375 0x1f, 2560 % 256, 2560 / 256,
376 0xff,
377 };
_FaxGetRun(FX_LPCBYTE ins_array,const FX_BYTE * src_buf,int & bitpos,int bitsize)378 int _FaxGetRun(FX_LPCBYTE ins_array, const FX_BYTE* src_buf, int& bitpos, int bitsize)
379 {
380 FX_DWORD code = 0;
381 int ins_off = 0;
382 while (1) {
383 FX_BYTE ins = ins_array[ins_off++];
384 if (ins == 0xff) {
385 return -1;
386 }
387 if (bitpos >= bitsize) {
388 return -1;
389 }
390 code <<= 1;
391 if (src_buf[bitpos / 8] & (1 << (7 - bitpos % 8))) {
392 code ++;
393 }
394 bitpos ++;
395 int next_off = ins_off + ins * 3;
396 for (; ins_off < next_off; ins_off += 3) {
397 if (ins_array[ins_off] == code) {
398 return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256;
399 }
400 }
401 }
402 }
_FaxG4GetRow(const FX_BYTE * src_buf,int bitsize,int & bitpos,FX_LPBYTE dest_buf,const FX_BYTE * ref_buf,int columns)403 FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns)
404 {
405 int a0 = -1, a0color = 1;
406 while (1) {
407 if (bitpos >= bitsize) {
408 return FALSE;
409 }
410 int a1, a2, b1, b2;
411 _FaxG4FindB1B2(ref_buf, columns, a0, a0color, b1, b2);
412 FX_BOOL bit = NEXTBIT;
413 int v_delta = 0;
414 if (bit) {
415 } else {
416 if (bitpos >= bitsize) {
417 return FALSE;
418 }
419 FX_BOOL bit1 = NEXTBIT;
420 if (bitpos >= bitsize) {
421 return FALSE;
422 }
423 FX_BOOL bit2 = NEXTBIT;
424 if (bit1 && bit2) {
425 v_delta = 1;
426 } else if (bit1) {
427 v_delta = -1;
428 } else if (bit2) {
429 int run_len1 = 0;
430 while (1) {
431 int run = _FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize);
432 run_len1 += run;
433 if (run < 64) {
434 break;
435 }
436 }
437 if (a0 < 0) {
438 run_len1 ++;
439 }
440 a1 = a0 + run_len1;
441 if (!a0color) {
442 _FaxFillBits(dest_buf, columns, a0, a1);
443 }
444 int run_len2 = 0;
445 while (1) {
446 int run = _FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns, src_buf, bitpos, bitsize);
447 run_len2 += run;
448 if (run < 64) {
449 break;
450 }
451 }
452 a2 = a1 + run_len2;
453 if (a0color) {
454 _FaxFillBits(dest_buf, columns, a1, a2);
455 }
456 a0 = a2;
457 if (a0 < columns) {
458 continue;
459 }
460 return TRUE;
461 } else {
462 if (bitpos >= bitsize) {
463 return FALSE;
464 }
465 bit = NEXTBIT;
466 if (bit) {
467 if (!a0color) {
468 _FaxFillBits(dest_buf, columns, a0, b2);
469 }
470 if (b2 >= columns) {
471 return TRUE;
472 }
473 a0 = b2;
474 continue;
475 } else {
476 if (bitpos >= bitsize) {
477 return FALSE;
478 }
479 FX_BOOL bit1 = NEXTBIT;
480 if (bitpos >= bitsize) {
481 return FALSE;
482 }
483 FX_BOOL bit2 = NEXTBIT;
484 if (bit1 && bit2) {
485 v_delta = 2;
486 } else if (bit1) {
487 v_delta = -2;
488 } else if (bit2) {
489 if (bitpos >= bitsize) {
490 return FALSE;
491 }
492 bit = NEXTBIT;
493 if (bit) {
494 v_delta = 3;
495 } else {
496 v_delta = -3;
497 }
498 } else {
499 if (bitpos >= bitsize) {
500 return FALSE;
501 }
502 bit = NEXTBIT;
503 if (bit) {
504 bitpos += 3;
505 continue;
506 } else {
507 bitpos += 5;
508 return TRUE;
509 }
510 }
511 }
512 }
513 }
514 a1 = b1 + v_delta;
515 if (!a0color) {
516 _FaxFillBits(dest_buf, columns, a0, a1);
517 }
518 if (a1 >= columns) {
519 return TRUE;
520 }
521 a0 = a1;
522 a0color = !a0color;
523 }
524 }
_FaxSkipEOL(const FX_BYTE * src_buf,int bitsize,int & bitpos)525 FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos)
526 {
527 int startbit = bitpos;
528 while (bitpos < bitsize) {
529 int bit = NEXTBIT;
530 if (bit) {
531 if (bitpos - startbit <= 11) {
532 bitpos = startbit;
533 }
534 return TRUE;
535 }
536 }
537 return FALSE;
538 }
_FaxGet1DLine(const FX_BYTE * src_buf,int bitsize,int & bitpos,FX_LPBYTE dest_buf,int columns)539 FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns)
540 {
541 int color = TRUE;
542 int startpos = 0;
543 while (1) {
544 if (bitpos >= bitsize) {
545 return FALSE;
546 }
547 int run_len = 0;
548 while (1) {
549 int run = _FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize);
550 if (run < 0) {
551 while (bitpos < bitsize) {
552 int bit = NEXTBIT;
553 if (bit) {
554 return TRUE;
555 }
556 }
557 return FALSE;
558 }
559 run_len += run;
560 if (run < 64) {
561 break;
562 }
563 }
564 if (!color) {
565 _FaxFillBits(dest_buf, columns, startpos, startpos + run_len);
566 }
567 startpos += run_len;
568 if (startpos >= columns) {
569 break;
570 }
571 color = !color;
572 }
573 return TRUE;
574 }
575 class CCodec_FaxDecoder : public CCodec_ScanlineDecoder
576 {
577 public:
578 CCodec_FaxDecoder();
579 virtual ~CCodec_FaxDecoder();
580 FX_BOOL Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
581 int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows);
v_DownScale(int dest_width,int dest_height)582 virtual void v_DownScale(int dest_width, int dest_height) {}
583 virtual FX_BOOL v_Rewind();
584 virtual FX_LPBYTE v_GetNextLine();
585 virtual FX_DWORD GetSrcOffset();
586 int m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack;
587 int bitpos;
588 FX_LPCBYTE m_pSrcBuf;
589 FX_DWORD m_SrcSize;
590 FX_LPBYTE m_pScanlineBuf, m_pRefBuf;
591 };
CCodec_FaxDecoder()592 CCodec_FaxDecoder::CCodec_FaxDecoder()
593 {
594 m_pScanlineBuf = NULL;
595 m_pRefBuf = NULL;
596 }
~CCodec_FaxDecoder()597 CCodec_FaxDecoder::~CCodec_FaxDecoder()
598 {
599 if (m_pScanlineBuf) {
600 FX_Free(m_pScanlineBuf);
601 }
602 if (m_pRefBuf) {
603 FX_Free(m_pRefBuf);
604 }
605 }
Create(FX_LPCBYTE src_buf,FX_DWORD src_size,int width,int height,int K,FX_BOOL EndOfLine,FX_BOOL EncodedByteAlign,FX_BOOL BlackIs1,int Columns,int Rows)606 FX_BOOL CCodec_FaxDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
607 int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows)
608 {
609 m_Encoding = K;
610 m_bEndOfLine = EndOfLine;
611 m_bByteAlign = EncodedByteAlign;
612 m_bBlack = BlackIs1;
613 m_OrigWidth = Columns;
614 m_OrigHeight = Rows;
615 if (m_OrigWidth == 0) {
616 m_OrigWidth = width;
617 }
618 if (m_OrigHeight == 0) {
619 m_OrigHeight = height;
620 }
621 m_Pitch = (m_OrigWidth + 31) / 32 * 4;
622 m_OutputWidth = m_OrigWidth;
623 m_OutputHeight = m_OrigHeight;
624 m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch);
625 m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch);
626 m_pSrcBuf = src_buf;
627 m_SrcSize = src_size;
628 m_nComps = 1;
629 m_bpc = 1;
630 m_bColorTransformed = FALSE;
631 return TRUE;
632 }
v_Rewind()633 FX_BOOL CCodec_FaxDecoder::v_Rewind()
634 {
635 FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);
636 bitpos = 0;
637 return TRUE;
638 }
v_GetNextLine()639 FX_LPBYTE CCodec_FaxDecoder::v_GetNextLine()
640 {
641 int bitsize = m_SrcSize * 8;
642 _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
643 if (bitpos >= bitsize) {
644 return NULL;
645 }
646 FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
647 if (m_Encoding < 0) {
648 _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth);
649 FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
650 } else if (m_Encoding == 0) {
651 _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
652 } else {
653 FX_BOOL bNext1D = m_pSrcBuf[bitpos / 8] & (1 << (7 - bitpos % 8));
654 bitpos ++;
655 if (bNext1D) {
656 _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
657 } else {
658 _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth);
659 }
660 FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
661 }
662 if (m_bEndOfLine) {
663 _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
664 }
665 if (m_bByteAlign && bitpos < bitsize) {
666 int bitpos0 = bitpos;
667 int bitpos1 = (bitpos + 7) / 8 * 8;
668 while (m_bByteAlign && bitpos0 < bitpos1) {
669 int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
670 if (bit != 0) {
671 m_bByteAlign = FALSE;
672 } else {
673 bitpos0 ++;
674 }
675 }
676 if (m_bByteAlign) {
677 bitpos = bitpos1;
678 }
679 }
680 if (m_bBlack) {
681 for (int i = 0; i < m_Pitch; i ++) {
682 m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
683 }
684 }
685 return m_pScanlineBuf;
686 }
GetSrcOffset()687 FX_DWORD CCodec_FaxDecoder::GetSrcOffset()
688 {
689 FX_DWORD ret = (bitpos + 7) / 8;
690 if (ret > m_SrcSize) {
691 ret = m_SrcSize;
692 }
693 return ret;
694 }
695 extern "C" {
_FaxG4Decode(void *,FX_LPCBYTE src_buf,FX_DWORD src_size,int * pbitpos,FX_LPBYTE dest_buf,int width,int height,int pitch)696 void _FaxG4Decode(void*, FX_LPCBYTE src_buf, FX_DWORD src_size, int* pbitpos, FX_LPBYTE dest_buf, int width, int height, int pitch)
697 {
698 if (pitch == 0) {
699 pitch = (width + 7) / 8;
700 }
701 FX_LPBYTE ref_buf = FX_Alloc(FX_BYTE, pitch);
702 FXSYS_memset8(ref_buf, 0xff, pitch);
703 int bitpos = *pbitpos;
704 for (int iRow = 0; iRow < height; iRow ++) {
705 FX_LPBYTE line_buf = dest_buf + iRow * pitch;
706 FXSYS_memset8(line_buf, 0xff, pitch);
707 _FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width);
708 FXSYS_memcpy32(ref_buf, line_buf, pitch);
709 }
710 FX_Free(ref_buf);
711 *pbitpos = bitpos;
712 }
713 };
714 static const FX_BYTE BlackRunTerminator[128] = {
715 0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4, 0x03, 5,
716 0x05, 6, 0x04, 6, 0x04, 7, 0x05, 7, 0x07, 7, 0x04, 8, 0x07, 8, 0x18, 9,
717 0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11, 0x6c, 11, 0x37, 11, 0x28, 11,
718 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12, 0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12,
719 0x6a, 12, 0x6b, 12, 0xd2, 12, 0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12,
720 0x6c, 12, 0x6d, 12, 0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12,
721 0x64, 12, 0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
722 0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12, 0x67, 12,
723 };
724 static const FX_BYTE BlackRunMarkup[80] = {
725 0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12, 0x6c, 13,
726 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13, 0x73, 13, 0x74, 13,
727 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13, 0x54, 13, 0x55, 13, 0x5a, 13,
728 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11, 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12,
729 0x14, 12, 0x15, 12, 0x16, 12, 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
730 };
731 static const FX_BYTE WhiteRunTerminator[128] = {
732 0x35, 8,
733 0x07, 6,
734 0x07, 4,
735 0x08, 4,
736 0x0B, 4,
737 0x0C, 4,
738 0x0E, 4,
739 0x0F, 4,
740 0x13, 5,
741 0x14, 5,
742 0x07, 5,
743 0x08, 5,
744 0x08, 6,
745 0x03, 6,
746 0x34, 6,
747 0x35, 6,
748 0x2a, 6,
749 0x2B, 6,
750 0x27, 7,
751 0x0c, 7,
752 0x08, 7,
753 0x17, 7,
754 0x03, 7,
755 0x04, 7,
756 0x28, 7,
757 0x2B, 7,
758 0x13, 7,
759 0x24, 7,
760 0x18, 7,
761 0x02, 8,
762 0x03, 8,
763 0x1a, 8,
764 0x1b, 8,
765 0x12, 8,
766 0x13, 8,
767 0x14, 8,
768 0x15, 8,
769 0x16, 8,
770 0x17, 8,
771 0x28, 8,
772 0x29, 8,
773 0x2a, 8,
774 0x2b, 8,
775 0x2c, 8,
776 0x2d, 8,
777 0x04, 8,
778 0x05, 8,
779 0x0a, 8,
780 0x0b, 8,
781 0x52, 8,
782 0x53, 8,
783 0x54, 8,
784 0x55, 8,
785 0x24, 8,
786 0x25, 8,
787 0x58, 8,
788 0x59, 8,
789 0x5a, 8,
790 0x5b, 8,
791 0x4a, 8,
792 0x4b, 8,
793 0x32, 8,
794 0x33, 8,
795 0x34, 8,
796 };
797 static const FX_BYTE WhiteRunMarkup[80] = {
798 0x1b, 5,
799 0x12, 5,
800 0x17, 6,
801 0x37, 7,
802 0x36, 8,
803 0x37, 8,
804 0x64, 8,
805 0x65, 8,
806 0x68, 8,
807 0x67, 8,
808 0xcc, 9,
809 0xcd, 9,
810 0xd2, 9,
811 0xd3, 9,
812 0xd4, 9,
813 0xd5, 9,
814 0xd6, 9,
815 0xd7, 9,
816 0xd8, 9,
817 0xd9, 9,
818 0xda, 9,
819 0xdb, 9,
820 0x98, 9,
821 0x99, 9,
822 0x9a, 9,
823 0x18, 6,
824 0x9b, 9,
825 0x08, 11,
826 0x0c, 11,
827 0x0d, 11,
828 0x12, 12,
829 0x13, 12,
830 0x14, 12,
831 0x15, 12,
832 0x16, 12,
833 0x17, 12,
834 0x1c, 12,
835 0x1d, 12,
836 0x1e, 12,
837 0x1f, 12,
838 };
_AddBitStream(FX_LPBYTE dest_buf,int & dest_bitpos,int data,int bitlen)839 static void _AddBitStream(FX_LPBYTE dest_buf, int& dest_bitpos, int data, int bitlen)
840 {
841 for (int i = bitlen - 1; i >= 0; i --) {
842 if (data & (1 << i)) {
843 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
844 }
845 dest_bitpos ++;
846 }
847 }
_FaxEncodeRun(FX_LPBYTE dest_buf,int & dest_bitpos,int run,FX_BOOL bWhite)848 static void _FaxEncodeRun(FX_LPBYTE dest_buf, int& dest_bitpos, int run, FX_BOOL bWhite)
849 {
850 while (run >= 2560) {
851 _AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
852 run -= 2560;
853 }
854 if (run >= 64) {
855 int markup = run - run % 64;
856 FX_LPCBYTE p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
857 p += (markup / 64 - 1) * 2;
858 _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
859 }
860 run %= 64;
861 FX_LPCBYTE p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
862 p += run * 2;
863 _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
864 }
_FaxEncode2DLine(FX_LPBYTE dest_buf,int & dest_bitpos,FX_LPCBYTE src_buf,FX_LPCBYTE ref_buf,int cols)865 static void _FaxEncode2DLine(FX_LPBYTE dest_buf, int& dest_bitpos, FX_LPCBYTE src_buf, FX_LPCBYTE ref_buf, int cols)
866 {
867 int a0 = -1, a0color = 1;
868 while (1) {
869 int a1 = _FindBit(src_buf, cols, a0 + 1, 1 - a0color);
870 int b1, b2;
871 _FaxG4FindB1B2(ref_buf, cols, a0, a0color, b1, b2);
872 if (b2 < a1) {
873 dest_bitpos += 3;
874 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
875 dest_bitpos ++;
876 a0 = b2;
877 } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
878 int delta = a1 - b1;
879 switch (delta) {
880 case 0:
881 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
882 break;
883 case 1:
884 case 2:
885 case 3:
886 dest_bitpos += delta == 1 ? 1 : delta + 2;
887 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
888 dest_bitpos ++;
889 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
890 break;
891 case -1:
892 case -2:
893 case -3:
894 dest_bitpos += delta == -1 ? 1 : -delta + 2;
895 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
896 dest_bitpos ++;
897 break;
898 }
899 dest_bitpos ++;
900 a0 = a1;
901 a0color = 1 - a0color;
902 } else {
903 int a2 = _FindBit(src_buf, cols, a1 + 1, a0color);
904 dest_bitpos ++;
905 dest_bitpos ++;
906 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
907 dest_bitpos ++;
908 if (a0 < 0) {
909 a0 = 0;
910 }
911 _FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
912 _FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, 1 - a0color);
913 a0 = a2;
914 }
915 if (a0 >= cols) {
916 return;
917 }
918 }
919 }
920 class CCodec_FaxEncoder
921 {
922 public:
923 CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch);
924 ~CCodec_FaxEncoder();
925 void Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
926 void Encode2DLine(FX_LPCBYTE scan_line);
927 CFX_BinaryBuf m_DestBuf;
928 FX_LPBYTE m_pRefLine, m_pLineBuf;
929 int m_Cols, m_Rows, m_Pitch;
930 FX_LPCBYTE m_pSrcBuf;
931 };
CCodec_FaxEncoder(FX_LPCBYTE src_buf,int width,int height,int pitch)932 CCodec_FaxEncoder::CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch)
933 {
934 m_pSrcBuf = src_buf;
935 m_Cols = width;
936 m_Rows = height;
937 m_Pitch = pitch;
938 m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch);
939 FXSYS_memset8(m_pRefLine, 0xff, m_Pitch);
940 m_pLineBuf = FX_Alloc2D(FX_BYTE, m_Pitch, 8);
941 m_DestBuf.EstimateSize(0, 10240);
942 }
~CCodec_FaxEncoder()943 CCodec_FaxEncoder::~CCodec_FaxEncoder()
944 {
945 if (m_pRefLine) {
946 FX_Free(m_pRefLine);
947 }
948 if (m_pLineBuf) {
949 FX_Free(m_pLineBuf);
950 }
951 }
Encode(FX_LPBYTE & dest_buf,FX_DWORD & dest_size)952 void CCodec_FaxEncoder::Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
953 {
954 int dest_bitpos = 0;
955 FX_BYTE last_byte = 0;
956 for (int i = 0; i < m_Rows; i ++) {
957 FX_LPCBYTE scan_line = m_pSrcBuf + i * m_Pitch;
958 FXSYS_memset32(m_pLineBuf, 0, m_Pitch * 8);
959 m_pLineBuf[0] = last_byte;
960 _FaxEncode2DLine(m_pLineBuf, dest_bitpos, scan_line, m_pRefLine, m_Cols);
961 m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
962 last_byte = m_pLineBuf[dest_bitpos / 8];
963 dest_bitpos %= 8;
964 FXSYS_memcpy32(m_pRefLine, scan_line, m_Pitch);
965 }
966 if (dest_bitpos) {
967 m_DestBuf.AppendByte(last_byte);
968 }
969 dest_buf = m_DestBuf.GetBuffer();
970 dest_size = m_DestBuf.GetSize();
971 m_DestBuf.DetachBuffer();
972 }
Encode(FX_LPCBYTE src_buf,int width,int height,int pitch,FX_LPBYTE & dest_buf,FX_DWORD & dest_size)973 FX_BOOL CCodec_FaxModule::Encode(FX_LPCBYTE src_buf, int width, int height, int pitch, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
974 {
975 CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
976 encoder.Encode(dest_buf, dest_size);
977 return TRUE;
978 }
CreateDecoder(FX_LPCBYTE src_buf,FX_DWORD src_size,int width,int height,int K,FX_BOOL EndOfLine,FX_BOOL EncodedByteAlign,FX_BOOL BlackIs1,int Columns,int Rows)979 ICodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
980 int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows)
981 {
982 CCodec_FaxDecoder* pDecoder = new CCodec_FaxDecoder;
983 pDecoder->Create(src_buf, src_size, width, height, K, EndOfLine, EncodedByteAlign, BlackIs1, Columns, Rows);
984 return pDecoder;
985 }
986