Index: core/fxcodec/codec/fx_codec_jpeg.cpp |
diff --git a/core/fxcodec/codec/fx_codec_jpeg.cpp b/core/fxcodec/codec/fx_codec_jpeg.cpp |
index fdfdd4faeb7bfb2291779d48b6462343778dd46d..c79760557536aa64f3d9cff8831d9d9d0dc8dd4f 100644 |
--- a/core/fxcodec/codec/fx_codec_jpeg.cpp |
+++ b/core/fxcodec/codec/fx_codec_jpeg.cpp |
@@ -27,6 +27,7 @@ extern "C" { |
} |
extern "C" { |
+ |
static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) { |
if (*src_size == 0) |
return; |
@@ -41,16 +42,13 @@ static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) { |
offset++; |
} |
} |
-}; |
-extern "C" { |
+ |
static void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {} |
-}; |
-extern "C" { |
+ |
static void _error_fatal(j_common_ptr cinfo) { |
longjmp(*(jmp_buf*)cinfo->client_data, -1); |
} |
-}; |
-extern "C" { |
+ |
static void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) { |
if (num > (long)cinfo->src->bytes_in_buffer) { |
_error_fatal((j_common_ptr)cinfo); |
@@ -58,25 +56,28 @@ static void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) { |
cinfo->src->next_input_byte += num; |
cinfo->src->bytes_in_buffer -= num; |
} |
-}; |
-extern "C" { |
+ |
static boolean _src_fill_buffer(j_decompress_ptr cinfo) { |
return 0; |
} |
-}; |
-extern "C" { |
+ |
static boolean _src_resync(j_decompress_ptr cinfo, int desired) { |
return 0; |
} |
-}; |
-extern "C" { |
+ |
static void _error_do_nothing(j_common_ptr cinfo) {} |
-}; |
-extern "C" { |
+ |
static void _error_do_nothing1(j_common_ptr cinfo, int) {} |
-}; |
-extern "C" { |
+ |
static void _error_do_nothing2(j_common_ptr cinfo, char*) {} |
+ |
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
+static void _dest_do_nothing(j_compress_ptr cinfo) {} |
+ |
+static boolean _dest_empty(j_compress_ptr cinfo) { |
+ return false; |
+} |
+#endif |
}; |
#define JPEG_MARKER_ICC (JPEG_APP0 + 2) |
@@ -480,3 +481,106 @@ uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, |
} |
return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; |
} |
+ |
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
+#define JPEG_BLOCK_SIZE 1048576 |
+bool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource, |
+ uint8_t** dest_buf, |
+ FX_STRSIZE* dest_size) { |
+ struct jpeg_error_mgr jerr; |
+ jerr.error_exit = _error_do_nothing; |
+ jerr.emit_message = _error_do_nothing1; |
+ jerr.output_message = _error_do_nothing; |
+ jerr.format_message = _error_do_nothing2; |
+ jerr.reset_error_mgr = _error_do_nothing; |
+ |
+ struct jpeg_compress_struct cinfo; |
+ memset(&cinfo, 0, sizeof(cinfo)); |
+ cinfo.err = &jerr; |
+ jpeg_create_compress(&cinfo); |
+ int Bpp = pSource->GetBPP() / 8; |
+ uint32_t nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1; |
+ uint32_t pitch = pSource->GetPitch(); |
+ uint32_t width = pdfium::base::checked_cast<uint32_t>(pSource->GetWidth()); |
+ uint32_t height = pdfium::base::checked_cast<uint32_t>(pSource->GetHeight()); |
+ FX_SAFE_UINT32 safe_buf_len = width; |
+ safe_buf_len *= height; |
+ safe_buf_len *= nComponents; |
+ safe_buf_len += 1024; |
+ if (!safe_buf_len.IsValid()) |
+ return false; |
+ |
+ uint32_t dest_buf_length = safe_buf_len.ValueOrDie(); |
+ *dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); |
+ const int MIN_TRY_BUF_LEN = 1024; |
+ while (!(*dest_buf) && dest_buf_length > MIN_TRY_BUF_LEN) { |
+ dest_buf_length >>= 1; |
+ *dest_buf = FX_TryAlloc(uint8_t, dest_buf_length); |
+ } |
+ if (!(*dest_buf)) |
+ return false; |
+ |
+ struct jpeg_destination_mgr dest; |
+ dest.init_destination = _dest_do_nothing; |
+ dest.term_destination = _dest_do_nothing; |
+ dest.empty_output_buffer = _dest_empty; |
+ dest.next_output_byte = *dest_buf; |
+ dest.free_in_buffer = dest_buf_length; |
+ cinfo.dest = &dest; |
+ cinfo.image_width = width; |
+ cinfo.image_height = height; |
+ cinfo.input_components = nComponents; |
+ if (nComponents == 1) { |
+ cinfo.in_color_space = JCS_GRAYSCALE; |
+ } else if (nComponents == 3) { |
+ cinfo.in_color_space = JCS_RGB; |
+ } else { |
+ cinfo.in_color_space = JCS_CMYK; |
+ } |
+ uint8_t* line_buf = nullptr; |
+ if (nComponents > 1) |
+ line_buf = FX_Alloc2D(uint8_t, width, nComponents); |
+ |
+ jpeg_set_defaults(&cinfo); |
+ jpeg_start_compress(&cinfo, TRUE); |
+ JSAMPROW row_pointer[1]; |
+ JDIMENSION row; |
+ while (cinfo.next_scanline < cinfo.image_height) { |
+ const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline); |
+ if (nComponents > 1) { |
+ uint8_t* dest_scan = line_buf; |
+ if (nComponents == 3) { |
+ for (uint32_t i = 0; i < width; i++) { |
+ dest_scan[0] = src_scan[2]; |
+ dest_scan[1] = src_scan[1]; |
+ dest_scan[2] = src_scan[0]; |
+ dest_scan += 3; |
+ src_scan += Bpp; |
+ } |
+ } else { |
+ for (uint32_t i = 0; i < pitch; i++) { |
+ *dest_scan++ = ~*src_scan++; |
+ } |
+ } |
+ row_pointer[0] = line_buf; |
+ } else { |
+ row_pointer[0] = (uint8_t*)src_scan; |
+ } |
+ row = cinfo.next_scanline; |
+ jpeg_write_scanlines(&cinfo, row_pointer, 1); |
+ if (cinfo.next_scanline == row) { |
+ *dest_buf = |
+ FX_Realloc(uint8_t, *dest_buf, dest_buf_length + JPEG_BLOCK_SIZE); |
+ dest.next_output_byte = *dest_buf + dest_buf_length - dest.free_in_buffer; |
+ dest_buf_length += JPEG_BLOCK_SIZE; |
+ dest.free_in_buffer += JPEG_BLOCK_SIZE; |
+ } |
+ } |
+ jpeg_finish_compress(&cinfo); |
+ jpeg_destroy_compress(&cinfo); |
+ FX_Free(line_buf); |
+ *dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer; |
+ |
+ return true; |
+} |
+#endif |