| 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 static void error_fatal(j_common_ptr cinfo) { |
| 48 extern "C" { | |
| 49 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 static void src_skip_data(struct jpeg_decompress_struct* cinfo, long num) { |
| 53 extern "C" { | |
| 54 static void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) { | |
| 55 if (num > (long)cinfo->src->bytes_in_buffer) { | 52 if (num > (long)cinfo->src->bytes_in_buffer) { |
| 56 _error_fatal((j_common_ptr)cinfo); | 53 error_fatal((j_common_ptr)cinfo); |
| 57 } | 54 } |
| 58 cinfo->src->next_input_byte += num; | 55 cinfo->src->next_input_byte += num; |
| 59 cinfo->src->bytes_in_buffer -= num; | 56 cinfo->src->bytes_in_buffer -= num; |
| 60 } | 57 } |
| 61 }; | 58 |
| 62 extern "C" { | 59 static boolean src_fill_buffer(j_decompress_ptr cinfo) { |
| 63 static boolean _src_fill_buffer(j_decompress_ptr cinfo) { | |
| 64 return 0; | 60 return 0; |
| 65 } | 61 } |
| 66 }; | 62 |
| 67 extern "C" { | 63 static boolean src_resync(j_decompress_ptr cinfo, int desired) { |
| 68 static boolean _src_resync(j_decompress_ptr cinfo, int desired) { | |
| 69 return 0; | 64 return 0; |
| 70 } | 65 } |
| 71 }; | 66 |
| 72 extern "C" { | 67 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
| 73 static void _error_do_nothing(j_common_ptr cinfo) {} | 68 static void dest_do_nothing(j_compress_ptr cinfo) {} |
| 74 }; | 69 |
| 75 extern "C" { | 70 static boolean dest_empty(j_compress_ptr cinfo) { |
| 76 static void _error_do_nothing1(j_common_ptr cinfo, int) {} | 71 return false; |
| 77 }; | 72 } |
| 78 extern "C" { | 73 #endif |
| 79 static void _error_do_nothing2(j_common_ptr cinfo, char*) {} | 74 |
| 75 static void error_do_nothing(j_common_ptr cinfo) {} |
| 76 |
| 77 static void error_do_nothing1(j_common_ptr cinfo, int) {} |
| 78 |
| 79 static void error_do_nothing2(j_common_ptr cinfo, char*) {} |
| 80 }; | 80 }; |
| 81 | 81 |
| 82 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) | 82 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) |
| 83 #define JPEG_MARKER_MAXSIZE 0xFFFF | 83 #define JPEG_MARKER_MAXSIZE 0xFFFF |
| 84 | 84 |
| 85 #ifdef PDF_ENABLE_XFA | 85 #ifdef PDF_ENABLE_XFA |
| 86 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, | 86 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, |
| 87 CFX_DIBAttribute* pAttribute) { | 87 CFX_DIBAttribute* pAttribute) { |
| 88 if (!pAttribute) | 88 if (!pAttribute) |
| 89 return; | 89 return; |
| 90 | 90 |
| 91 pAttribute->m_nXDPI = pInfo->X_density; | 91 pAttribute->m_nXDPI = pInfo->X_density; |
| 92 pAttribute->m_nYDPI = pInfo->Y_density; | 92 pAttribute->m_nYDPI = pInfo->Y_density; |
| 93 pAttribute->m_wDPIUnit = pInfo->density_unit; | 93 pAttribute->m_wDPIUnit = pInfo->density_unit; |
| 94 } | 94 } |
| 95 #endif // PDF_ENABLE_XFA | 95 #endif // PDF_ENABLE_XFA |
| 96 | 96 |
| 97 static bool JpegLoadInfo(const uint8_t* src_buf, | 97 static bool JpegLoadInfo(const uint8_t* src_buf, |
| 98 uint32_t src_size, | 98 uint32_t src_size, |
| 99 int* width, | 99 int* width, |
| 100 int* height, | 100 int* height, |
| 101 int* num_components, | 101 int* num_components, |
| 102 int* bits_per_components, | 102 int* bits_per_components, |
| 103 bool* color_transform) { | 103 bool* color_transform) { |
| 104 JpegScanSOI(&src_buf, &src_size); | 104 JpegScanSOI(&src_buf, &src_size); |
| 105 struct jpeg_decompress_struct cinfo; | 105 struct jpeg_decompress_struct cinfo; |
| 106 struct jpeg_error_mgr jerr; | 106 struct jpeg_error_mgr jerr; |
| 107 jerr.error_exit = _error_fatal; | 107 jerr.error_exit = error_fatal; |
| 108 jerr.emit_message = _error_do_nothing1; | 108 jerr.emit_message = error_do_nothing1; |
| 109 jerr.output_message = _error_do_nothing; | 109 jerr.output_message = error_do_nothing; |
| 110 jerr.format_message = _error_do_nothing2; | 110 jerr.format_message = error_do_nothing2; |
| 111 jerr.reset_error_mgr = _error_do_nothing; | 111 jerr.reset_error_mgr = error_do_nothing; |
| 112 jerr.trace_level = 0; | 112 jerr.trace_level = 0; |
| 113 cinfo.err = &jerr; | 113 cinfo.err = &jerr; |
| 114 jmp_buf mark; | 114 jmp_buf mark; |
| 115 cinfo.client_data = &mark; | 115 cinfo.client_data = &mark; |
| 116 if (setjmp(mark) == -1) | 116 if (setjmp(mark) == -1) |
| 117 return false; | 117 return false; |
| 118 | 118 |
| 119 jpeg_create_decompress(&cinfo); | 119 jpeg_create_decompress(&cinfo); |
| 120 struct jpeg_source_mgr src; | 120 struct jpeg_source_mgr src; |
| 121 src.init_source = _src_do_nothing; | 121 src.init_source = src_do_nothing; |
| 122 src.term_source = _src_do_nothing; | 122 src.term_source = src_do_nothing; |
| 123 src.skip_input_data = _src_skip_data; | 123 src.skip_input_data = src_skip_data; |
| 124 src.fill_input_buffer = _src_fill_buffer; | 124 src.fill_input_buffer = src_fill_buffer; |
| 125 src.resync_to_restart = _src_resync; | 125 src.resync_to_restart = src_resync; |
| 126 src.bytes_in_buffer = src_size; | 126 src.bytes_in_buffer = src_size; |
| 127 src.next_input_byte = src_buf; | 127 src.next_input_byte = src_buf; |
| 128 cinfo.src = &src; | 128 cinfo.src = &src; |
| 129 if (setjmp(mark) == -1) { | 129 if (setjmp(mark) == -1) { |
| 130 jpeg_destroy_decompress(&cinfo); | 130 jpeg_destroy_decompress(&cinfo); |
| 131 return false; | 131 return false; |
| 132 } | 132 } |
| 133 int ret = jpeg_read_header(&cinfo, true); | 133 int ret = jpeg_read_header(&cinfo, true); |
| 134 if (ret != JPEG_HEADER_OK) { | 134 if (ret != JPEG_HEADER_OK) { |
| 135 jpeg_destroy_decompress(&cinfo); | 135 jpeg_destroy_decompress(&cinfo); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 234 |
| 235 bool CCodec_JpegDecoder::Create(const uint8_t* src_buf, | 235 bool CCodec_JpegDecoder::Create(const uint8_t* src_buf, |
| 236 uint32_t src_size, | 236 uint32_t src_size, |
| 237 int width, | 237 int width, |
| 238 int height, | 238 int height, |
| 239 int nComps, | 239 int nComps, |
| 240 bool ColorTransform) { | 240 bool ColorTransform) { |
| 241 JpegScanSOI(&src_buf, &src_size); | 241 JpegScanSOI(&src_buf, &src_size); |
| 242 m_SrcBuf = src_buf; | 242 m_SrcBuf = src_buf; |
| 243 m_SrcSize = src_size; | 243 m_SrcSize = src_size; |
| 244 jerr.error_exit = _error_fatal; | 244 jerr.error_exit = error_fatal; |
| 245 jerr.emit_message = _error_do_nothing1; | 245 jerr.emit_message = error_do_nothing1; |
| 246 jerr.output_message = _error_do_nothing; | 246 jerr.output_message = error_do_nothing; |
| 247 jerr.format_message = _error_do_nothing2; | 247 jerr.format_message = error_do_nothing2; |
| 248 jerr.reset_error_mgr = _error_do_nothing; | 248 jerr.reset_error_mgr = error_do_nothing; |
| 249 src.init_source = _src_do_nothing; | 249 src.init_source = src_do_nothing; |
| 250 src.term_source = _src_do_nothing; | 250 src.term_source = src_do_nothing; |
| 251 src.skip_input_data = _src_skip_data; | 251 src.skip_input_data = src_skip_data; |
| 252 src.fill_input_buffer = _src_fill_buffer; | 252 src.fill_input_buffer = src_fill_buffer; |
| 253 src.resync_to_restart = _src_resync; | 253 src.resync_to_restart = src_resync; |
| 254 m_bJpegTransform = ColorTransform; | 254 m_bJpegTransform = ColorTransform; |
| 255 if (src_size > 1 && | 255 if (src_size > 1 && |
| 256 FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { | 256 FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { |
| 257 ((uint8_t*)src_buf)[src_size - 2] = 0xFF; | 257 ((uint8_t*)src_buf)[src_size - 2] = 0xFF; |
| 258 ((uint8_t*)src_buf)[src_size - 1] = 0xD9; | 258 ((uint8_t*)src_buf)[src_size - 1] = 0xD9; |
| 259 } | 259 } |
| 260 m_OutputWidth = m_OrigWidth = width; | 260 m_OutputWidth = m_OrigWidth = width; |
| 261 m_OutputHeight = m_OrigHeight = height; | 261 m_OutputHeight = m_OrigHeight = height; |
| 262 if (!InitDecode()) | 262 if (!InitDecode()) |
| 263 return false; | 263 return false; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 struct FXJPEG_Context { | 347 struct FXJPEG_Context { |
| 348 jmp_buf m_JumpMark; | 348 jmp_buf m_JumpMark; |
| 349 jpeg_decompress_struct m_Info; | 349 jpeg_decompress_struct m_Info; |
| 350 jpeg_error_mgr m_ErrMgr; | 350 jpeg_error_mgr m_ErrMgr; |
| 351 jpeg_source_mgr m_SrcMgr; | 351 jpeg_source_mgr m_SrcMgr; |
| 352 unsigned int m_SkipSize; | 352 unsigned int m_SkipSize; |
| 353 void* (*m_AllocFunc)(unsigned int); | 353 void* (*m_AllocFunc)(unsigned int); |
| 354 void (*m_FreeFunc)(void*); | 354 void (*m_FreeFunc)(void*); |
| 355 }; | 355 }; |
| 356 extern "C" { | 356 extern "C" { |
| 357 static void _error_fatal1(j_common_ptr cinfo) { | 357 static void error_fatal1(j_common_ptr cinfo) { |
| 358 longjmp(((FXJPEG_Context*)cinfo->client_data)->m_JumpMark, -1); | 358 longjmp(((FXJPEG_Context*)cinfo->client_data)->m_JumpMark, -1); |
| 359 } | 359 } |
| 360 }; | 360 }; |
| 361 extern "C" { | 361 extern "C" { |
| 362 static void _src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) { | 362 static void src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) { |
| 363 if (cinfo->src->bytes_in_buffer < (size_t)num) { | 363 if (cinfo->src->bytes_in_buffer < (size_t)num) { |
| 364 ((FXJPEG_Context*)cinfo->client_data)->m_SkipSize = | 364 ((FXJPEG_Context*)cinfo->client_data)->m_SkipSize = |
| 365 (unsigned int)(num - cinfo->src->bytes_in_buffer); | 365 (unsigned int)(num - cinfo->src->bytes_in_buffer); |
| 366 cinfo->src->bytes_in_buffer = 0; | 366 cinfo->src->bytes_in_buffer = 0; |
| 367 } else { | 367 } else { |
| 368 cinfo->src->next_input_byte += num; | 368 cinfo->src->next_input_byte += num; |
| 369 cinfo->src->bytes_in_buffer -= num; | 369 cinfo->src->bytes_in_buffer -= num; |
| 370 } | 370 } |
| 371 } | 371 } |
| 372 }; | 372 }; |
| 373 static void* jpeg_alloc_func(unsigned int size) { | 373 static void* jpeg_alloc_func(unsigned int size) { |
| 374 return FX_Alloc(char, size); | 374 return FX_Alloc(char, size); |
| 375 } | 375 } |
| 376 static void jpeg_free_func(void* p) { | 376 static void jpeg_free_func(void* p) { |
| 377 FX_Free(p); | 377 FX_Free(p); |
| 378 } | 378 } |
| 379 FXJPEG_Context* CCodec_JpegModule::Start() { | 379 FXJPEG_Context* CCodec_JpegModule::Start() { |
| 380 FXJPEG_Context* p = FX_Alloc(FXJPEG_Context, 1); | 380 FXJPEG_Context* p = FX_Alloc(FXJPEG_Context, 1); |
| 381 p->m_AllocFunc = jpeg_alloc_func; | 381 p->m_AllocFunc = jpeg_alloc_func; |
| 382 p->m_FreeFunc = jpeg_free_func; | 382 p->m_FreeFunc = jpeg_free_func; |
| 383 p->m_ErrMgr.error_exit = _error_fatal1; | 383 p->m_ErrMgr.error_exit = error_fatal1; |
| 384 p->m_ErrMgr.emit_message = _error_do_nothing1; | 384 p->m_ErrMgr.emit_message = error_do_nothing1; |
| 385 p->m_ErrMgr.output_message = _error_do_nothing; | 385 p->m_ErrMgr.output_message = error_do_nothing; |
| 386 p->m_ErrMgr.format_message = _error_do_nothing2; | 386 p->m_ErrMgr.format_message = error_do_nothing2; |
| 387 p->m_ErrMgr.reset_error_mgr = _error_do_nothing; | 387 p->m_ErrMgr.reset_error_mgr = error_do_nothing; |
| 388 p->m_SrcMgr.init_source = _src_do_nothing; | 388 p->m_SrcMgr.init_source = src_do_nothing; |
| 389 p->m_SrcMgr.term_source = _src_do_nothing; | 389 p->m_SrcMgr.term_source = src_do_nothing; |
| 390 p->m_SrcMgr.skip_input_data = _src_skip_data1; | 390 p->m_SrcMgr.skip_input_data = src_skip_data1; |
| 391 p->m_SrcMgr.fill_input_buffer = _src_fill_buffer; | 391 p->m_SrcMgr.fill_input_buffer = src_fill_buffer; |
| 392 p->m_SrcMgr.resync_to_restart = _src_resync; | 392 p->m_SrcMgr.resync_to_restart = src_resync; |
| 393 p->m_Info.client_data = p; | 393 p->m_Info.client_data = p; |
| 394 p->m_Info.err = &p->m_ErrMgr; | 394 p->m_Info.err = &p->m_ErrMgr; |
| 395 if (setjmp(p->m_JumpMark) == -1) { | 395 if (setjmp(p->m_JumpMark) == -1) { |
| 396 return 0; | 396 return 0; |
| 397 } | 397 } |
| 398 jpeg_create_decompress(&p->m_Info); | 398 jpeg_create_decompress(&p->m_Info); |
| 399 p->m_Info.src = &p->m_SrcMgr; | 399 p->m_Info.src = &p->m_SrcMgr; |
| 400 p->m_SkipSize = 0; | 400 p->m_SkipSize = 0; |
| 401 return p; | 401 return p; |
| 402 } | 402 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, | 473 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, |
| 474 uint8_t** avail_buf_ptr) { | 474 uint8_t** avail_buf_ptr) { |
| 475 if (avail_buf_ptr) { | 475 if (avail_buf_ptr) { |
| 476 *avail_buf_ptr = nullptr; | 476 *avail_buf_ptr = nullptr; |
| 477 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { | 477 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { |
| 478 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; | 478 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; |
| 479 } | 479 } |
| 480 } | 480 } |
| 481 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; | 481 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; |
| 482 } | 482 } |
| 483 |
| 484 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
| 485 // static |
| 486 bool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource, |
| 487 uint8_t*& dest_buf, |
| 488 FX_STRSIZE& dest_size) { |
| 489 if (pSource->GetBPP() < 8 || pSource->GetPalette()) |
| 490 return false; |
| 491 |
| 492 struct jpeg_error_mgr jerr; |
| 493 jerr.error_exit = error_do_nothing; |
| 494 jerr.emit_message = error_do_nothing1; |
| 495 jerr.output_message = error_do_nothing; |
| 496 jerr.format_message = error_do_nothing2; |
| 497 jerr.reset_error_mgr = error_do_nothing; |
| 498 |
| 499 struct jpeg_compress_struct cinfo; |
| 500 memset(&cinfo, 0, sizeof(cinfo)); |
| 501 cinfo.err = &jerr; |
| 502 jpeg_create_compress(&cinfo); |
| 503 int bpp = pSource->GetBPP() / 8; |
| 504 uint32_t nComponents = bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1; |
| 505 uint32_t pitch = pSource->GetPitch(); |
| 506 uint32_t width = pdfium::base::checked_cast<uint32_t>(pSource->GetWidth()); |
| 507 uint32_t height = pdfium::base::checked_cast<uint32_t>(pSource->GetHeight()); |
| 508 FX_SAFE_UINT32 safe_buf_len = width; |
| 509 safe_buf_len *= height; |
| 510 safe_buf_len *= nComponents; |
| 511 safe_buf_len += 1024; |
| 512 if (!safe_buf_len.IsValid()) |
| 513 return false; |
| 514 |
| 515 uint32_t dest_buf_length = safe_buf_len.ValueOrDie(); |
| 516 dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); |
| 517 const int MIN_TRY_BUF_LEN = 1024; |
| 518 while (!dest_buf && dest_buf_length > MIN_TRY_BUF_LEN) { |
| 519 dest_buf_length >>= 1; |
| 520 dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); |
| 521 } |
| 522 if (!dest_buf) |
| 523 return false; |
| 524 |
| 525 struct jpeg_destination_mgr dest; |
| 526 dest.init_destination = dest_do_nothing; |
| 527 dest.term_destination = dest_do_nothing; |
| 528 dest.empty_output_buffer = dest_empty; |
| 529 dest.next_output_byte = dest_buf; |
| 530 dest.free_in_buffer = dest_buf_length; |
| 531 cinfo.dest = &dest; |
| 532 cinfo.image_width = width; |
| 533 cinfo.image_height = height; |
| 534 cinfo.input_components = nComponents; |
| 535 if (nComponents == 1) |
| 536 cinfo.in_color_space = JCS_GRAYSCALE; |
| 537 else if (nComponents == 3) |
| 538 cinfo.in_color_space = JCS_RGB; |
| 539 else |
| 540 cinfo.in_color_space = JCS_CMYK; |
| 541 |
| 542 uint8_t* line_buf = nullptr; |
| 543 if (nComponents > 1) |
| 544 line_buf = FX_Alloc2D(uint8_t, width, nComponents); |
| 545 |
| 546 jpeg_set_defaults(&cinfo); |
| 547 jpeg_start_compress(&cinfo, TRUE); |
| 548 JSAMPROW row_pointer[1]; |
| 549 JDIMENSION row; |
| 550 while (cinfo.next_scanline < cinfo.image_height) { |
| 551 const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline); |
| 552 if (nComponents > 1) { |
| 553 uint8_t* dest_scan = line_buf; |
| 554 if (nComponents == 3) { |
| 555 for (uint32_t i = 0; i < width; i++) { |
| 556 dest_scan[0] = src_scan[2]; |
| 557 dest_scan[1] = src_scan[1]; |
| 558 dest_scan[2] = src_scan[0]; |
| 559 dest_scan += 3; |
| 560 src_scan += bpp; |
| 561 } |
| 562 } else { |
| 563 for (uint32_t i = 0; i < pitch; i++) { |
| 564 *dest_scan++ = ~*src_scan++; |
| 565 } |
| 566 } |
| 567 row_pointer[0] = line_buf; |
| 568 } else { |
| 569 row_pointer[0] = (uint8_t*)src_scan; |
| 570 } |
| 571 row = cinfo.next_scanline; |
| 572 jpeg_write_scanlines(&cinfo, row_pointer, 1); |
| 573 if (cinfo.next_scanline == row) { |
| 574 static const uint32_t kJpegBlockSize = 1048576; |
| 575 dest_buf = |
| 576 FX_Realloc(uint8_t, dest_buf, dest_buf_length + kJpegBlockSize); |
| 577 dest.next_output_byte = dest_buf + dest_buf_length - dest.free_in_buffer; |
| 578 dest_buf_length += kJpegBlockSize; |
| 579 dest.free_in_buffer += kJpegBlockSize; |
| 580 } |
| 581 } |
| 582 jpeg_finish_compress(&cinfo); |
| 583 jpeg_destroy_compress(&cinfo); |
| 584 FX_Free(line_buf); |
| 585 dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer; |
| 586 |
| 587 return true; |
| 588 } |
| 589 #endif |
| OLD | NEW |