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 "codec_int.h"
8
9 #include <memory>
10
11 #include "core/include/fxcodec/fx_codec.h"
12 #include "core/include/fxcodec/fx_codec_flate.h"
13 #include "third_party/zlib_v128/zlib.h"
14
15 extern "C" {
my_alloc_func(void * opaque,unsigned int items,unsigned int size)16 static void* my_alloc_func(void* opaque,
17 unsigned int items,
18 unsigned int size) {
19 return FX_Alloc2D(uint8_t, items, size);
20 }
my_free_func(void * opaque,void * address)21 static void my_free_func(void* opaque, void* address) {
22 FX_Free(address);
23 }
FPDFAPI_FlateGetTotalOut(void * context)24 static int FPDFAPI_FlateGetTotalOut(void* context) {
25 return ((z_stream*)context)->total_out;
26 }
FPDFAPI_FlateGetTotalIn(void * context)27 static int FPDFAPI_FlateGetTotalIn(void* context) {
28 return ((z_stream*)context)->total_in;
29 }
FPDFAPI_FlateCompress(unsigned char * dest_buf,unsigned long * dest_size,const unsigned char * src_buf,unsigned long src_size)30 static void FPDFAPI_FlateCompress(unsigned char* dest_buf,
31 unsigned long* dest_size,
32 const unsigned char* src_buf,
33 unsigned long src_size) {
34 compress(dest_buf, dest_size, src_buf, src_size);
35 }
FPDFAPI_FlateInit(void * (* alloc_func)(void *,unsigned int,unsigned int),void (* free_func)(void *,void *))36 void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),
37 void (*free_func)(void*, void*)) {
38 z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream));
39 if (!p) {
40 return NULL;
41 }
42 FXSYS_memset(p, 0, sizeof(z_stream));
43 p->zalloc = alloc_func;
44 p->zfree = free_func;
45 inflateInit(p);
46 return p;
47 }
FPDFAPI_FlateInput(void * context,const unsigned char * src_buf,unsigned int src_size)48 void FPDFAPI_FlateInput(void* context,
49 const unsigned char* src_buf,
50 unsigned int src_size) {
51 ((z_stream*)context)->next_in = (unsigned char*)src_buf;
52 ((z_stream*)context)->avail_in = src_size;
53 }
FPDFAPI_FlateOutput(void * context,unsigned char * dest_buf,unsigned int dest_size)54 int FPDFAPI_FlateOutput(void* context,
55 unsigned char* dest_buf,
56 unsigned int dest_size) {
57 ((z_stream*)context)->next_out = dest_buf;
58 ((z_stream*)context)->avail_out = dest_size;
59 unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context);
60 int ret = inflate((z_stream*)context, Z_SYNC_FLUSH);
61 unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context);
62 unsigned int written = post_pos - pre_pos;
63 if (written < dest_size) {
64 FXSYS_memset(dest_buf + written, '\0', dest_size - written);
65 }
66 return ret;
67 }
FPDFAPI_FlateGetAvailIn(void * context)68 int FPDFAPI_FlateGetAvailIn(void* context) {
69 return ((z_stream*)context)->avail_in;
70 }
FPDFAPI_FlateGetAvailOut(void * context)71 int FPDFAPI_FlateGetAvailOut(void* context) {
72 return ((z_stream*)context)->avail_out;
73 }
FPDFAPI_FlateEnd(void * context)74 void FPDFAPI_FlateEnd(void* context) {
75 inflateEnd((z_stream*)context);
76 ((z_stream*)context)->zfree(0, context);
77 }
78 } // extern "C"
79
80 namespace {
81
82 class CLZWDecoder {
83 public:
84 int Decode(uint8_t* output,
85 FX_DWORD& outlen,
86 const uint8_t* input,
87 FX_DWORD& size,
88 FX_BOOL bEarlyChange);
89
90 private:
91 void AddCode(FX_DWORD prefix_code, uint8_t append_char);
92 void DecodeString(FX_DWORD code);
93
94 FX_DWORD m_InPos;
95 FX_DWORD m_OutPos;
96 uint8_t* m_pOutput;
97 const uint8_t* m_pInput;
98 FX_BOOL m_Early;
99 FX_DWORD m_CodeArray[5021];
100 FX_DWORD m_nCodes;
101 uint8_t m_DecodeStack[4000];
102 FX_DWORD m_StackLen;
103 int m_CodeLen;
104 };
AddCode(FX_DWORD prefix_code,uint8_t append_char)105 void CLZWDecoder::AddCode(FX_DWORD prefix_code, uint8_t append_char) {
106 if (m_nCodes + m_Early == 4094) {
107 return;
108 }
109 m_CodeArray[m_nCodes++] = (prefix_code << 16) | append_char;
110 if (m_nCodes + m_Early == 512 - 258) {
111 m_CodeLen = 10;
112 } else if (m_nCodes + m_Early == 1024 - 258) {
113 m_CodeLen = 11;
114 } else if (m_nCodes + m_Early == 2048 - 258) {
115 m_CodeLen = 12;
116 }
117 }
DecodeString(FX_DWORD code)118 void CLZWDecoder::DecodeString(FX_DWORD code) {
119 while (1) {
120 int index = code - 258;
121 if (index < 0 || index >= (int)m_nCodes) {
122 break;
123 }
124 FX_DWORD data = m_CodeArray[index];
125 if (m_StackLen >= sizeof(m_DecodeStack)) {
126 return;
127 }
128 m_DecodeStack[m_StackLen++] = (uint8_t)data;
129 code = data >> 16;
130 }
131 if (m_StackLen >= sizeof(m_DecodeStack)) {
132 return;
133 }
134 m_DecodeStack[m_StackLen++] = (uint8_t)code;
135 }
Decode(uint8_t * dest_buf,FX_DWORD & dest_size,const uint8_t * src_buf,FX_DWORD & src_size,FX_BOOL bEarlyChange)136 int CLZWDecoder::Decode(uint8_t* dest_buf,
137 FX_DWORD& dest_size,
138 const uint8_t* src_buf,
139 FX_DWORD& src_size,
140 FX_BOOL bEarlyChange) {
141 m_CodeLen = 9;
142 m_InPos = 0;
143 m_OutPos = 0;
144 m_pInput = src_buf;
145 m_pOutput = dest_buf;
146 m_Early = bEarlyChange ? 1 : 0;
147 m_nCodes = 0;
148 FX_DWORD old_code = (FX_DWORD)-1;
149 uint8_t last_char;
150 while (1) {
151 if (m_InPos + m_CodeLen > src_size * 8) {
152 break;
153 }
154 int byte_pos = m_InPos / 8;
155 int bit_pos = m_InPos % 8, bit_left = m_CodeLen;
156 FX_DWORD code = 0;
157 if (bit_pos) {
158 bit_left -= 8 - bit_pos;
159 code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left;
160 }
161 if (bit_left < 8) {
162 code |= m_pInput[byte_pos] >> (8 - bit_left);
163 } else {
164 bit_left -= 8;
165 code |= m_pInput[byte_pos++] << bit_left;
166 if (bit_left) {
167 code |= m_pInput[byte_pos] >> (8 - bit_left);
168 }
169 }
170 m_InPos += m_CodeLen;
171 if (code < 256) {
172 if (m_OutPos == dest_size) {
173 return -5;
174 }
175 if (m_pOutput) {
176 m_pOutput[m_OutPos] = (uint8_t)code;
177 }
178 m_OutPos++;
179 last_char = (uint8_t)code;
180 if (old_code != (FX_DWORD)-1) {
181 AddCode(old_code, last_char);
182 }
183 old_code = code;
184 } else if (code == 256) {
185 m_CodeLen = 9;
186 m_nCodes = 0;
187 old_code = (FX_DWORD)-1;
188 } else if (code == 257) {
189 break;
190 } else {
191 if (old_code == (FX_DWORD)-1) {
192 return 2;
193 }
194 m_StackLen = 0;
195 if (code >= m_nCodes + 258) {
196 if (m_StackLen < sizeof(m_DecodeStack)) {
197 m_DecodeStack[m_StackLen++] = last_char;
198 }
199 DecodeString(old_code);
200 } else {
201 DecodeString(code);
202 }
203 if (m_OutPos + m_StackLen > dest_size) {
204 return -5;
205 }
206 if (m_pOutput) {
207 for (FX_DWORD i = 0; i < m_StackLen; i++) {
208 m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1];
209 }
210 }
211 m_OutPos += m_StackLen;
212 last_char = m_DecodeStack[m_StackLen - 1];
213 if (old_code < 256) {
214 AddCode(old_code, last_char);
215 } else if (old_code - 258 >= m_nCodes) {
216 dest_size = m_OutPos;
217 src_size = (m_InPos + 7) / 8;
218 return 0;
219 } else {
220 AddCode(old_code, last_char);
221 }
222 old_code = code;
223 }
224 }
225 dest_size = m_OutPos;
226 src_size = (m_InPos + 7) / 8;
227 return 0;
228 }
229
PaethPredictor(int a,int b,int c)230 uint8_t PaethPredictor(int a, int b, int c) {
231 int p = a + b - c;
232 int pa = FXSYS_abs(p - a);
233 int pb = FXSYS_abs(p - b);
234 int pc = FXSYS_abs(p - c);
235 if (pa <= pb && pa <= pc) {
236 return (uint8_t)a;
237 }
238 if (pb <= pc) {
239 return (uint8_t)b;
240 }
241 return (uint8_t)c;
242 }
243
PNG_PredictorEncode(uint8_t * & data_buf,FX_DWORD & data_size,int predictor,int Colors,int BitsPerComponent,int Columns)244 FX_BOOL PNG_PredictorEncode(uint8_t*& data_buf,
245 FX_DWORD& data_size,
246 int predictor,
247 int Colors,
248 int BitsPerComponent,
249 int Columns) {
250 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8;
251 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
252 if (row_size <= 0)
253 return FALSE;
254 const int row_count = (data_size + row_size - 1) / row_size;
255 const int last_row_size = data_size % row_size;
256 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size + 1, row_count);
257 int byte_cnt = 0;
258 uint8_t* pSrcData = data_buf;
259 uint8_t* pDestData = dest_buf;
260 for (int row = 0; row < row_count; row++) {
261 if (predictor == 10) {
262 pDestData[0] = 0;
263 int move_size = row_size;
264 if (move_size * (row + 1) > (int)data_size) {
265 move_size = data_size - (move_size * row);
266 }
267 FXSYS_memmove(pDestData + 1, pSrcData, move_size);
268 pDestData += (move_size + 1);
269 pSrcData += move_size;
270 byte_cnt += move_size;
271 continue;
272 }
273 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) {
274 switch (predictor) {
275 case 11: {
276 pDestData[0] = 1;
277 uint8_t left = 0;
278 if (byte >= BytesPerPixel) {
279 left = pSrcData[byte - BytesPerPixel];
280 }
281 pDestData[byte + 1] = pSrcData[byte] - left;
282 } break;
283 case 12: {
284 pDestData[0] = 2;
285 uint8_t up = 0;
286 if (row) {
287 up = pSrcData[byte - row_size];
288 }
289 pDestData[byte + 1] = pSrcData[byte] - up;
290 } break;
291 case 13: {
292 pDestData[0] = 3;
293 uint8_t left = 0;
294 if (byte >= BytesPerPixel) {
295 left = pSrcData[byte - BytesPerPixel];
296 }
297 uint8_t up = 0;
298 if (row) {
299 up = pSrcData[byte - row_size];
300 }
301 pDestData[byte + 1] = pSrcData[byte] - (left + up) / 2;
302 } break;
303 case 14: {
304 pDestData[0] = 4;
305 uint8_t left = 0;
306 if (byte >= BytesPerPixel) {
307 left = pSrcData[byte - BytesPerPixel];
308 }
309 uint8_t up = 0;
310 if (row) {
311 up = pSrcData[byte - row_size];
312 }
313 uint8_t upper_left = 0;
314 if (byte >= BytesPerPixel && row) {
315 upper_left = pSrcData[byte - row_size - BytesPerPixel];
316 }
317 pDestData[byte + 1] =
318 pSrcData[byte] - PaethPredictor(left, up, upper_left);
319 } break;
320 default: { pDestData[byte + 1] = pSrcData[byte]; } break;
321 }
322 byte_cnt++;
323 }
324 pDestData += (row_size + 1);
325 pSrcData += row_size;
326 }
327 FX_Free(data_buf);
328 data_buf = dest_buf;
329 data_size = (row_size + 1) * row_count -
330 (last_row_size > 0 ? (row_size - last_row_size) : 0);
331 return TRUE;
332 }
333
PNG_PredictLine(uint8_t * pDestData,const uint8_t * pSrcData,const uint8_t * pLastLine,int bpc,int nColors,int nPixels)334 void PNG_PredictLine(uint8_t* pDestData,
335 const uint8_t* pSrcData,
336 const uint8_t* pLastLine,
337 int bpc,
338 int nColors,
339 int nPixels) {
340 int row_size = (nPixels * bpc * nColors + 7) / 8;
341 int BytesPerPixel = (bpc * nColors + 7) / 8;
342 uint8_t tag = pSrcData[0];
343 if (tag == 0) {
344 FXSYS_memmove(pDestData, pSrcData + 1, row_size);
345 return;
346 }
347 for (int byte = 0; byte < row_size; byte++) {
348 uint8_t raw_byte = pSrcData[byte + 1];
349 switch (tag) {
350 case 1: {
351 uint8_t left = 0;
352 if (byte >= BytesPerPixel) {
353 left = pDestData[byte - BytesPerPixel];
354 }
355 pDestData[byte] = raw_byte + left;
356 break;
357 }
358 case 2: {
359 uint8_t up = 0;
360 if (pLastLine) {
361 up = pLastLine[byte];
362 }
363 pDestData[byte] = raw_byte + up;
364 break;
365 }
366 case 3: {
367 uint8_t left = 0;
368 if (byte >= BytesPerPixel) {
369 left = pDestData[byte - BytesPerPixel];
370 }
371 uint8_t up = 0;
372 if (pLastLine) {
373 up = pLastLine[byte];
374 }
375 pDestData[byte] = raw_byte + (up + left) / 2;
376 break;
377 }
378 case 4: {
379 uint8_t left = 0;
380 if (byte >= BytesPerPixel) {
381 left = pDestData[byte - BytesPerPixel];
382 }
383 uint8_t up = 0;
384 if (pLastLine) {
385 up = pLastLine[byte];
386 }
387 uint8_t upper_left = 0;
388 if (byte >= BytesPerPixel && pLastLine) {
389 upper_left = pLastLine[byte - BytesPerPixel];
390 }
391 pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left);
392 break;
393 }
394 default:
395 pDestData[byte] = raw_byte;
396 break;
397 }
398 }
399 }
400
PNG_Predictor(uint8_t * & data_buf,FX_DWORD & data_size,int Colors,int BitsPerComponent,int Columns)401 FX_BOOL PNG_Predictor(uint8_t*& data_buf,
402 FX_DWORD& data_size,
403 int Colors,
404 int BitsPerComponent,
405 int Columns) {
406 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8;
407 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
408 if (row_size <= 0)
409 return FALSE;
410 const int row_count = (data_size + row_size) / (row_size + 1);
411 if (row_count <= 0)
412 return FALSE;
413 const int last_row_size = data_size % (row_size + 1);
414 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size, row_count);
415 int byte_cnt = 0;
416 uint8_t* pSrcData = data_buf;
417 uint8_t* pDestData = dest_buf;
418 for (int row = 0; row < row_count; row++) {
419 uint8_t tag = pSrcData[0];
420 byte_cnt++;
421 if (tag == 0) {
422 int move_size = row_size;
423 if ((row + 1) * (move_size + 1) > (int)data_size) {
424 move_size = last_row_size - 1;
425 }
426 FXSYS_memmove(pDestData, pSrcData + 1, move_size);
427 pSrcData += move_size + 1;
428 pDestData += move_size;
429 byte_cnt += move_size;
430 continue;
431 }
432 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) {
433 uint8_t raw_byte = pSrcData[byte + 1];
434 switch (tag) {
435 case 1: {
436 uint8_t left = 0;
437 if (byte >= BytesPerPixel) {
438 left = pDestData[byte - BytesPerPixel];
439 }
440 pDestData[byte] = raw_byte + left;
441 break;
442 }
443 case 2: {
444 uint8_t up = 0;
445 if (row) {
446 up = pDestData[byte - row_size];
447 }
448 pDestData[byte] = raw_byte + up;
449 break;
450 }
451 case 3: {
452 uint8_t left = 0;
453 if (byte >= BytesPerPixel) {
454 left = pDestData[byte - BytesPerPixel];
455 }
456 uint8_t up = 0;
457 if (row) {
458 up = pDestData[byte - row_size];
459 }
460 pDestData[byte] = raw_byte + (up + left) / 2;
461 break;
462 }
463 case 4: {
464 uint8_t left = 0;
465 if (byte >= BytesPerPixel) {
466 left = pDestData[byte - BytesPerPixel];
467 }
468 uint8_t up = 0;
469 if (row) {
470 up = pDestData[byte - row_size];
471 }
472 uint8_t upper_left = 0;
473 if (byte >= BytesPerPixel && row) {
474 upper_left = pDestData[byte - row_size - BytesPerPixel];
475 }
476 pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left);
477 break;
478 }
479 default:
480 pDestData[byte] = raw_byte;
481 break;
482 }
483 byte_cnt++;
484 }
485 pSrcData += row_size + 1;
486 pDestData += row_size;
487 }
488 FX_Free(data_buf);
489 data_buf = dest_buf;
490 data_size = row_size * row_count -
491 (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0);
492 return TRUE;
493 }
494
TIFF_PredictorEncodeLine(uint8_t * dest_buf,int row_size,int BitsPerComponent,int Colors,int Columns)495 void TIFF_PredictorEncodeLine(uint8_t* dest_buf,
496 int row_size,
497 int BitsPerComponent,
498 int Colors,
499 int Columns) {
500 int BytesPerPixel = BitsPerComponent * Colors / 8;
501 if (BitsPerComponent < 8) {
502 uint8_t mask = 0x01;
503 if (BitsPerComponent == 2) {
504 mask = 0x03;
505 } else if (BitsPerComponent == 4) {
506 mask = 0x0F;
507 }
508 int row_bits = Colors * BitsPerComponent * Columns;
509 for (int i = row_bits - BitsPerComponent; i >= BitsPerComponent;
510 i -= BitsPerComponent) {
511 int col = i % 8;
512 int index = i / 8;
513 int col_pre =
514 (col == 0) ? (8 - BitsPerComponent) : (col - BitsPerComponent);
515 int index_pre = (col == 0) ? (index - 1) : index;
516 uint8_t cur = (dest_buf[index] >> (8 - col - BitsPerComponent)) & mask;
517 uint8_t left =
518 (dest_buf[index_pre] >> (8 - col_pre - BitsPerComponent)) & mask;
519 cur -= left;
520 cur &= mask;
521 cur <<= (8 - col - BitsPerComponent);
522 dest_buf[index] &= ~(mask << ((8 - col - BitsPerComponent)));
523 dest_buf[index] |= cur;
524 }
525 } else if (BitsPerComponent == 8) {
526 for (int i = row_size - 1; i >= BytesPerPixel; i--) {
527 dest_buf[i] -= dest_buf[i - BytesPerPixel];
528 }
529 } else {
530 for (int i = row_size - BytesPerPixel; i >= BytesPerPixel;
531 i -= BytesPerPixel) {
532 FX_WORD pixel = (dest_buf[i] << 8) | dest_buf[i + 1];
533 pixel -=
534 (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1];
535 dest_buf[i] = pixel >> 8;
536 dest_buf[i + 1] = (uint8_t)pixel;
537 }
538 }
539 }
540
TIFF_PredictorEncode(uint8_t * & data_buf,FX_DWORD & data_size,int Colors,int BitsPerComponent,int Columns)541 FX_BOOL TIFF_PredictorEncode(uint8_t*& data_buf,
542 FX_DWORD& data_size,
543 int Colors,
544 int BitsPerComponent,
545 int Columns) {
546 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
547 if (row_size == 0)
548 return FALSE;
549 const int row_count = (data_size + row_size - 1) / row_size;
550 const int last_row_size = data_size % row_size;
551 for (int row = 0; row < row_count; row++) {
552 uint8_t* scan_line = data_buf + row * row_size;
553 if ((row + 1) * row_size > (int)data_size) {
554 row_size = last_row_size;
555 }
556 TIFF_PredictorEncodeLine(scan_line, row_size, BitsPerComponent, Colors,
557 Columns);
558 }
559 return TRUE;
560 }
561
TIFF_PredictLine(uint8_t * dest_buf,FX_DWORD row_size,int BitsPerComponent,int Colors,int Columns)562 void TIFF_PredictLine(uint8_t* dest_buf,
563 FX_DWORD row_size,
564 int BitsPerComponent,
565 int Colors,
566 int Columns) {
567 if (BitsPerComponent == 1) {
568 int row_bits = FX_MIN(BitsPerComponent * Colors * Columns, row_size * 8);
569 int index_pre = 0;
570 int col_pre = 0;
571 for (int i = 1; i < row_bits; i++) {
572 int col = i % 8;
573 int index = i / 8;
574 if (((dest_buf[index] >> (7 - col)) & 1) ^
575 ((dest_buf[index_pre] >> (7 - col_pre)) & 1)) {
576 dest_buf[index] |= 1 << (7 - col);
577 } else {
578 dest_buf[index] &= ~(1 << (7 - col));
579 }
580 index_pre = index;
581 col_pre = col;
582 }
583 return;
584 }
585 int BytesPerPixel = BitsPerComponent * Colors / 8;
586 if (BitsPerComponent == 16) {
587 for (FX_DWORD i = BytesPerPixel; i < row_size; i += 2) {
588 FX_WORD pixel =
589 (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1];
590 pixel += (dest_buf[i] << 8) | dest_buf[i + 1];
591 dest_buf[i] = pixel >> 8;
592 dest_buf[i + 1] = (uint8_t)pixel;
593 }
594 } else {
595 for (FX_DWORD i = BytesPerPixel; i < row_size; i++) {
596 dest_buf[i] += dest_buf[i - BytesPerPixel];
597 }
598 }
599 }
600
TIFF_Predictor(uint8_t * & data_buf,FX_DWORD & data_size,int Colors,int BitsPerComponent,int Columns)601 FX_BOOL TIFF_Predictor(uint8_t*& data_buf,
602 FX_DWORD& data_size,
603 int Colors,
604 int BitsPerComponent,
605 int Columns) {
606 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
607 if (row_size == 0)
608 return FALSE;
609 const int row_count = (data_size + row_size - 1) / row_size;
610 const int last_row_size = data_size % row_size;
611 for (int row = 0; row < row_count; row++) {
612 uint8_t* scan_line = data_buf + row * row_size;
613 if ((row + 1) * row_size > (int)data_size) {
614 row_size = last_row_size;
615 }
616 TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns);
617 }
618 return TRUE;
619 }
620
FlateUncompress(const uint8_t * src_buf,FX_DWORD src_size,FX_DWORD orig_size,uint8_t * & dest_buf,FX_DWORD & dest_size,FX_DWORD & offset)621 void FlateUncompress(const uint8_t* src_buf,
622 FX_DWORD src_size,
623 FX_DWORD orig_size,
624 uint8_t*& dest_buf,
625 FX_DWORD& dest_size,
626 FX_DWORD& offset) {
627 FX_DWORD guess_size = orig_size ? orig_size : src_size * 2;
628 const FX_DWORD kStepSize = 10240;
629 FX_DWORD alloc_step = orig_size ? kStepSize : std::min(src_size, kStepSize);
630 static const FX_DWORD kMaxInitialAllocSize = 10000000;
631 if (guess_size > kMaxInitialAllocSize) {
632 guess_size = kMaxInitialAllocSize;
633 alloc_step = kMaxInitialAllocSize;
634 }
635 FX_DWORD buf_size = guess_size;
636 FX_DWORD last_buf_size = buf_size;
637
638 dest_buf = nullptr;
639 dest_size = 0;
640 void* context = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
641 if (!context)
642 return;
643
644 std::unique_ptr<uint8_t, FxFreeDeleter> guess_buf(
645 FX_Alloc(uint8_t, guess_size + 1));
646 guess_buf.get()[guess_size] = '\0';
647
648 FPDFAPI_FlateInput(context, src_buf, src_size);
649
650 if (src_size < kStepSize) {
651 // This is the old implementation.
652 uint8_t* cur_buf = guess_buf.get();
653 while (1) {
654 int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
655 if (ret != Z_OK)
656 break;
657 int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
658 if (avail_buf_size != 0)
659 break;
660
661 FX_DWORD old_size = guess_size;
662 guess_size += alloc_step;
663 if (guess_size < old_size || guess_size + 1 < guess_size) {
664 FPDFAPI_FlateEnd(context);
665 return;
666 }
667
668 {
669 uint8_t* new_buf =
670 FX_Realloc(uint8_t, guess_buf.release(), guess_size + 1);
671 guess_buf.reset(new_buf);
672 }
673 guess_buf.get()[guess_size] = '\0';
674 cur_buf = guess_buf.get() + old_size;
675 buf_size = guess_size - old_size;
676 }
677 dest_size = FPDFAPI_FlateGetTotalOut(context);
678 offset = FPDFAPI_FlateGetTotalIn(context);
679 if (guess_size / 2 > dest_size) {
680 {
681 uint8_t* new_buf =
682 FX_Realloc(uint8_t, guess_buf.release(), dest_size + 1);
683 guess_buf.reset(new_buf);
684 }
685 guess_size = dest_size;
686 guess_buf.get()[guess_size] = '\0';
687 }
688 dest_buf = guess_buf.release();
689 } else {
690 CFX_ArrayTemplate<uint8_t*> result_tmp_bufs;
691 uint8_t* cur_buf = guess_buf.release();
692 while (1) {
693 int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
694 int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
695 if (ret != Z_OK) {
696 last_buf_size = buf_size - avail_buf_size;
697 result_tmp_bufs.Add(cur_buf);
698 break;
699 }
700 if (avail_buf_size != 0) {
701 last_buf_size = buf_size - avail_buf_size;
702 result_tmp_bufs.Add(cur_buf);
703 break;
704 }
705
706 result_tmp_bufs.Add(cur_buf);
707 cur_buf = FX_Alloc(uint8_t, buf_size + 1);
708 cur_buf[buf_size] = '\0';
709 }
710 dest_size = FPDFAPI_FlateGetTotalOut(context);
711 offset = FPDFAPI_FlateGetTotalIn(context);
712 if (result_tmp_bufs.GetSize() == 1) {
713 dest_buf = result_tmp_bufs[0];
714 } else {
715 uint8_t* result_buf = FX_Alloc(uint8_t, dest_size);
716 FX_DWORD result_pos = 0;
717 for (int32_t i = 0; i < result_tmp_bufs.GetSize(); i++) {
718 uint8_t* tmp_buf = result_tmp_bufs[i];
719 FX_DWORD tmp_buf_size = buf_size;
720 if (i == result_tmp_bufs.GetSize() - 1) {
721 tmp_buf_size = last_buf_size;
722 }
723 FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size);
724 result_pos += tmp_buf_size;
725 FX_Free(result_tmp_bufs[i]);
726 }
727 dest_buf = result_buf;
728 }
729 }
730 FPDFAPI_FlateEnd(context);
731 }
732
733 } // namespace
734
735 class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder {
736 public:
737 CCodec_FlateScanlineDecoder();
738 ~CCodec_FlateScanlineDecoder() override;
739
740 void Create(const uint8_t* src_buf,
741 FX_DWORD src_size,
742 int width,
743 int height,
744 int nComps,
745 int bpc,
746 int predictor,
747 int Colors,
748 int BitsPerComponent,
749 int Columns);
Destroy()750 void Destroy() { delete this; }
751
752 // CCodec_ScanlineDecoder
v_DownScale(int dest_width,int dest_height)753 void v_DownScale(int dest_width, int dest_height) override {}
754 FX_BOOL v_Rewind() override;
755 uint8_t* v_GetNextLine() override;
756 FX_DWORD GetSrcOffset() override;
757
758 void* m_pFlate;
759 const uint8_t* m_SrcBuf;
760 FX_DWORD m_SrcSize;
761 uint8_t* m_pScanline;
762 uint8_t* m_pLastLine;
763 uint8_t* m_pPredictBuffer;
764 uint8_t* m_pPredictRaw;
765 int m_Predictor;
766 int m_Colors;
767 int m_BitsPerComponent;
768 int m_Columns;
769 FX_DWORD m_PredictPitch;
770 size_t m_LeftOver;
771 };
772
CCodec_FlateScanlineDecoder()773 CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() {
774 m_pFlate = NULL;
775 m_pScanline = NULL;
776 m_pLastLine = NULL;
777 m_pPredictBuffer = NULL;
778 m_pPredictRaw = NULL;
779 m_LeftOver = 0;
780 }
~CCodec_FlateScanlineDecoder()781 CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() {
782 FX_Free(m_pScanline);
783 FX_Free(m_pLastLine);
784 FX_Free(m_pPredictBuffer);
785 FX_Free(m_pPredictRaw);
786 if (m_pFlate) {
787 FPDFAPI_FlateEnd(m_pFlate);
788 }
789 }
Create(const uint8_t * src_buf,FX_DWORD src_size,int width,int height,int nComps,int bpc,int predictor,int Colors,int BitsPerComponent,int Columns)790 void CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf,
791 FX_DWORD src_size,
792 int width,
793 int height,
794 int nComps,
795 int bpc,
796 int predictor,
797 int Colors,
798 int BitsPerComponent,
799 int Columns) {
800 m_SrcBuf = src_buf;
801 m_SrcSize = src_size;
802 m_OutputWidth = m_OrigWidth = width;
803 m_OutputHeight = m_OrigHeight = height;
804 m_nComps = nComps;
805 m_bpc = bpc;
806 m_bColorTransformed = FALSE;
807 m_Pitch = (static_cast<FX_DWORD>(width) * nComps * bpc + 7) / 8;
808 m_pScanline = FX_Alloc(uint8_t, m_Pitch);
809 m_Predictor = 0;
810 if (predictor) {
811 if (predictor >= 10) {
812 m_Predictor = 2;
813 } else if (predictor == 2) {
814 m_Predictor = 1;
815 }
816 if (m_Predictor) {
817 if (BitsPerComponent * Colors * Columns == 0) {
818 BitsPerComponent = m_bpc;
819 Colors = m_nComps;
820 Columns = m_OrigWidth;
821 }
822 m_Colors = Colors;
823 m_BitsPerComponent = BitsPerComponent;
824 m_Columns = Columns;
825 m_PredictPitch =
826 (static_cast<FX_DWORD>(m_BitsPerComponent) * m_Colors * m_Columns +
827 7) /
828 8;
829 m_pLastLine = FX_Alloc(uint8_t, m_PredictPitch);
830 m_pPredictRaw = FX_Alloc(uint8_t, m_PredictPitch + 1);
831 m_pPredictBuffer = FX_Alloc(uint8_t, m_PredictPitch);
832 }
833 }
834 }
v_Rewind()835 FX_BOOL CCodec_FlateScanlineDecoder::v_Rewind() {
836 if (m_pFlate) {
837 FPDFAPI_FlateEnd(m_pFlate);
838 }
839 m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
840 if (!m_pFlate) {
841 return FALSE;
842 }
843 FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize);
844 m_LeftOver = 0;
845 return TRUE;
846 }
v_GetNextLine()847 uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() {
848 if (m_Predictor) {
849 if (m_Pitch == m_PredictPitch) {
850 if (m_Predictor == 2) {
851 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
852 PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine,
853 m_BitsPerComponent, m_Colors, m_Columns);
854 FXSYS_memcpy(m_pLastLine, m_pScanline, m_PredictPitch);
855 } else {
856 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
857 TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps,
858 m_OutputWidth);
859 }
860 } else {
861 size_t bytes_to_go = m_Pitch;
862 size_t read_leftover =
863 m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver;
864 if (read_leftover) {
865 FXSYS_memcpy(m_pScanline,
866 m_pPredictBuffer + m_PredictPitch - m_LeftOver,
867 read_leftover);
868 m_LeftOver -= read_leftover;
869 bytes_to_go -= read_leftover;
870 }
871 while (bytes_to_go) {
872 if (m_Predictor == 2) {
873 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
874 PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine,
875 m_BitsPerComponent, m_Colors, m_Columns);
876 FXSYS_memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch);
877 } else {
878 FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch);
879 TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent,
880 m_Colors, m_Columns);
881 }
882 size_t read_bytes =
883 m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch;
884 FXSYS_memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer,
885 read_bytes);
886 m_LeftOver += m_PredictPitch - read_bytes;
887 bytes_to_go -= read_bytes;
888 }
889 }
890 } else {
891 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
892 }
893 return m_pScanline;
894 }
GetSrcOffset()895 FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset() {
896 return FPDFAPI_FlateGetTotalIn(m_pFlate);
897 }
898
CreateDecoder(const uint8_t * src_buf,FX_DWORD src_size,int width,int height,int nComps,int bpc,int predictor,int Colors,int BitsPerComponent,int Columns)899 ICodec_ScanlineDecoder* CCodec_FlateModule::CreateDecoder(
900 const uint8_t* src_buf,
901 FX_DWORD src_size,
902 int width,
903 int height,
904 int nComps,
905 int bpc,
906 int predictor,
907 int Colors,
908 int BitsPerComponent,
909 int Columns) {
910 CCodec_FlateScanlineDecoder* pDecoder = new CCodec_FlateScanlineDecoder;
911 pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor,
912 Colors, BitsPerComponent, Columns);
913 return pDecoder;
914 }
FlateOrLZWDecode(FX_BOOL bLZW,const uint8_t * src_buf,FX_DWORD src_size,FX_BOOL bEarlyChange,int predictor,int Colors,int BitsPerComponent,int Columns,FX_DWORD estimated_size,uint8_t * & dest_buf,FX_DWORD & dest_size)915 FX_DWORD CCodec_FlateModule::FlateOrLZWDecode(FX_BOOL bLZW,
916 const uint8_t* src_buf,
917 FX_DWORD src_size,
918 FX_BOOL bEarlyChange,
919 int predictor,
920 int Colors,
921 int BitsPerComponent,
922 int Columns,
923 FX_DWORD estimated_size,
924 uint8_t*& dest_buf,
925 FX_DWORD& dest_size) {
926 dest_buf = NULL;
927 FX_DWORD offset = 0;
928 int predictor_type = 0;
929 if (predictor) {
930 if (predictor >= 10) {
931 predictor_type = 2;
932 } else if (predictor == 2) {
933 predictor_type = 1;
934 }
935 }
936 if (bLZW) {
937 {
938 std::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
939 dest_size = (FX_DWORD)-1;
940 offset = src_size;
941 int err = decoder->Decode(NULL, dest_size, src_buf, offset, bEarlyChange);
942 if (err || dest_size == 0 || dest_size + 1 < dest_size) {
943 return -1;
944 }
945 }
946 {
947 std::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
948 dest_buf = FX_Alloc(uint8_t, dest_size + 1);
949 dest_buf[dest_size] = '\0';
950 decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange);
951 }
952 } else {
953 FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size,
954 offset);
955 }
956 if (predictor_type == 0) {
957 return offset;
958 }
959 FX_BOOL ret = TRUE;
960 if (predictor_type == 2) {
961 ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns);
962 } else if (predictor_type == 1) {
963 ret =
964 TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns);
965 }
966 return ret ? offset : -1;
967 }
Encode(const uint8_t * src_buf,FX_DWORD src_size,int predictor,int Colors,int BitsPerComponent,int Columns,uint8_t * & dest_buf,FX_DWORD & dest_size)968 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf,
969 FX_DWORD src_size,
970 int predictor,
971 int Colors,
972 int BitsPerComponent,
973 int Columns,
974 uint8_t*& dest_buf,
975 FX_DWORD& dest_size) {
976 if (predictor != 2 && predictor < 10) {
977 return Encode(src_buf, src_size, dest_buf, dest_size);
978 }
979 uint8_t* pSrcBuf = NULL;
980 pSrcBuf = FX_Alloc(uint8_t, src_size);
981 FXSYS_memcpy(pSrcBuf, src_buf, src_size);
982 FX_BOOL ret = TRUE;
983 if (predictor == 2) {
984 ret = TIFF_PredictorEncode(pSrcBuf, src_size, Colors, BitsPerComponent,
985 Columns);
986 } else if (predictor >= 10) {
987 ret = PNG_PredictorEncode(pSrcBuf, src_size, predictor, Colors,
988 BitsPerComponent, Columns);
989 }
990 if (ret)
991 ret = Encode(pSrcBuf, src_size, dest_buf, dest_size);
992 FX_Free(pSrcBuf);
993 return ret;
994 }
Encode(const uint8_t * src_buf,FX_DWORD src_size,uint8_t * & dest_buf,FX_DWORD & dest_size)995 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf,
996 FX_DWORD src_size,
997 uint8_t*& dest_buf,
998 FX_DWORD& dest_size) {
999 dest_size = src_size + src_size / 1000 + 12;
1000 dest_buf = FX_Alloc(uint8_t, dest_size);
1001 unsigned long temp_size = dest_size;
1002 FPDFAPI_FlateCompress(dest_buf, &temp_size, src_buf, src_size);
1003 dest_size = (FX_DWORD)temp_size;
1004 return TRUE;
1005 }
1006