Don't bother checking pointers before delete[] and FX_Free().
[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(void*,
594                   const uint8_t* src_buf,
595                   FX_DWORD src_size,
596                   int* pbitpos,
597                   uint8_t* dest_buf,
598                   int width,
599                   int height,
600                   int pitch) {
601   if (pitch == 0) {
602     pitch = (width + 7) / 8;
603   }
604   uint8_t* ref_buf = FX_Alloc(uint8_t, pitch);
605   FXSYS_memset(ref_buf, 0xff, pitch);
606   int bitpos = *pbitpos;
607   for (int iRow = 0; iRow < height; iRow++) {
608     uint8_t* line_buf = dest_buf + iRow * pitch;
609     FXSYS_memset(line_buf, 0xff, pitch);
610     _FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width);
611     FXSYS_memcpy(ref_buf, line_buf, pitch);
612   }
613   FX_Free(ref_buf);
614   *pbitpos = bitpos;
615 }
616 };
617 static const uint8_t BlackRunTerminator[128] = {
618     0x37, 10, 0x02, 3,  0x03, 2,  0x02, 2,  0x03, 3,  0x03, 4,  0x02, 4,
619     0x03, 5,  0x05, 6,  0x04, 6,  0x04, 7,  0x05, 7,  0x07, 7,  0x04, 8,
620     0x07, 8,  0x18, 9,  0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11,
621     0x6c, 11, 0x37, 11, 0x28, 11, 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12,
622     0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 0x6a, 12, 0x6b, 12, 0xd2, 12,
623     0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 0x6c, 12, 0x6d, 12,
624     0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 0x64, 12,
625     0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
626     0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12,
627     0x67, 12,
628 };
629 static const uint8_t BlackRunMarkup[80] = {
630     0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12,
631     0x6c, 13, 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13,
632     0x73, 13, 0x74, 13, 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13,
633     0x54, 13, 0x55, 13, 0x5a, 13, 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11,
634     0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
635     0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
636 };
637 static const uint8_t WhiteRunTerminator[128] = {
638     0x35, 8, 0x07, 6, 0x07, 4, 0x08, 4, 0x0B, 4, 0x0C, 4, 0x0E, 4, 0x0F, 4,
639     0x13, 5, 0x14, 5, 0x07, 5, 0x08, 5, 0x08, 6, 0x03, 6, 0x34, 6, 0x35, 6,
640     0x2a, 6, 0x2B, 6, 0x27, 7, 0x0c, 7, 0x08, 7, 0x17, 7, 0x03, 7, 0x04, 7,
641     0x28, 7, 0x2B, 7, 0x13, 7, 0x24, 7, 0x18, 7, 0x02, 8, 0x03, 8, 0x1a, 8,
642     0x1b, 8, 0x12, 8, 0x13, 8, 0x14, 8, 0x15, 8, 0x16, 8, 0x17, 8, 0x28, 8,
643     0x29, 8, 0x2a, 8, 0x2b, 8, 0x2c, 8, 0x2d, 8, 0x04, 8, 0x05, 8, 0x0a, 8,
644     0x0b, 8, 0x52, 8, 0x53, 8, 0x54, 8, 0x55, 8, 0x24, 8, 0x25, 8, 0x58, 8,
645     0x59, 8, 0x5a, 8, 0x5b, 8, 0x4a, 8, 0x4b, 8, 0x32, 8, 0x33, 8, 0x34, 8,
646 };
647 static const uint8_t WhiteRunMarkup[80] = {
648     0x1b, 5,  0x12, 5,  0x17, 6,  0x37, 7,  0x36, 8,  0x37, 8,  0x64, 8,
649     0x65, 8,  0x68, 8,  0x67, 8,  0xcc, 9,  0xcd, 9,  0xd2, 9,  0xd3, 9,
650     0xd4, 9,  0xd5, 9,  0xd6, 9,  0xd7, 9,  0xd8, 9,  0xd9, 9,  0xda, 9,
651     0xdb, 9,  0x98, 9,  0x99, 9,  0x9a, 9,  0x18, 6,  0x9b, 9,  0x08, 11,
652     0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
653     0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
654 };
655 static void _AddBitStream(uint8_t* dest_buf,
656                           int& dest_bitpos,
657                           int data,
658                           int bitlen) {
659   for (int i = bitlen - 1; i >= 0; i--) {
660     if (data & (1 << i)) {
661       dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
662     }
663     dest_bitpos++;
664   }
665 }
666 static void _FaxEncodeRun(uint8_t* dest_buf,
667                           int& dest_bitpos,
668                           int run,
669                           FX_BOOL bWhite) {
670   while (run >= 2560) {
671     _AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
672     run -= 2560;
673   }
674   if (run >= 64) {
675     int markup = run - run % 64;
676     const uint8_t* p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
677     p += (markup / 64 - 1) * 2;
678     _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
679   }
680   run %= 64;
681   const uint8_t* p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
682   p += run * 2;
683   _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
684 }
685 static void _FaxEncode2DLine(uint8_t* dest_buf,
686                              int& dest_bitpos,
687                              const uint8_t* src_buf,
688                              const uint8_t* ref_buf,
689                              int cols) {
690   int a0 = -1, a0color = 1;
691   while (1) {
692     int a1 = _FindBit(src_buf, cols, a0 + 1, 1 - a0color);
693     int b1, b2;
694     _FaxG4FindB1B2(ref_buf, cols, a0, a0color, b1, b2);
695     if (b2 < a1) {
696       dest_bitpos += 3;
697       dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
698       dest_bitpos++;
699       a0 = b2;
700     } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
701       int delta = a1 - b1;
702       switch (delta) {
703         case 0:
704           dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
705           break;
706         case 1:
707         case 2:
708         case 3:
709           dest_bitpos += delta == 1 ? 1 : delta + 2;
710           dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
711           dest_bitpos++;
712           dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
713           break;
714         case -1:
715         case -2:
716         case -3:
717           dest_bitpos += delta == -1 ? 1 : -delta + 2;
718           dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
719           dest_bitpos++;
720           break;
721       }
722       dest_bitpos++;
723       a0 = a1;
724       a0color = 1 - a0color;
725     } else {
726       int a2 = _FindBit(src_buf, cols, a1 + 1, a0color);
727       dest_bitpos++;
728       dest_bitpos++;
729       dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
730       dest_bitpos++;
731       if (a0 < 0) {
732         a0 = 0;
733       }
734       _FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
735       _FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, 1 - a0color);
736       a0 = a2;
737     }
738     if (a0 >= cols) {
739       return;
740     }
741   }
742 }
743 class CCodec_FaxEncoder {
744  public:
745   CCodec_FaxEncoder(const uint8_t* src_buf, int width, int height, int pitch);
746   ~CCodec_FaxEncoder();
747   void Encode(uint8_t*& dest_buf, FX_DWORD& dest_size);
748   void Encode2DLine(const uint8_t* scan_line);
749   CFX_BinaryBuf m_DestBuf;
750   uint8_t* m_pRefLine;
751   uint8_t* m_pLineBuf;
752   int m_Cols, m_Rows, m_Pitch;
753   const uint8_t* m_pSrcBuf;
754 };
755 CCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf,
756                                      int width,
757                                      int height,
758                                      int pitch) {
759   m_pSrcBuf = src_buf;
760   m_Cols = width;
761   m_Rows = height;
762   m_Pitch = pitch;
763   m_pRefLine = FX_Alloc(uint8_t, m_Pitch);
764   FXSYS_memset(m_pRefLine, 0xff, m_Pitch);
765   m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
766   m_DestBuf.EstimateSize(0, 10240);
767 }
768 CCodec_FaxEncoder::~CCodec_FaxEncoder() {
769   FX_Free(m_pRefLine);
770   FX_Free(m_pLineBuf);
771 }
772 void CCodec_FaxEncoder::Encode(uint8_t*& dest_buf, FX_DWORD& dest_size) {
773   int dest_bitpos = 0;
774   uint8_t last_byte = 0;
775   for (int i = 0; i < m_Rows; i++) {
776     const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch;
777     FXSYS_memset(m_pLineBuf, 0, m_Pitch * 8);
778     m_pLineBuf[0] = last_byte;
779     _FaxEncode2DLine(m_pLineBuf, dest_bitpos, scan_line, m_pRefLine, m_Cols);
780     m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
781     last_byte = m_pLineBuf[dest_bitpos / 8];
782     dest_bitpos %= 8;
783     FXSYS_memcpy(m_pRefLine, scan_line, m_Pitch);
784   }
785   if (dest_bitpos) {
786     m_DestBuf.AppendByte(last_byte);
787   }
788   dest_buf = m_DestBuf.GetBuffer();
789   dest_size = m_DestBuf.GetSize();
790   m_DestBuf.DetachBuffer();
791 }
792 FX_BOOL CCodec_FaxModule::Encode(const uint8_t* src_buf,
793                                  int width,
794                                  int height,
795                                  int pitch,
796                                  uint8_t*& dest_buf,
797                                  FX_DWORD& dest_size) {
798   CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
799   encoder.Encode(dest_buf, dest_size);
800   return TRUE;
801 }
802 ICodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(
803     const uint8_t* src_buf,
804     FX_DWORD src_size,
805     int width,
806     int height,
807     int K,
808     FX_BOOL EndOfLine,
809     FX_BOOL EncodedByteAlign,
810     FX_BOOL BlackIs1,
811     int Columns,
812     int Rows) {
813   CCodec_FaxDecoder* pDecoder = new CCodec_FaxDecoder;
814   pDecoder->Create(src_buf, src_size, width, height, K, EndOfLine,
815                    EncodedByteAlign, BlackIs1, Columns, Rows);
816   return pDecoder;
817 }