Remove a few unused variables, functions, and member variables.
[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 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
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 }
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 }
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 };
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 }
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 }
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 }
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);
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(FX_BYTE, m_Pitch);
625     if (m_pScanlineBuf == NULL) {
626         return FALSE;
627     }
628     m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch);
629     if (m_pRefBuf == NULL) {
630         return FALSE;
631     }
632     m_pSrcBuf = src_buf;
633     m_SrcSize = src_size;
634     m_nComps = 1;
635     m_bpc = 1;
636     m_bColorTransformed = FALSE;
637     return TRUE;
638 }
639 FX_BOOL CCodec_FaxDecoder::v_Rewind()
640 {
641     FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);
642     bitpos = 0;
643     return TRUE;
644 }
645 FX_LPBYTE CCodec_FaxDecoder::v_GetNextLine()
646 {
647     int bitsize = m_SrcSize * 8;
648     _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
649     if (bitpos >= bitsize) {
650         return NULL;
651     }
652     FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
653     if (m_Encoding < 0) {
654         _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth);
655         FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
656     } else if (m_Encoding == 0) {
657         _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
658     } else {
659         FX_BOOL bNext1D = m_pSrcBuf[bitpos / 8] & (1 << (7 - bitpos % 8));
660         bitpos ++;
661         if (bNext1D) {
662             _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
663         } else {
664             _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth);
665         }
666         FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
667     }
668     if (m_bEndOfLine) {
669         _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
670     }
671     if (m_bByteAlign && bitpos < bitsize) {
672         int bitpos0 = bitpos;
673         int bitpos1 = (bitpos + 7) / 8 * 8;
674         while (m_bByteAlign && bitpos0 < bitpos1) {
675             int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
676             if (bit != 0) {
677                 m_bByteAlign = FALSE;
678             } else {
679                 bitpos0 ++;
680             }
681         }
682         if (m_bByteAlign) {
683             bitpos = bitpos1;
684         }
685     }
686     if (m_bBlack) {
687         for (int i = 0; i < m_Pitch; i ++) {
688             m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
689         }
690     }
691     return m_pScanlineBuf;
692 }
693 FX_DWORD CCodec_FaxDecoder::GetSrcOffset()
694 {
695     FX_DWORD ret = (bitpos + 7) / 8;
696     if (ret > m_SrcSize) {
697         ret = m_SrcSize;
698     }
699     return ret;
700 }
701 extern "C" {
702     void _FaxG4Decode(void*, FX_LPCBYTE src_buf, FX_DWORD src_size, int* pbitpos, FX_LPBYTE dest_buf, int width, int height, int pitch)
703     {
704         if (pitch == 0) {
705             pitch = (width + 7) / 8;
706         }
707         FX_LPBYTE ref_buf = FX_Alloc(FX_BYTE, pitch);
708         if (ref_buf == NULL) {
709             return;
710         }
711         FXSYS_memset8(ref_buf, 0xff, pitch);
712         int bitpos = *pbitpos;
713         for (int iRow = 0; iRow < height; iRow ++) {
714             FX_LPBYTE line_buf = dest_buf + iRow * pitch;
715             FXSYS_memset8(line_buf, 0xff, pitch);
716             _FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width);
717             FXSYS_memcpy32(ref_buf, line_buf, pitch);
718         }
719         FX_Free(ref_buf);
720         *pbitpos = bitpos;
721     }
722 };
723 static const FX_BYTE BlackRunTerminator[128] = {
724     0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4, 0x03, 5,
725     0x05, 6, 0x04, 6, 0x04, 7, 0x05, 7, 0x07, 7, 0x04, 8, 0x07, 8, 0x18, 9,
726     0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11, 0x6c, 11, 0x37, 11, 0x28, 11,
727     0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12, 0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12,
728     0x6a, 12, 0x6b, 12, 0xd2, 12, 0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12,
729     0x6c, 12, 0x6d, 12, 0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12,
730     0x64, 12, 0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
731     0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12, 0x67, 12,
732 };
733 static const FX_BYTE BlackRunMarkup[80] = {
734     0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12, 0x6c, 13,
735     0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13, 0x73, 13, 0x74, 13,
736     0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13, 0x54, 13, 0x55, 13, 0x5a, 13,
737     0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11, 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12,
738     0x14, 12, 0x15, 12, 0x16, 12, 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
739 };
740 static const FX_BYTE WhiteRunTerminator[128] = {
741     0x35, 8,
742     0x07, 6,
743     0x07, 4,
744     0x08, 4,
745     0x0B, 4,
746     0x0C, 4,
747     0x0E, 4,
748     0x0F, 4,
749     0x13, 5,
750     0x14, 5,
751     0x07, 5,
752     0x08, 5,
753     0x08, 6,
754     0x03, 6,
755     0x34, 6,
756     0x35, 6,
757     0x2a, 6,
758     0x2B, 6,
759     0x27, 7,
760     0x0c, 7,
761     0x08, 7,
762     0x17, 7,
763     0x03, 7,
764     0x04, 7,
765     0x28, 7,
766     0x2B, 7,
767     0x13, 7,
768     0x24, 7,
769     0x18, 7,
770     0x02, 8,
771     0x03, 8,
772     0x1a, 8,
773     0x1b, 8,
774     0x12, 8,
775     0x13, 8,
776     0x14, 8,
777     0x15, 8,
778     0x16, 8,
779     0x17, 8,
780     0x28, 8,
781     0x29, 8,
782     0x2a, 8,
783     0x2b, 8,
784     0x2c, 8,
785     0x2d, 8,
786     0x04, 8,
787     0x05, 8,
788     0x0a, 8,
789     0x0b, 8,
790     0x52, 8,
791     0x53, 8,
792     0x54, 8,
793     0x55, 8,
794     0x24, 8,
795     0x25, 8,
796     0x58, 8,
797     0x59, 8,
798     0x5a, 8,
799     0x5b, 8,
800     0x4a, 8,
801     0x4b, 8,
802     0x32, 8,
803     0x33, 8,
804     0x34, 8,
805 };
806 static const FX_BYTE WhiteRunMarkup[80] = {
807     0x1b, 5,
808     0x12, 5,
809     0x17, 6,
810     0x37, 7,
811     0x36, 8,
812     0x37, 8,
813     0x64, 8,
814     0x65, 8,
815     0x68, 8,
816     0x67, 8,
817     0xcc, 9,
818     0xcd, 9,
819     0xd2, 9,
820     0xd3, 9,
821     0xd4, 9,
822     0xd5, 9,
823     0xd6, 9,
824     0xd7, 9,
825     0xd8, 9,
826     0xd9, 9,
827     0xda, 9,
828     0xdb, 9,
829     0x98, 9,
830     0x99, 9,
831     0x9a, 9,
832     0x18, 6,
833     0x9b, 9,
834     0x08, 11,
835     0x0c, 11,
836     0x0d, 11,
837     0x12, 12,
838     0x13, 12,
839     0x14, 12,
840     0x15, 12,
841     0x16, 12,
842     0x17, 12,
843     0x1c, 12,
844     0x1d, 12,
845     0x1e, 12,
846     0x1f, 12,
847 };
848 static void _AddBitStream(FX_LPBYTE dest_buf, int& dest_bitpos, int data, int bitlen)
849 {
850     for (int i = bitlen - 1; i >= 0; i --) {
851         if (data & (1 << i)) {
852             dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
853         }
854         dest_bitpos ++;
855     }
856 }
857 static void _FaxEncodeRun(FX_LPBYTE dest_buf, int& dest_bitpos, int run, FX_BOOL bWhite)
858 {
859     while (run >= 2560) {
860         _AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
861         run -= 2560;
862     }
863     if (run >= 64) {
864         int markup = run - run % 64;
865         FX_LPCBYTE p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
866         p += (markup / 64 - 1) * 2;
867         _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
868     }
869     run %= 64;
870     FX_LPCBYTE p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
871     p += run * 2;
872     _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
873 }
874 static void _FaxEncode2DLine(FX_LPBYTE dest_buf, int& dest_bitpos, FX_LPCBYTE src_buf, FX_LPCBYTE ref_buf, int cols)
875 {
876     int a0 = -1, a0color = 1;
877     while (1) {
878         int a1 = _FindBit(src_buf, cols, a0 + 1, 1 - a0color);
879         int b1, b2;
880         _FaxG4FindB1B2(ref_buf, cols, a0, a0color, b1, b2);
881         if (b2 < a1) {
882             dest_bitpos += 3;
883             dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
884             dest_bitpos ++;
885             a0 = b2;
886         } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
887             int delta = a1 - b1;
888             switch (delta) {
889                 case 0:
890                     dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
891                     break;
892                 case 1:
893                 case 2:
894                 case 3:
895                     dest_bitpos += delta == 1 ? 1 : delta + 2;
896                     dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
897                     dest_bitpos ++;
898                     dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
899                     break;
900                 case -1:
901                 case -2:
902                 case -3:
903                     dest_bitpos += delta == -1 ? 1 : -delta + 2;
904                     dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
905                     dest_bitpos ++;
906                     break;
907             }
908             dest_bitpos ++;
909             a0 = a1;
910             a0color = 1 - a0color;
911         } else {
912             int a2 = _FindBit(src_buf, cols, a1 + 1, a0color);
913             dest_bitpos ++;
914             dest_bitpos ++;
915             dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
916             dest_bitpos ++;
917             if (a0 < 0) {
918                 a0 = 0;
919             }
920             _FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
921             _FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, 1 - a0color);
922             a0 = a2;
923         }
924         if (a0 >= cols) {
925             return;
926         }
927     }
928 }
929 class CCodec_FaxEncoder : public CFX_Object
930 {
931 public:
932     CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch);
933     ~CCodec_FaxEncoder();
934     void                        Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
935     void                        Encode2DLine(FX_LPCBYTE scan_line);
936     CFX_BinaryBuf       m_DestBuf;
937     FX_LPBYTE           m_pRefLine, m_pLineBuf;
938     int                         m_Cols, m_Rows, m_Pitch;
939     FX_LPCBYTE          m_pSrcBuf;
940 };
941 CCodec_FaxEncoder::CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch)
942 {
943     m_pSrcBuf = src_buf;
944     m_Cols = width;
945     m_Rows = height;
946     m_Pitch = pitch;
947     m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch);
948     if (m_pRefLine == NULL) {
949         return;
950     }
951     FXSYS_memset8(m_pRefLine, 0xff, m_Pitch);
952     m_pLineBuf = FX_Alloc(FX_BYTE, m_Pitch * 8);
953     if (m_pLineBuf == NULL) {
954         return;
955     }
956     m_DestBuf.EstimateSize(0, 10240);
957 }
958 CCodec_FaxEncoder::~CCodec_FaxEncoder()
959 {
960     if (m_pRefLine) {
961         FX_Free(m_pRefLine);
962     }
963     if (m_pLineBuf) {
964         FX_Free(m_pLineBuf);
965     }
966 }
967 void CCodec_FaxEncoder::Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
968 {
969     int dest_bitpos = 0;
970     FX_BYTE last_byte = 0;
971     for (int i = 0; i < m_Rows; i ++) {
972         FX_LPCBYTE scan_line = m_pSrcBuf + i * m_Pitch;
973         FXSYS_memset32(m_pLineBuf, 0, m_Pitch * 8);
974         m_pLineBuf[0] = last_byte;
975         _FaxEncode2DLine(m_pLineBuf, dest_bitpos, scan_line, m_pRefLine, m_Cols);
976         m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
977         last_byte = m_pLineBuf[dest_bitpos / 8];
978         dest_bitpos %= 8;
979         FXSYS_memcpy32(m_pRefLine, scan_line, m_Pitch);
980     }
981     if (dest_bitpos) {
982         m_DestBuf.AppendByte(last_byte);
983     }
984     dest_buf = m_DestBuf.GetBuffer();
985     dest_size = m_DestBuf.GetSize();
986     m_DestBuf.DetachBuffer();
987 }
988 FX_BOOL CCodec_FaxModule::Encode(FX_LPCBYTE src_buf, int width, int height, int pitch, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
989 {
990     CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
991     encoder.Encode(dest_buf, dest_size);
992     return TRUE;
993 }
994 ICodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
995         int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows)
996 {
997     CCodec_FaxDecoder* pDecoder = FX_NEW CCodec_FaxDecoder;
998     if (pDecoder == NULL) {
999         return NULL;
1000     }
1001     pDecoder->Create(src_buf, src_size, width, height, K, EndOfLine, EncodedByteAlign, BlackIs1, Columns, Rows);
1002     return pDecoder;
1003 }