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