• Home
  • 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 <algorithm>
8 #include <memory>
9 #include <vector>
10 
11 #include "core/fxcodec/codec/codec_int.h"
12 #include "core/fxcodec/fx_codec.h"
13 #include "core/fxcrt/fx_memory.h"
14 #include "third_party/base/ptr_util.h"
15 
16 namespace {
17 
18 const uint8_t OneLeadPos[256] = {
19     8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
20     3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
21     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
22     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
23     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
24     1, 1, 1, 1, 1, 1, 1, 1, 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, 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 };
31 const uint8_t ZeroLeadPos[256] = {
32     0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0,
36     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37     0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 2, 2, 2, 2, 2, 2, 2, 2,
41     2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
42     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
43 };
44 
45 // Limit of image dimension, an arbitrary large number.
46 const int kMaxImageDimension = 0x01FFFF;
47 
FindBit(const uint8_t * data_buf,int max_pos,int start_pos,int bit)48 int FindBit(const uint8_t* data_buf, int max_pos, int start_pos, int bit) {
49   ASSERT(start_pos >= 0);
50   if (start_pos >= max_pos)
51     return max_pos;
52 
53   const uint8_t* leading_pos = bit ? OneLeadPos : ZeroLeadPos;
54   if (start_pos % 8) {
55     uint8_t data = data_buf[start_pos / 8];
56     if (bit)
57       data &= 0xff >> (start_pos % 8);
58     else
59       data |= 0xff << (8 - start_pos % 8);
60 
61     if (leading_pos[data] < 8)
62       return start_pos / 8 * 8 + leading_pos[data];
63 
64     start_pos += 7;
65   }
66   uint8_t skip = bit ? 0x00 : 0xff;
67   int byte_pos = start_pos / 8;
68   int max_byte = (max_pos + 7) / 8;
69   while (byte_pos < max_byte) {
70     if (data_buf[byte_pos] != skip)
71       break;
72 
73     ++byte_pos;
74   }
75   if (byte_pos == max_byte)
76     return max_pos;
77 
78   return std::min(leading_pos[data_buf[byte_pos]] + byte_pos * 8, max_pos);
79 }
80 
FaxG4FindB1B2(const std::vector<uint8_t> & ref_buf,int columns,int a0,bool a0color,int * b1,int * b2)81 void FaxG4FindB1B2(const std::vector<uint8_t>& ref_buf,
82                    int columns,
83                    int a0,
84                    bool a0color,
85                    int* b1,
86                    int* b2) {
87   uint8_t first_bit =
88       (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
89   *b1 = FindBit(ref_buf.data(), columns, a0 + 1, !first_bit);
90   if (*b1 >= columns) {
91     *b1 = *b2 = columns;
92     return;
93   }
94   if (first_bit == !a0color) {
95     *b1 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
96     first_bit = !first_bit;
97   }
98   if (*b1 >= columns) {
99     *b1 = *b2 = columns;
100     return;
101   }
102   *b2 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
103 }
104 
FaxFillBits(uint8_t * dest_buf,int columns,int startpos,int endpos)105 void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
106   startpos = std::max(startpos, 0);
107   endpos = std::min(std::max(endpos, 0), columns);
108   if (startpos >= endpos)
109     return;
110 
111   int first_byte = startpos / 8;
112   int last_byte = (endpos - 1) / 8;
113   if (first_byte == last_byte) {
114     for (int i = startpos % 8; i <= (endpos - 1) % 8; ++i)
115       dest_buf[first_byte] -= 1 << (7 - i);
116     return;
117   }
118 
119   for (int i = startpos % 8; i < 8; ++i)
120     dest_buf[first_byte] -= 1 << (7 - i);
121   for (int i = 0; i <= (endpos - 1) % 8; ++i)
122     dest_buf[last_byte] -= 1 << (7 - i);
123 
124   if (last_byte > first_byte + 1)
125     FXSYS_memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
126 }
127 
NextBit(const uint8_t * src_buf,int * bitpos)128 inline bool NextBit(const uint8_t* src_buf, int* bitpos) {
129   int pos = (*bitpos)++;
130   return !!(src_buf[pos / 8] & (1 << (7 - pos % 8)));
131 }
132 
133 const uint8_t FaxBlackRunIns[] = {
134     0,          2,          0x02,       3,          0,          0x03,
135     2,          0,          2,          0x02,       1,          0,
136     0x03,       4,          0,          2,          0x02,       6,
137     0,          0x03,       5,          0,          1,          0x03,
138     7,          0,          2,          0x04,       9,          0,
139     0x05,       8,          0,          3,          0x04,       10,
140     0,          0x05,       11,         0,          0x07,       12,
141     0,          2,          0x04,       13,         0,          0x07,
142     14,         0,          1,          0x18,       15,         0,
143     5,          0x08,       18,         0,          0x0f,       64,
144     0,          0x17,       16,         0,          0x18,       17,
145     0,          0x37,       0,          0,          10,         0x08,
146     0x00,       0x07,       0x0c,       0x40,       0x07,       0x0d,
147     0x80,       0x07,       0x17,       24,         0,          0x18,
148     25,         0,          0x28,       23,         0,          0x37,
149     22,         0,          0x67,       19,         0,          0x68,
150     20,         0,          0x6c,       21,         0,          54,
151     0x12,       1984 % 256, 1984 / 256, 0x13,       2048 % 256, 2048 / 256,
152     0x14,       2112 % 256, 2112 / 256, 0x15,       2176 % 256, 2176 / 256,
153     0x16,       2240 % 256, 2240 / 256, 0x17,       2304 % 256, 2304 / 256,
154     0x1c,       2368 % 256, 2368 / 256, 0x1d,       2432 % 256, 2432 / 256,
155     0x1e,       2496 % 256, 2496 / 256, 0x1f,       2560 % 256, 2560 / 256,
156     0x24,       52,         0,          0x27,       55,         0,
157     0x28,       56,         0,          0x2b,       59,         0,
158     0x2c,       60,         0,          0x33,       320 % 256,  320 / 256,
159     0x34,       384 % 256,  384 / 256,  0x35,       448 % 256,  448 / 256,
160     0x37,       53,         0,          0x38,       54,         0,
161     0x52,       50,         0,          0x53,       51,         0,
162     0x54,       44,         0,          0x55,       45,         0,
163     0x56,       46,         0,          0x57,       47,         0,
164     0x58,       57,         0,          0x59,       58,         0,
165     0x5a,       61,         0,          0x5b,       256 % 256,  256 / 256,
166     0x64,       48,         0,          0x65,       49,         0,
167     0x66,       62,         0,          0x67,       63,         0,
168     0x68,       30,         0,          0x69,       31,         0,
169     0x6a,       32,         0,          0x6b,       33,         0,
170     0x6c,       40,         0,          0x6d,       41,         0,
171     0xc8,       128,        0,          0xc9,       192,        0,
172     0xca,       26,         0,          0xcb,       27,         0,
173     0xcc,       28,         0,          0xcd,       29,         0,
174     0xd2,       34,         0,          0xd3,       35,         0,
175     0xd4,       36,         0,          0xd5,       37,         0,
176     0xd6,       38,         0,          0xd7,       39,         0,
177     0xda,       42,         0,          0xdb,       43,         0,
178     20,         0x4a,       640 % 256,  640 / 256,  0x4b,       704 % 256,
179     704 / 256,  0x4c,       768 % 256,  768 / 256,  0x4d,       832 % 256,
180     832 / 256,  0x52,       1280 % 256, 1280 / 256, 0x53,       1344 % 256,
181     1344 / 256, 0x54,       1408 % 256, 1408 / 256, 0x55,       1472 % 256,
182     1472 / 256, 0x5a,       1536 % 256, 1536 / 256, 0x5b,       1600 % 256,
183     1600 / 256, 0x64,       1664 % 256, 1664 / 256, 0x65,       1728 % 256,
184     1728 / 256, 0x6c,       512 % 256,  512 / 256,  0x6d,       576 % 256,
185     576 / 256,  0x72,       896 % 256,  896 / 256,  0x73,       960 % 256,
186     960 / 256,  0x74,       1024 % 256, 1024 / 256, 0x75,       1088 % 256,
187     1088 / 256, 0x76,       1152 % 256, 1152 / 256, 0x77,       1216 % 256,
188     1216 / 256, 0xff};
189 
190 const uint8_t FaxWhiteRunIns[] = {
191     0,          0,          0,          6,          0x07,       2,
192     0,          0x08,       3,          0,          0x0B,       4,
193     0,          0x0C,       5,          0,          0x0E,       6,
194     0,          0x0F,       7,          0,          6,          0x07,
195     10,         0,          0x08,       11,         0,          0x12,
196     128,        0,          0x13,       8,          0,          0x14,
197     9,          0,          0x1b,       64,         0,          9,
198     0x03,       13,         0,          0x07,       1,          0,
199     0x08,       12,         0,          0x17,       192,        0,
200     0x18,       1664 % 256, 1664 / 256, 0x2a,       16,         0,
201     0x2B,       17,         0,          0x34,       14,         0,
202     0x35,       15,         0,          12,         0x03,       22,
203     0,          0x04,       23,         0,          0x08,       20,
204     0,          0x0c,       19,         0,          0x13,       26,
205     0,          0x17,       21,         0,          0x18,       28,
206     0,          0x24,       27,         0,          0x27,       18,
207     0,          0x28,       24,         0,          0x2B,       25,
208     0,          0x37,       256 % 256,  256 / 256,  42,         0x02,
209     29,         0,          0x03,       30,         0,          0x04,
210     45,         0,          0x05,       46,         0,          0x0a,
211     47,         0,          0x0b,       48,         0,          0x12,
212     33,         0,          0x13,       34,         0,          0x14,
213     35,         0,          0x15,       36,         0,          0x16,
214     37,         0,          0x17,       38,         0,          0x1a,
215     31,         0,          0x1b,       32,         0,          0x24,
216     53,         0,          0x25,       54,         0,          0x28,
217     39,         0,          0x29,       40,         0,          0x2a,
218     41,         0,          0x2b,       42,         0,          0x2c,
219     43,         0,          0x2d,       44,         0,          0x32,
220     61,         0,          0x33,       62,         0,          0x34,
221     63,         0,          0x35,       0,          0,          0x36,
222     320 % 256,  320 / 256,  0x37,       384 % 256,  384 / 256,  0x4a,
223     59,         0,          0x4b,       60,         0,          0x52,
224     49,         0,          0x53,       50,         0,          0x54,
225     51,         0,          0x55,       52,         0,          0x58,
226     55,         0,          0x59,       56,         0,          0x5a,
227     57,         0,          0x5b,       58,         0,          0x64,
228     448 % 256,  448 / 256,  0x65,       512 % 256,  512 / 256,  0x67,
229     640 % 256,  640 / 256,  0x68,       576 % 256,  576 / 256,  16,
230     0x98,       1472 % 256, 1472 / 256, 0x99,       1536 % 256, 1536 / 256,
231     0x9a,       1600 % 256, 1600 / 256, 0x9b,       1728 % 256, 1728 / 256,
232     0xcc,       704 % 256,  704 / 256,  0xcd,       768 % 256,  768 / 256,
233     0xd2,       832 % 256,  832 / 256,  0xd3,       896 % 256,  896 / 256,
234     0xd4,       960 % 256,  960 / 256,  0xd5,       1024 % 256, 1024 / 256,
235     0xd6,       1088 % 256, 1088 / 256, 0xd7,       1152 % 256, 1152 / 256,
236     0xd8,       1216 % 256, 1216 / 256, 0xd9,       1280 % 256, 1280 / 256,
237     0xda,       1344 % 256, 1344 / 256, 0xdb,       1408 % 256, 1408 / 256,
238     0,          3,          0x08,       1792 % 256, 1792 / 256, 0x0c,
239     1856 % 256, 1856 / 256, 0x0d,       1920 % 256, 1920 / 256, 10,
240     0x12,       1984 % 256, 1984 / 256, 0x13,       2048 % 256, 2048 / 256,
241     0x14,       2112 % 256, 2112 / 256, 0x15,       2176 % 256, 2176 / 256,
242     0x16,       2240 % 256, 2240 / 256, 0x17,       2304 % 256, 2304 / 256,
243     0x1c,       2368 % 256, 2368 / 256, 0x1d,       2432 % 256, 2432 / 256,
244     0x1e,       2496 % 256, 2496 / 256, 0x1f,       2560 % 256, 2560 / 256,
245     0xff,
246 };
247 
FaxGetRun(const uint8_t * ins_array,const uint8_t * src_buf,int * bitpos,int bitsize)248 int FaxGetRun(const uint8_t* ins_array,
249               const uint8_t* src_buf,
250               int* bitpos,
251               int bitsize) {
252   uint32_t code = 0;
253   int ins_off = 0;
254   while (1) {
255     uint8_t ins = ins_array[ins_off++];
256     if (ins == 0xff)
257       return -1;
258 
259     if (*bitpos >= bitsize)
260       return -1;
261 
262     code <<= 1;
263     if (src_buf[*bitpos / 8] & (1 << (7 - *bitpos % 8)))
264       ++code;
265 
266     ++(*bitpos);
267     int next_off = ins_off + ins * 3;
268     for (; ins_off < next_off; ins_off += 3) {
269       if (ins_array[ins_off] == code) {
270         return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256;
271       }
272     }
273   }
274 }
275 
FaxG4GetRow(const uint8_t * src_buf,int bitsize,int * bitpos,uint8_t * dest_buf,const std::vector<uint8_t> & ref_buf,int columns)276 bool FaxG4GetRow(const uint8_t* src_buf,
277                  int bitsize,
278                  int* bitpos,
279                  uint8_t* dest_buf,
280                  const std::vector<uint8_t>& ref_buf,
281                  int columns) {
282   int a0 = -1;
283   bool a0color = true;
284   while (1) {
285     if (*bitpos >= bitsize)
286       return false;
287 
288     int a1;
289     int a2;
290     int b1;
291     int b2;
292     FaxG4FindB1B2(ref_buf, columns, a0, a0color, &b1, &b2);
293 
294     int v_delta = 0;
295     if (!NextBit(src_buf, bitpos)) {
296       if (*bitpos >= bitsize)
297         return false;
298 
299       bool bit1 = NextBit(src_buf, bitpos);
300       if (*bitpos >= bitsize)
301         return false;
302 
303       bool bit2 = NextBit(src_buf, bitpos);
304       if (bit1) {
305         v_delta = bit2 ? 1 : -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         if (NextBit(src_buf, bitpos)) {
346           if (!a0color)
347             FaxFillBits(dest_buf, columns, a0, b2);
348 
349           if (b2 >= columns)
350             return true;
351 
352           a0 = b2;
353           continue;
354         }
355 
356         if (*bitpos >= bitsize)
357           return false;
358 
359         bool next_bit1 = NextBit(src_buf, bitpos);
360         if (*bitpos >= bitsize)
361           return false;
362 
363         bool next_bit2 = NextBit(src_buf, bitpos);
364         if (next_bit1) {
365           v_delta = next_bit2 ? 2 : -2;
366         } else if (next_bit2) {
367           if (*bitpos >= bitsize)
368             return false;
369 
370           v_delta = NextBit(src_buf, bitpos) ? 3 : -3;
371         } else {
372           if (*bitpos >= bitsize)
373             return false;
374 
375           if (NextBit(src_buf, bitpos)) {
376             *bitpos += 3;
377             continue;
378           }
379           *bitpos += 5;
380           return true;
381         }
382       }
383     }
384     a1 = b1 + v_delta;
385     if (!a0color)
386       FaxFillBits(dest_buf, columns, a0, a1);
387 
388     if (a1 >= columns)
389       return true;
390 
391     // The position of picture element must be monotonic increasing.
392     if (a0 >= a1)
393       return false;
394 
395     a0 = a1;
396     a0color = !a0color;
397   }
398 }
399 
FaxSkipEOL(const uint8_t * src_buf,int bitsize,int * bitpos)400 bool FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) {
401   int startbit = *bitpos;
402   while (*bitpos < bitsize) {
403     if (!NextBit(src_buf, bitpos))
404       continue;
405     if (*bitpos - startbit <= 11)
406       *bitpos = startbit;
407     return true;
408   }
409   return false;
410 }
411 
FaxGet1DLine(const uint8_t * src_buf,int bitsize,int * bitpos,std::vector<uint8_t> * dest_buf,int columns)412 bool FaxGet1DLine(const uint8_t* src_buf,
413                   int bitsize,
414                   int* bitpos,
415                   std::vector<uint8_t>* dest_buf,
416                   int columns) {
417   bool color = true;
418   int startpos = 0;
419   while (1) {
420     if (*bitpos >= bitsize)
421       return false;
422 
423     int run_len = 0;
424     while (1) {
425       int run = FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf,
426                           bitpos, bitsize);
427       if (run < 0) {
428         while (*bitpos < bitsize) {
429           if (NextBit(src_buf, bitpos))
430             return true;
431         }
432         return false;
433       }
434       run_len += run;
435       if (run < 64) {
436         break;
437       }
438     }
439     if (!color)
440       FaxFillBits(dest_buf->data(), columns, startpos, startpos + run_len);
441 
442     startpos += run_len;
443     if (startpos >= columns)
444       break;
445 
446     color = !color;
447   }
448   return true;
449 }
450 
451 }  // namespace
452 
453 class CCodec_FaxDecoder : public CCodec_ScanlineDecoder {
454  public:
455   CCodec_FaxDecoder(const uint8_t* src_buf,
456                     uint32_t src_size,
457                     int width,
458                     int height,
459                     uint32_t pitch,
460                     int K,
461                     bool EndOfLine,
462                     bool EncodedByteAlign,
463                     bool BlackIs1);
464   ~CCodec_FaxDecoder() override;
465 
466   // CCodec_ScanlineDecoder
467   bool v_Rewind() override;
468   uint8_t* v_GetNextLine() override;
469   uint32_t GetSrcOffset() override;
470 
471  private:
472   const int m_Encoding;
473   int m_bitpos;
474   bool m_bByteAlign;
475   const bool m_bEndOfLine;
476   const bool m_bBlack;
477   const uint32_t m_SrcSize;
478   const uint8_t* const m_pSrcBuf;
479   std::vector<uint8_t> m_ScanlineBuf;
480   std::vector<uint8_t> m_RefBuf;
481 };
482 
CCodec_FaxDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,uint32_t pitch,int K,bool EndOfLine,bool EncodedByteAlign,bool BlackIs1)483 CCodec_FaxDecoder::CCodec_FaxDecoder(const uint8_t* src_buf,
484                                      uint32_t src_size,
485                                      int width,
486                                      int height,
487                                      uint32_t pitch,
488                                      int K,
489                                      bool EndOfLine,
490                                      bool EncodedByteAlign,
491                                      bool BlackIs1)
492     : CCodec_ScanlineDecoder(width, height, width, height, 1, 1, pitch),
493       m_Encoding(K),
494       m_bitpos(0),
495       m_bByteAlign(EncodedByteAlign),
496       m_bEndOfLine(EndOfLine),
497       m_bBlack(BlackIs1),
498       m_SrcSize(src_size),
499       m_pSrcBuf(src_buf),
500       m_ScanlineBuf(pitch),
501       m_RefBuf(pitch) {}
502 
~CCodec_FaxDecoder()503 CCodec_FaxDecoder::~CCodec_FaxDecoder() {}
504 
v_Rewind()505 bool CCodec_FaxDecoder::v_Rewind() {
506   FXSYS_memset(m_RefBuf.data(), 0xff, m_RefBuf.size());
507   m_bitpos = 0;
508   return true;
509 }
510 
v_GetNextLine()511 uint8_t* CCodec_FaxDecoder::v_GetNextLine() {
512   int bitsize = m_SrcSize * 8;
513   FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
514   if (m_bitpos >= bitsize)
515     return nullptr;
516 
517   FXSYS_memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size());
518   if (m_Encoding < 0) {
519     FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
520                 m_OrigWidth);
521     m_RefBuf = m_ScanlineBuf;
522   } else if (m_Encoding == 0) {
523     FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
524   } else {
525     if (NextBit(m_pSrcBuf, &m_bitpos)) {
526       FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
527     } else {
528       FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
529                   m_OrigWidth);
530     }
531     m_RefBuf = m_ScanlineBuf;
532   }
533   if (m_bEndOfLine)
534     FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
535 
536   if (m_bByteAlign && m_bitpos < bitsize) {
537     int bitpos0 = m_bitpos;
538     int bitpos1 = (m_bitpos + 7) / 8 * 8;
539     while (m_bByteAlign && bitpos0 < bitpos1) {
540       int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
541       if (bit != 0) {
542         m_bByteAlign = false;
543       } else {
544         ++bitpos0;
545       }
546     }
547     if (m_bByteAlign)
548       m_bitpos = bitpos1;
549   }
550   if (m_bBlack) {
551     for (uint32_t i = 0; i < m_Pitch; ++i) {
552       m_ScanlineBuf[i] = ~m_ScanlineBuf[i];
553     }
554   }
555   return m_ScanlineBuf.data();
556 }
557 
GetSrcOffset()558 uint32_t CCodec_FaxDecoder::GetSrcOffset() {
559   return std::min(static_cast<uint32_t>((m_bitpos + 7) / 8), m_SrcSize);
560 }
561 
FaxG4Decode(const uint8_t * src_buf,uint32_t src_size,int * pbitpos,uint8_t * dest_buf,int width,int height,int pitch)562 void FaxG4Decode(const uint8_t* src_buf,
563                  uint32_t src_size,
564                  int* pbitpos,
565                  uint8_t* dest_buf,
566                  int width,
567                  int height,
568                  int pitch) {
569   if (pitch == 0)
570     pitch = (width + 7) / 8;
571 
572   std::vector<uint8_t> ref_buf(pitch, 0xff);
573   int bitpos = *pbitpos;
574   for (int iRow = 0; iRow < height; iRow++) {
575     uint8_t* line_buf = dest_buf + iRow * pitch;
576     FXSYS_memset(line_buf, 0xff, pitch);
577     FaxG4GetRow(src_buf, src_size << 3, &bitpos, line_buf, ref_buf, width);
578     FXSYS_memcpy(ref_buf.data(), line_buf, pitch);
579   }
580   *pbitpos = bitpos;
581 }
582 
CreateDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,int K,bool EndOfLine,bool EncodedByteAlign,bool BlackIs1,int Columns,int Rows)583 std::unique_ptr<CCodec_ScanlineDecoder> CCodec_FaxModule::CreateDecoder(
584     const uint8_t* src_buf,
585     uint32_t src_size,
586     int width,
587     int height,
588     int K,
589     bool EndOfLine,
590     bool EncodedByteAlign,
591     bool BlackIs1,
592     int Columns,
593     int Rows) {
594   int actual_width = Columns ? Columns : width;
595   int actual_height = Rows ? Rows : height;
596 
597   // Reject invalid values.
598   if (actual_width <= 0 || actual_height <= 0)
599     return nullptr;
600 
601   // Reject unreasonable large input.
602   if (actual_width > kMaxImageDimension || actual_height > kMaxImageDimension)
603     return nullptr;
604 
605   uint32_t pitch = (static_cast<uint32_t>(actual_width) + 31) / 32 * 4;
606   return pdfium::MakeUnique<CCodec_FaxDecoder>(
607       src_buf, src_size, actual_width, actual_height, pitch, K, EndOfLine,
608       EncodedByteAlign, BlackIs1);
609 }
610 
611 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
612 namespace {
613 const uint8_t BlackRunTerminator[128] = {
614     0x37, 10, 0x02, 3,  0x03, 2,  0x02, 2,  0x03, 3,  0x03, 4,  0x02, 4,
615     0x03, 5,  0x05, 6,  0x04, 6,  0x04, 7,  0x05, 7,  0x07, 7,  0x04, 8,
616     0x07, 8,  0x18, 9,  0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11,
617     0x6c, 11, 0x37, 11, 0x28, 11, 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12,
618     0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 0x6a, 12, 0x6b, 12, 0xd2, 12,
619     0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 0x6c, 12, 0x6d, 12,
620     0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 0x64, 12,
621     0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
622     0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12,
623     0x67, 12,
624 };
625 
626 const uint8_t BlackRunMarkup[80] = {
627     0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12,
628     0x6c, 13, 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13,
629     0x73, 13, 0x74, 13, 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13,
630     0x54, 13, 0x55, 13, 0x5a, 13, 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11,
631     0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
632     0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
633 };
634 
635 const uint8_t WhiteRunTerminator[128] = {
636     0x35, 8, 0x07, 6, 0x07, 4, 0x08, 4, 0x0B, 4, 0x0C, 4, 0x0E, 4, 0x0F, 4,
637     0x13, 5, 0x14, 5, 0x07, 5, 0x08, 5, 0x08, 6, 0x03, 6, 0x34, 6, 0x35, 6,
638     0x2a, 6, 0x2B, 6, 0x27, 7, 0x0c, 7, 0x08, 7, 0x17, 7, 0x03, 7, 0x04, 7,
639     0x28, 7, 0x2B, 7, 0x13, 7, 0x24, 7, 0x18, 7, 0x02, 8, 0x03, 8, 0x1a, 8,
640     0x1b, 8, 0x12, 8, 0x13, 8, 0x14, 8, 0x15, 8, 0x16, 8, 0x17, 8, 0x28, 8,
641     0x29, 8, 0x2a, 8, 0x2b, 8, 0x2c, 8, 0x2d, 8, 0x04, 8, 0x05, 8, 0x0a, 8,
642     0x0b, 8, 0x52, 8, 0x53, 8, 0x54, 8, 0x55, 8, 0x24, 8, 0x25, 8, 0x58, 8,
643     0x59, 8, 0x5a, 8, 0x5b, 8, 0x4a, 8, 0x4b, 8, 0x32, 8, 0x33, 8, 0x34, 8,
644 };
645 
646 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 
AddBitStream(uint8_t * dest_buf,int * dest_bitpos,int data,int bitlen)655 void AddBitStream(uint8_t* dest_buf, int* dest_bitpos, int data, int bitlen) {
656   for (int i = bitlen - 1; i >= 0; i--) {
657     if (data & (1 << i)) {
658       dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
659     }
660     (*dest_bitpos)++;
661   }
662 }
663 
FaxEncodeRun(uint8_t * dest_buf,int * dest_bitpos,int run,bool bWhite)664 void FaxEncodeRun(uint8_t* dest_buf, int* dest_bitpos, int run, bool bWhite) {
665   while (run >= 2560) {
666     AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
667     run -= 2560;
668   }
669   if (run >= 64) {
670     int markup = run - run % 64;
671     const uint8_t* p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
672     p += (markup / 64 - 1) * 2;
673     AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
674   }
675   run %= 64;
676   const uint8_t* p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
677   p += run * 2;
678   AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
679 }
680 
FaxEncode2DLine(uint8_t * dest_buf,int * dest_bitpos,const uint8_t * src_buf,const std::vector<uint8_t> & ref_buf,int cols)681 void FaxEncode2DLine(uint8_t* dest_buf,
682                      int* dest_bitpos,
683                      const uint8_t* src_buf,
684                      const std::vector<uint8_t>& ref_buf,
685                      int cols) {
686   int a0 = -1;
687   bool a0color = true;
688   while (1) {
689     int a1 = FindBit(src_buf, cols, a0 + 1, !a0color);
690     int b1;
691     int b2;
692     FaxG4FindB1B2(ref_buf, cols, a0, a0color, &b1, &b2);
693     if (b2 < a1) {
694       *dest_bitpos += 3;
695       dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
696       (*dest_bitpos)++;
697       a0 = b2;
698     } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
699       int delta = a1 - b1;
700       switch (delta) {
701         case 0:
702           dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
703           break;
704         case 1:
705         case 2:
706         case 3:
707           *dest_bitpos += delta == 1 ? 1 : delta + 2;
708           dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
709           (*dest_bitpos)++;
710           dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
711           break;
712         case -1:
713         case -2:
714         case -3:
715           *dest_bitpos += delta == -1 ? 1 : -delta + 2;
716           dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
717           (*dest_bitpos)++;
718           break;
719       }
720       (*dest_bitpos)++;
721       a0 = a1;
722       a0color = !a0color;
723     } else {
724       int a2 = FindBit(src_buf, cols, a1 + 1, a0color);
725       (*dest_bitpos)++;
726       (*dest_bitpos)++;
727       dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
728       (*dest_bitpos)++;
729       if (a0 < 0) {
730         a0 = 0;
731       }
732       FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
733       FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, !a0color);
734       a0 = a2;
735     }
736     if (a0 >= cols) {
737       return;
738     }
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(std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
747               uint32_t* dest_size);
748 
749  private:
750   CFX_BinaryBuf m_DestBuf;
751   std::vector<uint8_t> m_RefLine;
752   uint8_t* m_pLineBuf;
753   const int m_Cols;
754   const int m_Rows;
755   const int m_Pitch;
756   const uint8_t* m_pSrcBuf;
757 };
758 
CCodec_FaxEncoder(const uint8_t * src_buf,int width,int height,int pitch)759 CCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf,
760                                      int width,
761                                      int height,
762                                      int pitch)
763     : m_Cols(width), m_Rows(height), m_Pitch(pitch), m_pSrcBuf(src_buf) {
764   m_RefLine.resize(m_Pitch);
765   FXSYS_memset(m_RefLine.data(), 0xff, m_Pitch);
766   m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
767   m_DestBuf.EstimateSize(0, 10240);
768 }
769 
~CCodec_FaxEncoder()770 CCodec_FaxEncoder::~CCodec_FaxEncoder() {
771   FX_Free(m_pLineBuf);
772 }
773 
Encode(std::unique_ptr<uint8_t,FxFreeDeleter> * dest_buf,uint32_t * dest_size)774 void CCodec_FaxEncoder::Encode(
775     std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
776     uint32_t* dest_size) {
777   int dest_bitpos = 0;
778   uint8_t last_byte = 0;
779   for (int i = 0; i < m_Rows; i++) {
780     const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch;
781     FXSYS_memset(m_pLineBuf, 0, m_Pitch * 8);
782     m_pLineBuf[0] = last_byte;
783     FaxEncode2DLine(m_pLineBuf, &dest_bitpos, scan_line, m_RefLine, m_Cols);
784     m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
785     last_byte = m_pLineBuf[dest_bitpos / 8];
786     dest_bitpos %= 8;
787     FXSYS_memcpy(m_RefLine.data(), scan_line, m_Pitch);
788   }
789   if (dest_bitpos) {
790     m_DestBuf.AppendByte(last_byte);
791   }
792   *dest_size = m_DestBuf.GetSize();
793   *dest_buf = m_DestBuf.DetachBuffer();
794 }
795 
796 }  // namespace
797 
FaxEncode(const uint8_t * src_buf,int width,int height,int pitch,std::unique_ptr<uint8_t,FxFreeDeleter> * dest_buf,uint32_t * dest_size)798 void CCodec_FaxModule::FaxEncode(
799     const uint8_t* src_buf,
800     int width,
801     int height,
802     int pitch,
803     std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
804     uint32_t* dest_size) {
805   CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
806   encoder.Encode(dest_buf, dest_size);
807 }
808 
809 #endif
810