Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / fxcodec / codec / fx_codec_fax.cpp
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 uint8_t 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 uint8_t 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
46 int _FindBit(const uint8_t* 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         uint8_t 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     uint8_t 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 }
82 void _FaxG4FindB1B2(const uint8_t* ref_buf, int columns, int a0, FX_BOOL a0color, int& b1, int& b2)
83 {
84     if (a0color) {
85         a0color = 1;
86     }
87     uint8_t 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 }
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 uint8_t 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 uint8_t 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 };
378 int _FaxGetRun(FX_LPCBYTE ins_array, const uint8_t* src_buf, int& bitpos, int bitsize)
379 {
380     FX_DWORD code = 0;
381     int ins_off = 0;
382     while (1) {
383         uint8_t 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 }
403 FX_BOOL _FaxG4GetRow(const uint8_t* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const uint8_t* 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 }
525 FX_BOOL _FaxSkipEOL(const uint8_t* 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 }
539 FX_BOOL _FaxGet1DLine(const uint8_t* 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);
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 };
592 CCodec_FaxDecoder::CCodec_FaxDecoder()
593 {
594     m_pScanlineBuf = NULL;
595     m_pRefBuf = NULL;
596 }
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 }
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(uint8_t, m_Pitch);
625     m_pRefBuf = FX_Alloc(uint8_t, 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 }
633 FX_BOOL CCodec_FaxDecoder::v_Rewind()
634 {
635     FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);
636     bitpos = 0;
637     return TRUE;
638 }
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 }
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" {
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(uint8_t, 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 uint8_t 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 uint8_t 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 uint8_t 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 uint8_t 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 };
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 }
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 }
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 };
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(uint8_t, m_Pitch);
939     FXSYS_memset8(m_pRefLine, 0xff, m_Pitch);
940     m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
941     m_DestBuf.EstimateSize(0, 10240);
942 }
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 }
952 void CCodec_FaxEncoder::Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
953 {
954     int dest_bitpos = 0;
955     uint8_t 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 }
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 }
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 }