| 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 "core/fxcodec/codec/codec_int.h" | 9 #include "core/fxcodec/codec/codec_int.h" |
| 10 #include "core/fxcodec/include/fx_codec.h" | 10 #include "core/fxcodec/include/fx_codec.h" |
| 11 #include "core/fxcrt/include/fx_safe_types.h" | 11 #include "core/fxcrt/include/fx_safe_types.h" |
| 12 #include "core/fxge/include/fx_dib.h" | 12 #include "core/fxge/include/fx_dib.h" |
| 13 | 13 |
| 14 extern "C" { | 14 extern "C" { |
| 15 #undef FAR | 15 #undef FAR |
| 16 #if defined(USE_SYSTEM_LIBJPEG) | 16 #if defined(USE_SYSTEM_LIBJPEG) |
| 17 #include <jpeglib.h> | 17 #include <jpeglib.h> |
| 18 #elif defined(USE_LIBJPEG_TURBO) | 18 #elif defined(USE_LIBJPEG_TURBO) |
| 19 #include "third_party/libjpeg_turbo/jpeglib.h" | 19 #include "third_party/libjpeg_turbo/jpeglib.h" |
| 20 #else | 20 #else |
| 21 #include "third_party/libjpeg/jpeglib.h" | 21 #include "third_party/libjpeg/jpeglib.h" |
| 22 #endif | 22 #endif |
| 23 } | 23 } |
| 24 | 24 |
| 25 extern "C" { | 25 extern "C" { |
| 26 static void _JpegScanSOI(const uint8_t*& src_buf, uint32_t& src_size) { | 26 static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) { |
| 27 if (src_size == 0) { | 27 if (*src_size == 0) |
| 28 return; | 28 return; |
| 29 } | 29 |
| 30 uint32_t offset = 0; | 30 uint32_t offset = 0; |
| 31 while (offset < src_size - 1) { | 31 while (offset < *src_size - 1) { |
| 32 if (src_buf[offset] == 0xff && src_buf[offset + 1] == 0xd8) { | 32 if ((*src_buf)[offset] == 0xff && (*src_buf)[offset + 1] == 0xd8) { |
| 33 src_buf += offset; | 33 *src_buf += offset; |
| 34 src_size -= offset; | 34 *src_size -= offset; |
| 35 return; | 35 return; |
| 36 } | 36 } |
| 37 offset++; | 37 offset++; |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 }; | 40 }; |
| 41 extern "C" { | 41 extern "C" { |
| 42 static void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {} | 42 static void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {} |
| 43 }; | 43 }; |
| 44 extern "C" { | 44 extern "C" { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 67 }; | 67 }; |
| 68 extern "C" { | 68 extern "C" { |
| 69 static void _error_do_nothing(j_common_ptr cinfo) {} | 69 static void _error_do_nothing(j_common_ptr cinfo) {} |
| 70 }; | 70 }; |
| 71 extern "C" { | 71 extern "C" { |
| 72 static void _error_do_nothing1(j_common_ptr cinfo, int) {} | 72 static void _error_do_nothing1(j_common_ptr cinfo, int) {} |
| 73 }; | 73 }; |
| 74 extern "C" { | 74 extern "C" { |
| 75 static void _error_do_nothing2(j_common_ptr cinfo, char*) {} | 75 static void _error_do_nothing2(j_common_ptr cinfo, char*) {} |
| 76 }; | 76 }; |
| 77 #define JPEG_MARKER_EXIF (JPEG_APP0 + 1) | 77 |
| 78 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) | 78 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) |
| 79 #define JPEG_MARKER_AUTHORTIME (JPEG_APP0 + 3) | |
| 80 #define JPEG_MARKER_MAXSIZE 0xFFFF | 79 #define JPEG_MARKER_MAXSIZE 0xFFFF |
| 81 #define JPEG_OVERHEAD_LEN 14 | |
| 82 static FX_BOOL _JpegEmbedIccProfile(j_compress_ptr cinfo, | |
| 83 const uint8_t* icc_buf_ptr, | |
| 84 uint32_t icc_length) { | |
| 85 if (!icc_buf_ptr || icc_length == 0) { | |
| 86 return FALSE; | |
| 87 } | |
| 88 uint32_t icc_segment_size = (JPEG_MARKER_MAXSIZE - 2 - JPEG_OVERHEAD_LEN); | |
| 89 uint32_t icc_segment_num = (icc_length / icc_segment_size) + 1; | |
| 90 if (icc_segment_num > 255) { | |
| 91 return FALSE; | |
| 92 } | |
| 93 uint32_t icc_data_length = | |
| 94 JPEG_OVERHEAD_LEN + (icc_segment_num > 1 ? icc_segment_size : icc_length); | |
| 95 uint8_t* icc_data = FX_Alloc(uint8_t, icc_data_length); | |
| 96 FXSYS_memcpy(icc_data, "\x49\x43\x43\x5f\x50\x52\x4f\x46\x49\x4c\x45\x00", | |
| 97 12); | |
| 98 icc_data[13] = (uint8_t)icc_segment_num; | |
| 99 for (uint8_t i = 0; i < (icc_segment_num - 1); i++) { | |
| 100 icc_data[12] = i + 1; | |
| 101 FXSYS_memcpy(icc_data + JPEG_OVERHEAD_LEN, | |
| 102 icc_buf_ptr + i * icc_segment_size, icc_segment_size); | |
| 103 jpeg_write_marker(cinfo, JPEG_MARKER_ICC, icc_data, icc_data_length); | |
| 104 } | |
| 105 icc_data[12] = (uint8_t)icc_segment_num; | |
| 106 uint32_t icc_size = (icc_segment_num - 1) * icc_segment_size; | |
| 107 FXSYS_memcpy(icc_data + JPEG_OVERHEAD_LEN, icc_buf_ptr + icc_size, | |
| 108 icc_length - icc_size); | |
| 109 jpeg_write_marker(cinfo, JPEG_MARKER_ICC, icc_data, | |
| 110 JPEG_OVERHEAD_LEN + icc_length - icc_size); | |
| 111 FX_Free(icc_data); | |
| 112 return TRUE; | |
| 113 } | |
| 114 extern "C" { | |
| 115 static void _dest_do_nothing(j_compress_ptr cinfo) {} | |
| 116 }; | |
| 117 extern "C" { | |
| 118 static boolean _dest_empty(j_compress_ptr cinfo) { | |
| 119 return FALSE; | |
| 120 } | |
| 121 }; | |
| 122 #define JPEG_BLOCK_SIZE 1048576 | |
| 123 static void _JpegEncode(const CFX_DIBSource* pSource, | |
| 124 uint8_t*& dest_buf, | |
| 125 FX_STRSIZE& dest_size, | |
| 126 int quality, | |
| 127 const uint8_t* icc_buf, | |
| 128 uint32_t icc_length) { | |
| 129 struct jpeg_error_mgr jerr; | |
| 130 jerr.error_exit = _error_do_nothing; | |
| 131 jerr.emit_message = _error_do_nothing1; | |
| 132 jerr.output_message = _error_do_nothing; | |
| 133 jerr.format_message = _error_do_nothing2; | |
| 134 jerr.reset_error_mgr = _error_do_nothing; | |
| 135 | 80 |
| 136 struct jpeg_compress_struct cinfo; | |
| 137 memset(&cinfo, 0, sizeof(cinfo)); | |
| 138 cinfo.err = &jerr; | |
| 139 jpeg_create_compress(&cinfo); | |
| 140 int Bpp = pSource->GetBPP() / 8; | |
| 141 uint32_t nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1; | |
| 142 uint32_t pitch = pSource->GetPitch(); | |
| 143 uint32_t width = pdfium::base::checked_cast<uint32_t>(pSource->GetWidth()); | |
| 144 uint32_t height = pdfium::base::checked_cast<uint32_t>(pSource->GetHeight()); | |
| 145 FX_SAFE_UINT32 safe_buf_len = width; | |
| 146 safe_buf_len *= height; | |
| 147 safe_buf_len *= nComponents; | |
| 148 safe_buf_len += 1024; | |
| 149 if (icc_length) { | |
| 150 safe_buf_len += 255 * 18; | |
| 151 safe_buf_len += icc_length; | |
| 152 } | |
| 153 uint32_t dest_buf_length = 0; | |
| 154 if (!safe_buf_len.IsValid()) { | |
| 155 dest_buf = nullptr; | |
| 156 } else { | |
| 157 dest_buf_length = safe_buf_len.ValueOrDie(); | |
| 158 dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); | |
| 159 const int MIN_TRY_BUF_LEN = 1024; | |
| 160 while (!dest_buf && dest_buf_length > MIN_TRY_BUF_LEN) { | |
| 161 dest_buf_length >>= 1; | |
| 162 dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); | |
| 163 } | |
| 164 } | |
| 165 if (!dest_buf) { | |
| 166 FX_OutOfMemoryTerminate(); | |
| 167 } | |
| 168 struct jpeg_destination_mgr dest; | |
| 169 dest.init_destination = _dest_do_nothing; | |
| 170 dest.term_destination = _dest_do_nothing; | |
| 171 dest.empty_output_buffer = _dest_empty; | |
| 172 dest.next_output_byte = dest_buf; | |
| 173 dest.free_in_buffer = dest_buf_length; | |
| 174 cinfo.dest = &dest; | |
| 175 cinfo.image_width = width; | |
| 176 cinfo.image_height = height; | |
| 177 cinfo.input_components = nComponents; | |
| 178 if (nComponents == 1) { | |
| 179 cinfo.in_color_space = JCS_GRAYSCALE; | |
| 180 } else if (nComponents == 3) { | |
| 181 cinfo.in_color_space = JCS_RGB; | |
| 182 } else { | |
| 183 cinfo.in_color_space = JCS_CMYK; | |
| 184 } | |
| 185 uint8_t* line_buf = NULL; | |
| 186 if (nComponents > 1) { | |
| 187 line_buf = FX_Alloc2D(uint8_t, width, nComponents); | |
| 188 } | |
| 189 jpeg_set_defaults(&cinfo); | |
| 190 if (quality != 75) { | |
| 191 jpeg_set_quality(&cinfo, quality, TRUE); | |
| 192 } | |
| 193 jpeg_start_compress(&cinfo, TRUE); | |
| 194 _JpegEmbedIccProfile(&cinfo, icc_buf, icc_length); | |
| 195 JSAMPROW row_pointer[1]; | |
| 196 JDIMENSION row; | |
| 197 while (cinfo.next_scanline < cinfo.image_height) { | |
| 198 const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline); | |
| 199 if (nComponents > 1) { | |
| 200 uint8_t* dest_scan = line_buf; | |
| 201 if (nComponents == 3) { | |
| 202 for (uint32_t i = 0; i < width; i++) { | |
| 203 dest_scan[0] = src_scan[2]; | |
| 204 dest_scan[1] = src_scan[1]; | |
| 205 dest_scan[2] = src_scan[0]; | |
| 206 dest_scan += 3; | |
| 207 src_scan += Bpp; | |
| 208 } | |
| 209 } else { | |
| 210 for (uint32_t i = 0; i < pitch; i++) { | |
| 211 *dest_scan++ = ~*src_scan++; | |
| 212 } | |
| 213 } | |
| 214 row_pointer[0] = line_buf; | |
| 215 } else { | |
| 216 row_pointer[0] = (uint8_t*)src_scan; | |
| 217 } | |
| 218 row = cinfo.next_scanline; | |
| 219 jpeg_write_scanlines(&cinfo, row_pointer, 1); | |
| 220 if (cinfo.next_scanline == row) { | |
| 221 dest_buf = | |
| 222 FX_Realloc(uint8_t, dest_buf, dest_buf_length + JPEG_BLOCK_SIZE); | |
| 223 dest.next_output_byte = dest_buf + dest_buf_length - dest.free_in_buffer; | |
| 224 dest_buf_length += JPEG_BLOCK_SIZE; | |
| 225 dest.free_in_buffer += JPEG_BLOCK_SIZE; | |
| 226 } | |
| 227 } | |
| 228 jpeg_finish_compress(&cinfo); | |
| 229 jpeg_destroy_compress(&cinfo); | |
| 230 FX_Free(line_buf); | |
| 231 dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer; | |
| 232 } | |
| 233 | 81 |
| 234 #ifdef PDF_ENABLE_XFA | 82 #ifdef PDF_ENABLE_XFA |
| 235 static void _JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, | 83 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, |
| 236 CFX_DIBAttribute* pAttribute) { | 84 CFX_DIBAttribute* pAttribute) { |
| 237 if (pInfo == NULL || pAttribute == NULL) { | 85 if (!pInfo || !pAttribute) |
| 238 return; | 86 return; |
| 239 } | 87 |
| 240 if (pAttribute) { | 88 pAttribute->m_nXDPI = pInfo->X_density; |
| 241 pAttribute->m_nXDPI = pInfo->X_density; | 89 pAttribute->m_nYDPI = pInfo->Y_density; |
| 242 pAttribute->m_nYDPI = pInfo->Y_density; | 90 pAttribute->m_wDPIUnit = pInfo->density_unit; |
| 243 pAttribute->m_wDPIUnit = pInfo->density_unit; | |
| 244 } | |
| 245 } | 91 } |
| 246 #endif // PDF_ENABLE_XFA | 92 #endif // PDF_ENABLE_XFA |
| 247 | 93 |
| 248 static FX_BOOL _JpegLoadInfo(const uint8_t* src_buf, | 94 static bool JpegLoadInfo(const uint8_t* src_buf, |
| 249 uint32_t src_size, | 95 uint32_t src_size, |
| 250 int& width, | 96 int* width, |
| 251 int& height, | 97 int* height, |
| 252 int& num_components, | 98 int* num_components, |
| 253 int& bits_per_components, | 99 int* bits_per_components, |
| 254 FX_BOOL& color_transform, | 100 bool* color_transform) { |
| 255 uint8_t** icc_buf_ptr, | 101 JpegScanSOI(&src_buf, &src_size); |
| 256 uint32_t* icc_length) { | |
| 257 _JpegScanSOI(src_buf, src_size); | |
| 258 struct jpeg_decompress_struct cinfo; | 102 struct jpeg_decompress_struct cinfo; |
| 259 struct jpeg_error_mgr jerr; | 103 struct jpeg_error_mgr jerr; |
| 260 jerr.error_exit = _error_fatal; | 104 jerr.error_exit = _error_fatal; |
| 261 jerr.emit_message = _error_do_nothing1; | 105 jerr.emit_message = _error_do_nothing1; |
| 262 jerr.output_message = _error_do_nothing; | 106 jerr.output_message = _error_do_nothing; |
| 263 jerr.format_message = _error_do_nothing2; | 107 jerr.format_message = _error_do_nothing2; |
| 264 jerr.reset_error_mgr = _error_do_nothing; | 108 jerr.reset_error_mgr = _error_do_nothing; |
| 265 jerr.trace_level = 0; | 109 jerr.trace_level = 0; |
| 266 cinfo.err = &jerr; | 110 cinfo.err = &jerr; |
| 267 jmp_buf mark; | 111 jmp_buf mark; |
| 268 cinfo.client_data = &mark; | 112 cinfo.client_data = &mark; |
| 269 if (setjmp(mark) == -1) { | 113 if (setjmp(mark) == -1) |
| 270 return FALSE; | 114 return false; |
| 271 } | 115 |
| 272 jpeg_create_decompress(&cinfo); | 116 jpeg_create_decompress(&cinfo); |
| 273 struct jpeg_source_mgr src; | 117 struct jpeg_source_mgr src; |
| 274 src.init_source = _src_do_nothing; | 118 src.init_source = _src_do_nothing; |
| 275 src.term_source = _src_do_nothing; | 119 src.term_source = _src_do_nothing; |
| 276 src.skip_input_data = _src_skip_data; | 120 src.skip_input_data = _src_skip_data; |
| 277 src.fill_input_buffer = _src_fill_buffer; | 121 src.fill_input_buffer = _src_fill_buffer; |
| 278 src.resync_to_restart = _src_resync; | 122 src.resync_to_restart = _src_resync; |
| 279 src.bytes_in_buffer = src_size; | 123 src.bytes_in_buffer = src_size; |
| 280 src.next_input_byte = src_buf; | 124 src.next_input_byte = src_buf; |
| 281 cinfo.src = &src; | 125 cinfo.src = &src; |
| 282 if (setjmp(mark) == -1) { | 126 if (setjmp(mark) == -1) { |
| 283 jpeg_destroy_decompress(&cinfo); | 127 jpeg_destroy_decompress(&cinfo); |
| 284 return FALSE; | 128 return false; |
| 285 } | |
| 286 if (icc_buf_ptr && icc_length) { | |
| 287 jpeg_save_markers(&cinfo, JPEG_MARKER_ICC, JPEG_MARKER_MAXSIZE); | |
| 288 } | 129 } |
| 289 int ret = jpeg_read_header(&cinfo, TRUE); | 130 int ret = jpeg_read_header(&cinfo, TRUE); |
| 290 if (ret != JPEG_HEADER_OK) { | 131 if (ret != JPEG_HEADER_OK) { |
| 291 jpeg_destroy_decompress(&cinfo); | 132 jpeg_destroy_decompress(&cinfo); |
| 292 return FALSE; | 133 return false; |
| 293 } | 134 } |
| 294 width = cinfo.image_width; | 135 *width = cinfo.image_width; |
| 295 height = cinfo.image_height; | 136 *height = cinfo.image_height; |
| 296 num_components = cinfo.num_components; | 137 *num_components = cinfo.num_components; |
| 297 color_transform = | 138 *color_transform = |
| 298 cinfo.jpeg_color_space == JCS_YCbCr || cinfo.jpeg_color_space == JCS_YCCK; | 139 cinfo.jpeg_color_space == JCS_YCbCr || cinfo.jpeg_color_space == JCS_YCCK; |
| 299 bits_per_components = cinfo.data_precision; | 140 *bits_per_components = cinfo.data_precision; |
| 300 if (icc_buf_ptr) { | |
| 301 *icc_buf_ptr = NULL; | |
| 302 } | |
| 303 if (icc_length) { | |
| 304 *icc_length = 0; | |
| 305 } | |
| 306 jpeg_destroy_decompress(&cinfo); | 141 jpeg_destroy_decompress(&cinfo); |
| 307 return TRUE; | 142 return true; |
| 308 } | 143 } |
| 309 | 144 |
| 310 class CCodec_JpegDecoder : public CCodec_ScanlineDecoder { | 145 class CCodec_JpegDecoder : public CCodec_ScanlineDecoder { |
| 311 public: | 146 public: |
| 312 CCodec_JpegDecoder(); | 147 CCodec_JpegDecoder(); |
| 313 ~CCodec_JpegDecoder() override; | 148 ~CCodec_JpegDecoder() override; |
| 314 | 149 |
| 315 FX_BOOL Create(const uint8_t* src_buf, | 150 FX_BOOL Create(const uint8_t* src_buf, |
| 316 uint32_t src_size, | 151 uint32_t src_size, |
| 317 int width, | 152 int width, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 344 | 179 |
| 345 CCodec_JpegDecoder::CCodec_JpegDecoder() { | 180 CCodec_JpegDecoder::CCodec_JpegDecoder() { |
| 346 m_pScanlineBuf = NULL; | 181 m_pScanlineBuf = NULL; |
| 347 m_bStarted = FALSE; | 182 m_bStarted = FALSE; |
| 348 m_bInited = FALSE; | 183 m_bInited = FALSE; |
| 349 FXSYS_memset(&cinfo, 0, sizeof(cinfo)); | 184 FXSYS_memset(&cinfo, 0, sizeof(cinfo)); |
| 350 FXSYS_memset(&jerr, 0, sizeof(jerr)); | 185 FXSYS_memset(&jerr, 0, sizeof(jerr)); |
| 351 FXSYS_memset(&src, 0, sizeof(src)); | 186 FXSYS_memset(&src, 0, sizeof(src)); |
| 352 m_nDefaultScaleDenom = 1; | 187 m_nDefaultScaleDenom = 1; |
| 353 } | 188 } |
| 189 |
| 354 CCodec_JpegDecoder::~CCodec_JpegDecoder() { | 190 CCodec_JpegDecoder::~CCodec_JpegDecoder() { |
| 355 FX_Free(m_pScanlineBuf); | 191 FX_Free(m_pScanlineBuf); |
| 356 if (m_bInited) { | 192 if (m_bInited) |
| 357 jpeg_destroy_decompress(&cinfo); | 193 jpeg_destroy_decompress(&cinfo); |
| 358 } | |
| 359 } | 194 } |
| 195 |
| 360 FX_BOOL CCodec_JpegDecoder::InitDecode() { | 196 FX_BOOL CCodec_JpegDecoder::InitDecode() { |
| 361 cinfo.err = &jerr; | 197 cinfo.err = &jerr; |
| 362 cinfo.client_data = &m_JmpBuf; | 198 cinfo.client_data = &m_JmpBuf; |
| 363 if (setjmp(m_JmpBuf) == -1) { | 199 if (setjmp(m_JmpBuf) == -1) |
| 364 return FALSE; | 200 return FALSE; |
| 365 } | 201 |
| 366 jpeg_create_decompress(&cinfo); | 202 jpeg_create_decompress(&cinfo); |
| 367 m_bInited = TRUE; | 203 m_bInited = TRUE; |
| 368 cinfo.src = &src; | 204 cinfo.src = &src; |
| 369 src.bytes_in_buffer = m_SrcSize; | 205 src.bytes_in_buffer = m_SrcSize; |
| 370 src.next_input_byte = m_SrcBuf; | 206 src.next_input_byte = m_SrcBuf; |
| 371 if (setjmp(m_JmpBuf) == -1) { | 207 if (setjmp(m_JmpBuf) == -1) { |
| 372 jpeg_destroy_decompress(&cinfo); | 208 jpeg_destroy_decompress(&cinfo); |
| 373 m_bInited = FALSE; | 209 m_bInited = FALSE; |
| 374 return FALSE; | 210 return FALSE; |
| 375 } | 211 } |
| 376 cinfo.image_width = m_OrigWidth; | 212 cinfo.image_width = m_OrigWidth; |
| 377 cinfo.image_height = m_OrigHeight; | 213 cinfo.image_height = m_OrigHeight; |
| 378 int ret = jpeg_read_header(&cinfo, TRUE); | 214 int ret = jpeg_read_header(&cinfo, TRUE); |
| 379 if (ret != JPEG_HEADER_OK) { | 215 if (ret != JPEG_HEADER_OK) |
| 380 return FALSE; | 216 return FALSE; |
| 381 } | 217 |
| 382 if (cinfo.saw_Adobe_marker) { | 218 if (cinfo.saw_Adobe_marker) |
| 383 m_bJpegTransform = TRUE; | 219 m_bJpegTransform = TRUE; |
| 384 } | 220 |
| 385 if (cinfo.num_components == 3 && !m_bJpegTransform) { | 221 if (cinfo.num_components == 3 && !m_bJpegTransform) |
| 386 cinfo.out_color_space = cinfo.jpeg_color_space; | 222 cinfo.out_color_space = cinfo.jpeg_color_space; |
| 387 } | 223 |
| 388 m_OrigWidth = cinfo.image_width; | 224 m_OrigWidth = cinfo.image_width; |
| 389 m_OrigHeight = cinfo.image_height; | 225 m_OrigHeight = cinfo.image_height; |
| 390 m_OutputWidth = m_OrigWidth; | 226 m_OutputWidth = m_OrigWidth; |
| 391 m_OutputHeight = m_OrigHeight; | 227 m_OutputHeight = m_OrigHeight; |
| 392 m_nDefaultScaleDenom = cinfo.scale_denom; | 228 m_nDefaultScaleDenom = cinfo.scale_denom; |
| 393 return TRUE; | 229 return TRUE; |
| 394 } | 230 } |
| 231 |
| 395 FX_BOOL CCodec_JpegDecoder::Create(const uint8_t* src_buf, | 232 FX_BOOL CCodec_JpegDecoder::Create(const uint8_t* src_buf, |
| 396 uint32_t src_size, | 233 uint32_t src_size, |
| 397 int width, | 234 int width, |
| 398 int height, | 235 int height, |
| 399 int nComps, | 236 int nComps, |
| 400 FX_BOOL ColorTransform) { | 237 FX_BOOL ColorTransform) { |
| 401 _JpegScanSOI(src_buf, src_size); | 238 JpegScanSOI(&src_buf, &src_size); |
| 402 m_SrcBuf = src_buf; | 239 m_SrcBuf = src_buf; |
| 403 m_SrcSize = src_size; | 240 m_SrcSize = src_size; |
| 404 jerr.error_exit = _error_fatal; | 241 jerr.error_exit = _error_fatal; |
| 405 jerr.emit_message = _error_do_nothing1; | 242 jerr.emit_message = _error_do_nothing1; |
| 406 jerr.output_message = _error_do_nothing; | 243 jerr.output_message = _error_do_nothing; |
| 407 jerr.format_message = _error_do_nothing2; | 244 jerr.format_message = _error_do_nothing2; |
| 408 jerr.reset_error_mgr = _error_do_nothing; | 245 jerr.reset_error_mgr = _error_do_nothing; |
| 409 src.init_source = _src_do_nothing; | 246 src.init_source = _src_do_nothing; |
| 410 src.term_source = _src_do_nothing; | 247 src.term_source = _src_do_nothing; |
| 411 src.skip_input_data = _src_skip_data; | 248 src.skip_input_data = _src_skip_data; |
| 412 src.fill_input_buffer = _src_fill_buffer; | 249 src.fill_input_buffer = _src_fill_buffer; |
| 413 src.resync_to_restart = _src_resync; | 250 src.resync_to_restart = _src_resync; |
| 414 m_bJpegTransform = ColorTransform; | 251 m_bJpegTransform = ColorTransform; |
| 415 if (src_size > 1 && | 252 if (src_size > 1 && |
| 416 FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { | 253 FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { |
| 417 ((uint8_t*)src_buf)[src_size - 2] = 0xFF; | 254 ((uint8_t*)src_buf)[src_size - 2] = 0xFF; |
| 418 ((uint8_t*)src_buf)[src_size - 1] = 0xD9; | 255 ((uint8_t*)src_buf)[src_size - 1] = 0xD9; |
| 419 } | 256 } |
| 420 m_OutputWidth = m_OrigWidth = width; | 257 m_OutputWidth = m_OrigWidth = width; |
| 421 m_OutputHeight = m_OrigHeight = height; | 258 m_OutputHeight = m_OrigHeight = height; |
| 422 if (!InitDecode()) { | 259 if (!InitDecode()) |
| 423 return FALSE; | 260 return FALSE; |
| 424 } | 261 |
| 425 if (cinfo.num_components < nComps) { | 262 if (cinfo.num_components < nComps) |
| 426 return FALSE; | 263 return FALSE; |
| 427 } | 264 |
| 428 if ((int)cinfo.image_width < width) { | 265 if ((int)cinfo.image_width < width) |
| 429 return FALSE; | 266 return FALSE; |
| 430 } | 267 |
| 431 m_Pitch = | 268 m_Pitch = |
| 432 (static_cast<uint32_t>(cinfo.image_width) * cinfo.num_components + 3) / | 269 (static_cast<uint32_t>(cinfo.image_width) * cinfo.num_components + 3) / |
| 433 4 * 4; | 270 4 * 4; |
| 434 m_pScanlineBuf = FX_Alloc(uint8_t, m_Pitch); | 271 m_pScanlineBuf = FX_Alloc(uint8_t, m_Pitch); |
| 435 m_nComps = cinfo.num_components; | 272 m_nComps = cinfo.num_components; |
| 436 m_bpc = 8; | 273 m_bpc = 8; |
| 437 m_bStarted = FALSE; | 274 m_bStarted = FALSE; |
| 438 return TRUE; | 275 return TRUE; |
| 439 } | 276 } |
| 440 | 277 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 455 jpeg_destroy_decompress(&cinfo); | 292 jpeg_destroy_decompress(&cinfo); |
| 456 return FALSE; | 293 return FALSE; |
| 457 } | 294 } |
| 458 if ((int)cinfo.output_width > m_OrigWidth) { | 295 if ((int)cinfo.output_width > m_OrigWidth) { |
| 459 ASSERT(FALSE); | 296 ASSERT(FALSE); |
| 460 return FALSE; | 297 return FALSE; |
| 461 } | 298 } |
| 462 m_bStarted = TRUE; | 299 m_bStarted = TRUE; |
| 463 return TRUE; | 300 return TRUE; |
| 464 } | 301 } |
| 302 |
| 465 uint8_t* CCodec_JpegDecoder::v_GetNextLine() { | 303 uint8_t* CCodec_JpegDecoder::v_GetNextLine() { |
| 466 if (setjmp(m_JmpBuf) == -1) | 304 if (setjmp(m_JmpBuf) == -1) |
| 467 return nullptr; | 305 return nullptr; |
| 468 | 306 |
| 469 int nlines = jpeg_read_scanlines(&cinfo, &m_pScanlineBuf, 1); | 307 int nlines = jpeg_read_scanlines(&cinfo, &m_pScanlineBuf, 1); |
| 470 if (nlines < 1) { | 308 return nlines > 0 ? m_pScanlineBuf : nullptr; |
| 471 return nullptr; | |
| 472 } | |
| 473 return m_pScanlineBuf; | |
| 474 } | 309 } |
| 310 |
| 475 uint32_t CCodec_JpegDecoder::GetSrcOffset() { | 311 uint32_t CCodec_JpegDecoder::GetSrcOffset() { |
| 476 return (uint32_t)(m_SrcSize - src.bytes_in_buffer); | 312 return (uint32_t)(m_SrcSize - src.bytes_in_buffer); |
| 477 } | 313 } |
| 314 |
| 478 CCodec_ScanlineDecoder* CCodec_JpegModule::CreateDecoder( | 315 CCodec_ScanlineDecoder* CCodec_JpegModule::CreateDecoder( |
| 479 const uint8_t* src_buf, | 316 const uint8_t* src_buf, |
| 480 uint32_t src_size, | 317 uint32_t src_size, |
| 481 int width, | 318 int width, |
| 482 int height, | 319 int height, |
| 483 int nComps, | 320 int nComps, |
| 484 FX_BOOL ColorTransform) { | 321 FX_BOOL ColorTransform) { |
| 485 if (!src_buf || src_size == 0) { | 322 if (!src_buf || src_size == 0) |
| 486 return NULL; | 323 return nullptr; |
| 487 } | 324 |
| 488 CCodec_JpegDecoder* pDecoder = new CCodec_JpegDecoder; | 325 std::unique_ptr<CCodec_JpegDecoder> pDecoder(new CCodec_JpegDecoder); |
| 489 if (!pDecoder->Create(src_buf, src_size, width, height, nComps, | 326 if (!pDecoder->Create(src_buf, src_size, width, height, nComps, |
| 490 ColorTransform)) { | 327 ColorTransform)) { |
| 491 delete pDecoder; | 328 return nullptr; |
| 492 return NULL; | |
| 493 } | 329 } |
| 494 return pDecoder; | 330 return pDecoder.release(); |
| 495 } | 331 } |
| 496 FX_BOOL CCodec_JpegModule::LoadInfo(const uint8_t* src_buf, | 332 |
| 497 uint32_t src_size, | 333 bool CCodec_JpegModule::LoadInfo(const uint8_t* src_buf, |
| 498 int& width, | 334 uint32_t src_size, |
| 499 int& height, | 335 int* width, |
| 500 int& num_components, | 336 int* height, |
| 501 int& bits_per_components, | 337 int* num_components, |
| 502 FX_BOOL& color_transform, | 338 int* bits_per_components, |
| 503 uint8_t** icc_buf_ptr, | 339 bool* color_transform) { |
| 504 uint32_t* icc_length) { | 340 return JpegLoadInfo(src_buf, src_size, width, height, num_components, |
| 505 return _JpegLoadInfo(src_buf, src_size, width, height, num_components, | 341 bits_per_components, color_transform); |
| 506 bits_per_components, color_transform, icc_buf_ptr, | |
| 507 icc_length); | |
| 508 } | 342 } |
| 509 FX_BOOL CCodec_JpegModule::Encode(const CFX_DIBSource* pSource, | |
| 510 uint8_t*& dest_buf, | |
| 511 FX_STRSIZE& dest_size, | |
| 512 int quality, | |
| 513 const uint8_t* icc_buf, | |
| 514 uint32_t icc_length) { | |
| 515 if (pSource->GetBPP() < 8 || pSource->GetPalette()) | |
| 516 return FALSE; | |
| 517 | 343 |
| 518 _JpegEncode(pSource, dest_buf, dest_size, quality, icc_buf, icc_length); | |
| 519 return TRUE; | |
| 520 } | |
| 521 struct FXJPEG_Context { | 344 struct FXJPEG_Context { |
| 522 jmp_buf m_JumpMark; | 345 jmp_buf m_JumpMark; |
| 523 jpeg_decompress_struct m_Info; | 346 jpeg_decompress_struct m_Info; |
| 524 jpeg_error_mgr m_ErrMgr; | 347 jpeg_error_mgr m_ErrMgr; |
| 525 jpeg_source_mgr m_SrcMgr; | 348 jpeg_source_mgr m_SrcMgr; |
| 526 unsigned int m_SkipSize; | 349 unsigned int m_SkipSize; |
| 527 void* (*m_AllocFunc)(unsigned int); | 350 void* (*m_AllocFunc)(unsigned int); |
| 528 void (*m_FreeFunc)(void*); | 351 void (*m_FreeFunc)(void*); |
| 529 }; | 352 }; |
| 530 extern "C" { | 353 extern "C" { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 int ret = jpeg_read_header(&ctx->m_Info, true); | 438 int ret = jpeg_read_header(&ctx->m_Info, true); |
| 616 if (ret == JPEG_SUSPENDED) | 439 if (ret == JPEG_SUSPENDED) |
| 617 return 2; | 440 return 2; |
| 618 if (ret != JPEG_HEADER_OK) | 441 if (ret != JPEG_HEADER_OK) |
| 619 return 1; | 442 return 1; |
| 620 | 443 |
| 621 *width = ctx->m_Info.image_width; | 444 *width = ctx->m_Info.image_width; |
| 622 *height = ctx->m_Info.image_height; | 445 *height = ctx->m_Info.image_height; |
| 623 *nComps = ctx->m_Info.num_components; | 446 *nComps = ctx->m_Info.num_components; |
| 624 #ifdef PDF_ENABLE_XFA | 447 #ifdef PDF_ENABLE_XFA |
| 625 _JpegLoadAttribute(&ctx->m_Info, pAttribute); | 448 JpegLoadAttribute(&ctx->m_Info, pAttribute); |
| 626 #endif | 449 #endif |
| 627 return 0; | 450 return 0; |
| 628 } | 451 } |
| 629 | 452 |
| 630 int CCodec_JpegModule::StartScanline(FXJPEG_Context* ctx, int down_scale) { | 453 int CCodec_JpegModule::StartScanline(FXJPEG_Context* ctx, int down_scale) { |
| 631 if (setjmp(ctx->m_JumpMark) == -1) | 454 if (setjmp(ctx->m_JumpMark) == -1) |
| 632 return 0; | 455 return 0; |
| 633 | 456 |
| 634 ctx->m_Info.scale_denom = down_scale; | 457 ctx->m_Info.scale_denom = down_scale; |
| 635 return jpeg_start_decompress(&ctx->m_Info); | 458 return jpeg_start_decompress(&ctx->m_Info); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 647 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, | 470 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, |
| 648 uint8_t** avail_buf_ptr) { | 471 uint8_t** avail_buf_ptr) { |
| 649 if (avail_buf_ptr) { | 472 if (avail_buf_ptr) { |
| 650 *avail_buf_ptr = NULL; | 473 *avail_buf_ptr = NULL; |
| 651 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { | 474 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { |
| 652 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; | 475 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; |
| 653 } | 476 } |
| 654 } | 477 } |
| 655 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; | 478 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; |
| 656 } | 479 } |
| OLD | NEW |