Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: core/src/fxcodec/codec/fx_codec_flate.cpp

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

Powered by Google App Engine
This is Rietveld 408576698