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 |