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