OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include <setjmp.h> | 7 #include <setjmp.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "core/fxcodec/codec/codec_int.h" | 12 #include "core/fxcodec/codec/codec_int.h" |
13 #include "core/fxcodec/fx_codec.h" | 13 #include "core/fxcodec/fx_codec.h" |
14 #include "core/fxcrt/fx_safe_types.h" | 14 #include "core/fxcrt/fx_safe_types.h" |
15 #include "core/fxge/fx_dib.h" | 15 #include "core/fxge/fx_dib.h" |
16 #include "third_party/base/ptr_util.h" | 16 #include "third_party/base/ptr_util.h" |
17 | 17 |
18 extern "C" { | 18 extern "C" { |
19 #undef FAR | 19 #undef FAR |
20 #if defined(USE_SYSTEM_LIBJPEG) | 20 #if defined(USE_SYSTEM_LIBJPEG) |
21 #include <jpeglib.h> | 21 #include <jpeglib.h> |
22 #elif defined(USE_LIBJPEG_TURBO) | 22 #elif defined(USE_LIBJPEG_TURBO) |
23 #include "third_party/libjpeg_turbo/jpeglib.h" | 23 #include "third_party/libjpeg_turbo/jpeglib.h" |
24 #else | 24 #else |
25 #include "third_party/libjpeg/jpeglib.h" | 25 #include "third_party/libjpeg/jpeglib.h" |
26 #endif | 26 #endif |
27 } | 27 } |
28 | 28 |
29 extern "C" { | 29 extern "C" { |
| 30 |
30 static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) { | 31 static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) { |
31 if (*src_size == 0) | 32 if (*src_size == 0) |
32 return; | 33 return; |
33 | 34 |
34 uint32_t offset = 0; | 35 uint32_t offset = 0; |
35 while (offset < *src_size - 1) { | 36 while (offset < *src_size - 1) { |
36 if ((*src_buf)[offset] == 0xff && (*src_buf)[offset + 1] == 0xd8) { | 37 if ((*src_buf)[offset] == 0xff && (*src_buf)[offset + 1] == 0xd8) { |
37 *src_buf += offset; | 38 *src_buf += offset; |
38 *src_size -= offset; | 39 *src_size -= offset; |
39 return; | 40 return; |
40 } | 41 } |
41 offset++; | 42 offset++; |
42 } | 43 } |
43 } | 44 } |
44 }; | 45 |
45 extern "C" { | |
46 static void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {} | 46 static void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {} |
47 }; | 47 |
48 extern "C" { | |
49 static void _error_fatal(j_common_ptr cinfo) { | 48 static void _error_fatal(j_common_ptr cinfo) { |
50 longjmp(*(jmp_buf*)cinfo->client_data, -1); | 49 longjmp(*(jmp_buf*)cinfo->client_data, -1); |
51 } | 50 } |
52 }; | 51 |
53 extern "C" { | |
54 static void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) { | 52 static void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) { |
55 if (num > (long)cinfo->src->bytes_in_buffer) { | 53 if (num > (long)cinfo->src->bytes_in_buffer) { |
56 _error_fatal((j_common_ptr)cinfo); | 54 _error_fatal((j_common_ptr)cinfo); |
57 } | 55 } |
58 cinfo->src->next_input_byte += num; | 56 cinfo->src->next_input_byte += num; |
59 cinfo->src->bytes_in_buffer -= num; | 57 cinfo->src->bytes_in_buffer -= num; |
60 } | 58 } |
61 }; | 59 |
62 extern "C" { | |
63 static boolean _src_fill_buffer(j_decompress_ptr cinfo) { | 60 static boolean _src_fill_buffer(j_decompress_ptr cinfo) { |
64 return 0; | 61 return 0; |
65 } | 62 } |
66 }; | 63 |
67 extern "C" { | |
68 static boolean _src_resync(j_decompress_ptr cinfo, int desired) { | 64 static boolean _src_resync(j_decompress_ptr cinfo, int desired) { |
69 return 0; | 65 return 0; |
70 } | 66 } |
71 }; | 67 |
72 extern "C" { | |
73 static void _error_do_nothing(j_common_ptr cinfo) {} | 68 static void _error_do_nothing(j_common_ptr cinfo) {} |
74 }; | 69 |
75 extern "C" { | |
76 static void _error_do_nothing1(j_common_ptr cinfo, int) {} | 70 static void _error_do_nothing1(j_common_ptr cinfo, int) {} |
77 }; | 71 |
78 extern "C" { | |
79 static void _error_do_nothing2(j_common_ptr cinfo, char*) {} | 72 static void _error_do_nothing2(j_common_ptr cinfo, char*) {} |
| 73 |
| 74 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
| 75 static void _dest_do_nothing(j_compress_ptr cinfo) {} |
| 76 |
| 77 static boolean _dest_empty(j_compress_ptr cinfo) { |
| 78 return false; |
| 79 } |
| 80 #endif |
80 }; | 81 }; |
81 | 82 |
82 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) | 83 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) |
83 #define JPEG_MARKER_MAXSIZE 0xFFFF | 84 #define JPEG_MARKER_MAXSIZE 0xFFFF |
84 | 85 |
85 #ifdef PDF_ENABLE_XFA | 86 #ifdef PDF_ENABLE_XFA |
86 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, | 87 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, |
87 CFX_DIBAttribute* pAttribute) { | 88 CFX_DIBAttribute* pAttribute) { |
88 if (!pAttribute) | 89 if (!pAttribute) |
89 return; | 90 return; |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, | 474 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, |
474 uint8_t** avail_buf_ptr) { | 475 uint8_t** avail_buf_ptr) { |
475 if (avail_buf_ptr) { | 476 if (avail_buf_ptr) { |
476 *avail_buf_ptr = nullptr; | 477 *avail_buf_ptr = nullptr; |
477 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { | 478 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { |
478 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; | 479 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; |
479 } | 480 } |
480 } | 481 } |
481 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; | 482 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; |
482 } | 483 } |
| 484 |
| 485 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
| 486 #define JPEG_BLOCK_SIZE 1048576 |
| 487 bool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource, |
| 488 uint8_t** dest_buf, |
| 489 FX_STRSIZE* dest_size) { |
| 490 struct jpeg_error_mgr jerr; |
| 491 jerr.error_exit = _error_do_nothing; |
| 492 jerr.emit_message = _error_do_nothing1; |
| 493 jerr.output_message = _error_do_nothing; |
| 494 jerr.format_message = _error_do_nothing2; |
| 495 jerr.reset_error_mgr = _error_do_nothing; |
| 496 |
| 497 struct jpeg_compress_struct cinfo; |
| 498 memset(&cinfo, 0, sizeof(cinfo)); |
| 499 cinfo.err = &jerr; |
| 500 jpeg_create_compress(&cinfo); |
| 501 int Bpp = pSource->GetBPP() / 8; |
| 502 uint32_t nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1; |
| 503 uint32_t pitch = pSource->GetPitch(); |
| 504 uint32_t width = pdfium::base::checked_cast<uint32_t>(pSource->GetWidth()); |
| 505 uint32_t height = pdfium::base::checked_cast<uint32_t>(pSource->GetHeight()); |
| 506 FX_SAFE_UINT32 safe_buf_len = width; |
| 507 safe_buf_len *= height; |
| 508 safe_buf_len *= nComponents; |
| 509 safe_buf_len += 1024; |
| 510 if (!safe_buf_len.IsValid()) |
| 511 return false; |
| 512 |
| 513 uint32_t dest_buf_length = safe_buf_len.ValueOrDie(); |
| 514 *dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); |
| 515 const int MIN_TRY_BUF_LEN = 1024; |
| 516 while (!(*dest_buf) && dest_buf_length > MIN_TRY_BUF_LEN) { |
| 517 dest_buf_length >>= 1; |
| 518 *dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); |
| 519 } |
| 520 if (!(*dest_buf)) |
| 521 return false; |
| 522 |
| 523 struct jpeg_destination_mgr dest; |
| 524 dest.init_destination = _dest_do_nothing; |
| 525 dest.term_destination = _dest_do_nothing; |
| 526 dest.empty_output_buffer = _dest_empty; |
| 527 dest.next_output_byte = *dest_buf; |
| 528 dest.free_in_buffer = dest_buf_length; |
| 529 cinfo.dest = &dest; |
| 530 cinfo.image_width = width; |
| 531 cinfo.image_height = height; |
| 532 cinfo.input_components = nComponents; |
| 533 if (nComponents == 1) { |
| 534 cinfo.in_color_space = JCS_GRAYSCALE; |
| 535 } else if (nComponents == 3) { |
| 536 cinfo.in_color_space = JCS_RGB; |
| 537 } else { |
| 538 cinfo.in_color_space = JCS_CMYK; |
| 539 } |
| 540 uint8_t* line_buf = nullptr; |
| 541 if (nComponents > 1) |
| 542 line_buf = FX_Alloc2D(uint8_t, width, nComponents); |
| 543 |
| 544 jpeg_set_defaults(&cinfo); |
| 545 jpeg_start_compress(&cinfo, TRUE); |
| 546 JSAMPROW row_pointer[1]; |
| 547 JDIMENSION row; |
| 548 while (cinfo.next_scanline < cinfo.image_height) { |
| 549 const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline); |
| 550 if (nComponents > 1) { |
| 551 uint8_t* dest_scan = line_buf; |
| 552 if (nComponents == 3) { |
| 553 for (uint32_t i = 0; i < width; i++) { |
| 554 dest_scan[0] = src_scan[2]; |
| 555 dest_scan[1] = src_scan[1]; |
| 556 dest_scan[2] = src_scan[0]; |
| 557 dest_scan += 3; |
| 558 src_scan += Bpp; |
| 559 } |
| 560 } else { |
| 561 for (uint32_t i = 0; i < pitch; i++) { |
| 562 *dest_scan++ = ~*src_scan++; |
| 563 } |
| 564 } |
| 565 row_pointer[0] = line_buf; |
| 566 } else { |
| 567 row_pointer[0] = (uint8_t*)src_scan; |
| 568 } |
| 569 row = cinfo.next_scanline; |
| 570 jpeg_write_scanlines(&cinfo, row_pointer, 1); |
| 571 if (cinfo.next_scanline == row) { |
| 572 *dest_buf = |
| 573 FX_Realloc(uint8_t, *dest_buf, dest_buf_length + JPEG_BLOCK_SIZE); |
| 574 dest.next_output_byte = *dest_buf + dest_buf_length - dest.free_in_buffer; |
| 575 dest_buf_length += JPEG_BLOCK_SIZE; |
| 576 dest.free_in_buffer += JPEG_BLOCK_SIZE; |
| 577 } |
| 578 } |
| 579 jpeg_finish_compress(&cinfo); |
| 580 jpeg_destroy_compress(&cinfo); |
| 581 FX_Free(line_buf); |
| 582 *dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer; |
| 583 |
| 584 return true; |
| 585 } |
| 586 #endif |
OLD | NEW |