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" { 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 } 21 static void my_free_func(void* opaque, void* address) { 22 FX_Free(address); 23 } 24 static int FPDFAPI_FlateGetTotalOut(void* context) { 25 return ((z_stream*)context)->total_out; 26 } 27 static int FPDFAPI_FlateGetTotalIn(void* context) { 28 return ((z_stream*)context)->total_in; 29 } 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 } 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 } 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 } 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 } 68 int FPDFAPI_FlateGetAvailIn(void* context) { 69 return ((z_stream*)context)->avail_in; 70 } 71 int FPDFAPI_FlateGetAvailOut(void* context) { 72 return ((z_stream*)context)->avail_out; 73 } 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 }; 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 } 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 } 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 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 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 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 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 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 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 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 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 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); 750 void Destroy() { delete this; } 751 752 // CCodec_ScanlineDecoder 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 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 } 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 } 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 } 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 } 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 } 895 FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset() { 896 return FPDFAPI_FlateGetTotalIn(m_pFlate); 897 } 898 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 } 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 } 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 } 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