Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / image / decoders / nsJPEGDecoder.cpp
blob95631e95f77bd9079b4120f01ddb4f844b568d1f
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ImageLogging.h" // Must appear first.
9 #include "nsJPEGDecoder.h"
11 #include <cstdint>
13 #include "imgFrame.h"
14 #include "Orientation.h"
15 #include "EXIF.h"
16 #include "SurfacePipeFactory.h"
18 #include "nspr.h"
19 #include "nsCRT.h"
20 #include "gfxColor.h"
22 #include "jerror.h"
24 #include "gfxPlatform.h"
25 #include "mozilla/EndianUtils.h"
26 #include "mozilla/gfx/Types.h"
27 #include "mozilla/Telemetry.h"
29 extern "C" {
30 #include "iccjpeg.h"
33 #if MOZ_BIG_ENDIAN()
34 # define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_XRGB
35 #else
36 # define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_BGRX
37 #endif
39 static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput,
40 int32_t aWidth);
42 using mozilla::gfx::SurfaceFormat;
44 namespace mozilla {
45 namespace image {
47 static mozilla::LazyLogModule sJPEGLog("JPEGDecoder");
49 static mozilla::LazyLogModule sJPEGDecoderAccountingLog(
50 "JPEGDecoderAccounting");
52 static qcms_profile* GetICCProfile(struct jpeg_decompress_struct& info) {
53 JOCTET* profilebuf;
54 uint32_t profileLength;
55 qcms_profile* profile = nullptr;
57 if (read_icc_profile(&info, &profilebuf, &profileLength)) {
58 profile = qcms_profile_from_memory(profilebuf, profileLength);
59 free(profilebuf);
62 return profile;
65 METHODDEF(void) init_source(j_decompress_ptr jd);
66 METHODDEF(boolean) fill_input_buffer(j_decompress_ptr jd);
67 METHODDEF(void) skip_input_data(j_decompress_ptr jd, long num_bytes);
68 METHODDEF(void) term_source(j_decompress_ptr jd);
69 METHODDEF(void) my_error_exit(j_common_ptr cinfo);
70 METHODDEF(void) progress_monitor(j_common_ptr info);
72 // Normal JFIF markers can't have more bytes than this.
73 #define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1)
75 nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
76 Decoder::DecodeStyle aDecodeStyle)
77 : Decoder(aImage),
78 mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA,
79 State::JPEG_DATA, SIZE_MAX),
80 Transition::TerminateSuccess()),
81 mProfile(nullptr),
82 mProfileLength(0),
83 mCMSLine(nullptr),
84 mDecodeStyle(aDecodeStyle) {
85 this->mErr.pub.error_exit = nullptr;
86 this->mErr.pub.emit_message = nullptr;
87 this->mErr.pub.output_message = nullptr;
88 this->mErr.pub.format_message = nullptr;
89 this->mErr.pub.reset_error_mgr = nullptr;
90 this->mErr.pub.msg_code = 0;
91 this->mErr.pub.trace_level = 0;
92 this->mErr.pub.num_warnings = 0;
93 this->mErr.pub.jpeg_message_table = nullptr;
94 this->mErr.pub.last_jpeg_message = 0;
95 this->mErr.pub.addon_message_table = nullptr;
96 this->mErr.pub.first_addon_message = 0;
97 this->mErr.pub.last_addon_message = 0;
98 mState = JPEG_HEADER;
99 mReading = true;
100 mImageData = nullptr;
102 mBytesToSkip = 0;
103 memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
104 memset(&mSourceMgr, 0, sizeof(mSourceMgr));
105 memset(&mProgressMgr, 0, sizeof(mProgressMgr));
106 mInfo.client_data = (void*)this;
108 mSegment = nullptr;
109 mSegmentLen = 0;
111 mBackBuffer = nullptr;
112 mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0;
114 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
115 ("nsJPEGDecoder::nsJPEGDecoder: Creating JPEG decoder %p", this));
118 nsJPEGDecoder::~nsJPEGDecoder() {
119 // Step 8: Release JPEG decompression object
120 mInfo.src = nullptr;
121 jpeg_destroy_decompress(&mInfo);
123 free(mBackBuffer);
124 mBackBuffer = nullptr;
126 delete[] mCMSLine;
128 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
129 ("nsJPEGDecoder::~nsJPEGDecoder: Destroying JPEG decoder %p", this));
132 Maybe<Telemetry::HistogramID> nsJPEGDecoder::SpeedHistogram() const {
133 return Some(Telemetry::IMAGE_DECODE_SPEED_JPEG);
136 nsresult nsJPEGDecoder::InitInternal() {
137 // We set up the normal JPEG error routines, then override error_exit.
138 mInfo.err = jpeg_std_error(&mErr.pub);
139 // mInfo.err = jpeg_std_error(&mErr.pub);
140 mErr.pub.error_exit = my_error_exit;
141 // Establish the setjmp return context for my_error_exit to use.
142 if (setjmp(mErr.setjmp_buffer)) {
143 // If we get here, the JPEG code has signaled an error, and initialization
144 // has failed.
145 return NS_ERROR_FAILURE;
148 // Step 1: allocate and initialize JPEG decompression object
149 jpeg_create_decompress(&mInfo);
150 // Set the source manager
151 mInfo.src = &mSourceMgr;
153 // Step 2: specify data source (eg, a file)
155 // Setup callback functions.
156 mSourceMgr.init_source = init_source;
157 mSourceMgr.fill_input_buffer = fill_input_buffer;
158 mSourceMgr.skip_input_data = skip_input_data;
159 mSourceMgr.resync_to_restart = jpeg_resync_to_restart;
160 mSourceMgr.term_source = term_source;
162 mInfo.mem->max_memory_to_use = static_cast<long>(
163 std::min<size_t>(SurfaceCache::MaximumCapacity(), LONG_MAX));
165 mProgressMgr.progress_monitor = &progress_monitor;
166 mInfo.progress = &mProgressMgr;
168 // Record app markers for ICC data
169 for (uint32_t m = 0; m < 16; m++) {
170 jpeg_save_markers(&mInfo, JPEG_APP0 + m, 0xFFFF);
173 return NS_OK;
176 nsresult nsJPEGDecoder::FinishInternal() {
177 // If we're not in any sort of error case, force our state to JPEG_DONE.
178 if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
179 (mState != JPEG_ERROR) && !IsMetadataDecode()) {
180 mState = JPEG_DONE;
183 return NS_OK;
186 LexerResult nsJPEGDecoder::DoDecode(SourceBufferIterator& aIterator,
187 IResumable* aOnResume) {
188 MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
190 return mLexer.Lex(aIterator, aOnResume,
191 [=](State aState, const char* aData, size_t aLength) {
192 switch (aState) {
193 case State::JPEG_DATA:
194 return ReadJPEGData(aData, aLength);
195 case State::FINISHED_JPEG_DATA:
196 return FinishedJPEGData();
198 MOZ_CRASH("Unknown State");
202 LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData(
203 const char* aData, size_t aLength) {
204 mSegment = reinterpret_cast<const JOCTET*>(aData);
205 mSegmentLen = aLength;
207 // Return here if there is a error within libjpeg.
208 nsresult error_code;
209 // This cast to nsresult makes sense because setjmp() returns whatever we
210 // passed to longjmp(), which was actually an nsresult. These error codes
211 // have been translated from libjpeg error codes, like so:
212 // JERR_OUT_OF_MEMORY => NS_ERROR_OUT_OF_MEMORY
213 // JERR_UNKNOWN_MARKER => NS_ERROR_ILLEGAL_VALUE
214 // JERR_SOF_UNSUPPORTED => NS_ERROR_INVALID_CONTENT_ENCODING
215 // <any other error> => NS_ERROR_FAILURE
216 if ((error_code = static_cast<nsresult>(setjmp(mErr.setjmp_buffer))) !=
217 NS_OK) {
218 bool fatal = true;
219 if (error_code == NS_ERROR_FAILURE) {
220 // Error due to corrupt data. Make sure that we don't feed any more data
221 // to libjpeg-turbo.
222 mState = JPEG_SINK_NON_JPEG_TRAILER;
223 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
224 ("} (setjmp returned NS_ERROR_FAILURE)"));
225 } else if (error_code == NS_ERROR_ILLEGAL_VALUE) {
226 // This is a recoverable error. Consume the marker and continue.
227 mInfo.unread_marker = 0;
228 fatal = false;
229 } else if (error_code == NS_ERROR_INVALID_CONTENT_ENCODING) {
230 // The content is encoding frames with a format that libjpeg can't handle.
231 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
232 ("} (setjmp returned NS_ERROR_INVALID_CONTENT_ENCODING)"));
233 // Check to see if we're in the done state, which indicates that we've
234 // already processed the main JPEG data.
235 bool inDoneState = (mState == JPEG_DONE);
236 // Whether we succeed or fail, we shouldn't send any more data.
237 mState = JPEG_SINK_NON_JPEG_TRAILER;
239 // If we're in the done state, we exit successfully and attempt to
240 // display the content we've already received. Otherwise, we fallthrough
241 // and treat this as a fatal error.
242 if (inDoneState) {
243 return Transition::TerminateSuccess();
245 } else {
246 // Error for another reason. (Possibly OOM.)
247 mState = JPEG_ERROR;
248 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
249 ("} (setjmp returned an error)"));
252 if (fatal) {
253 return Transition::TerminateFailure();
257 MOZ_LOG(sJPEGLog, LogLevel::Debug,
258 ("[this=%p] nsJPEGDecoder::Write -- processing JPEG data\n", this));
260 switch (mState) {
261 case JPEG_HEADER: {
262 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
263 "nsJPEGDecoder::Write -- entering JPEG_HEADER"
264 " case");
266 // Step 3: read file parameters with jpeg_read_header()
267 if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED) {
268 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
269 ("} (JPEG_SUSPENDED)"));
270 return Transition::ContinueUnbuffered(
271 State::JPEG_DATA); // I/O suspension
274 // Post our size to the superclass
275 EXIFData exif = ReadExifData();
276 PostSize(mInfo.image_width, mInfo.image_height, exif.orientation,
277 exif.resolution);
278 if (WantsFrameCount()) {
279 PostFrameCount(/* aFrameCount */ 1);
281 if (HasError()) {
282 // Setting the size led to an error.
283 mState = JPEG_ERROR;
284 return Transition::TerminateFailure();
287 // If we're doing a metadata decode, we're done.
288 if (IsMetadataDecode()) {
289 return Transition::TerminateSuccess();
292 // We're doing a full decode.
293 switch (mInfo.jpeg_color_space) {
294 case JCS_GRAYSCALE:
295 case JCS_RGB:
296 case JCS_YCbCr:
297 // By default, we will output directly to BGRA. If we need to apply
298 // special color transforms, this may change.
299 switch (SurfaceFormat::OS_RGBX) {
300 case SurfaceFormat::B8G8R8X8:
301 mInfo.out_color_space = JCS_EXT_BGRX;
302 break;
303 case SurfaceFormat::X8R8G8B8:
304 mInfo.out_color_space = JCS_EXT_XRGB;
305 break;
306 case SurfaceFormat::R8G8B8X8:
307 mInfo.out_color_space = JCS_EXT_RGBX;
308 break;
309 default:
310 mState = JPEG_ERROR;
311 return Transition::TerminateFailure();
313 break;
314 case JCS_CMYK:
315 case JCS_YCCK:
316 // libjpeg can convert from YCCK to CMYK, but not to XRGB.
317 mInfo.out_color_space = JCS_CMYK;
318 break;
319 default:
320 mState = JPEG_ERROR;
321 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
322 ("} (unknown colorspace (3))"));
323 return Transition::TerminateFailure();
326 if (mCMSMode != CMSMode::Off) {
327 if ((mInProfile = GetICCProfile(mInfo)) != nullptr &&
328 GetCMSOutputProfile()) {
329 uint32_t profileSpace = qcms_profile_get_color_space(mInProfile);
331 qcms_data_type outputType = gfxPlatform::GetCMSOSRGBAType();
332 Maybe<qcms_data_type> inputType;
333 if (profileSpace == icSigRgbData) {
334 // We can always color manage RGB profiles since it happens at the
335 // end of the pipeline.
336 inputType.emplace(outputType);
337 } else if (profileSpace == icSigGrayData &&
338 mInfo.jpeg_color_space == JCS_GRAYSCALE) {
339 // We can only color manage gray profiles if the original color
340 // space is grayscale. This means we must downscale after color
341 // management since the downscaler assumes BGRA.
342 mInfo.out_color_space = JCS_GRAYSCALE;
343 inputType.emplace(QCMS_DATA_GRAY_8);
346 #if 0
347 // We don't currently support CMYK profiles. The following
348 // code dealt with lcms types. Add something like this
349 // back when we gain support for CMYK.
351 // Adobe Photoshop writes YCCK/CMYK files with inverted data
352 if (mInfo.out_color_space == JCS_CMYK) {
353 type |= FLAVOR_SH(mInfo.saw_Adobe_marker ? 1 : 0);
355 #endif
357 if (inputType) {
358 // Calculate rendering intent.
359 int intent = gfxPlatform::GetRenderingIntent();
360 if (intent == -1) {
361 intent = qcms_profile_get_rendering_intent(mInProfile);
364 // Create the color management transform.
365 mTransform = qcms_transform_create(mInProfile, *inputType,
366 GetCMSOutputProfile(),
367 outputType, (qcms_intent)intent);
369 } else if (mCMSMode == CMSMode::All) {
370 mTransform = GetCMSsRGBTransform(SurfaceFormat::OS_RGBX);
374 // We don't want to use the pipe buffers directly because we don't want
375 // any reads on non-BGRA formatted data.
376 if (mInfo.out_color_space == JCS_GRAYSCALE ||
377 mInfo.out_color_space == JCS_CMYK) {
378 mCMSLine = new (std::nothrow) uint32_t[mInfo.image_width];
379 if (!mCMSLine) {
380 mState = JPEG_ERROR;
381 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
382 ("} (could allocate buffer for color conversion)"));
383 return Transition::TerminateFailure();
387 // Don't allocate a giant and superfluous memory buffer
388 // when not doing a progressive decode.
389 mInfo.buffered_image =
390 mDecodeStyle == PROGRESSIVE && jpeg_has_multiple_scans(&mInfo);
392 /* Used to set up image size so arrays can be allocated */
393 jpeg_calc_output_dimensions(&mInfo);
395 // We handle the transform outside the pipeline if we are outputting in
396 // grayscale, because the pipeline wants BGRA pixels, particularly the
397 // downscaling filter, so we can't handle it after downscaling as would
398 // be optimal.
399 qcms_transform* pipeTransform =
400 mInfo.out_color_space != JCS_GRAYSCALE ? mTransform : nullptr;
402 Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateReorientSurfacePipe(
403 this, Size(), OutputSize(), SurfaceFormat::OS_RGBX, pipeTransform,
404 GetOrientation(), SurfacePipeFlags());
405 if (!pipe) {
406 mState = JPEG_ERROR;
407 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
408 ("} (could not initialize surface pipe)"));
409 return Transition::TerminateFailure();
412 mPipe = std::move(*pipe);
414 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
415 (" JPEGDecoderAccounting: nsJPEGDecoder::"
416 "Write -- created image frame with %ux%u pixels",
417 mInfo.image_width, mInfo.image_height));
419 mState = JPEG_START_DECOMPRESS;
420 [[fallthrough]]; // to start decompressing.
423 case JPEG_START_DECOMPRESS: {
424 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
425 "nsJPEGDecoder::Write -- entering"
426 " JPEG_START_DECOMPRESS case");
427 // Step 4: set parameters for decompression
429 // FIXME -- Should reset dct_method and dither mode
430 // for final pass of progressive JPEG
432 mInfo.dct_method = JDCT_ISLOW;
433 mInfo.dither_mode = JDITHER_FS;
434 mInfo.do_fancy_upsampling = TRUE;
435 mInfo.enable_2pass_quant = FALSE;
436 mInfo.do_block_smoothing = TRUE;
438 // Step 5: Start decompressor
439 if (jpeg_start_decompress(&mInfo) == FALSE) {
440 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
441 ("} (I/O suspension after jpeg_start_decompress())"));
442 return Transition::ContinueUnbuffered(
443 State::JPEG_DATA); // I/O suspension
446 // If this is a progressive JPEG ...
447 mState = mInfo.buffered_image ? JPEG_DECOMPRESS_PROGRESSIVE
448 : JPEG_DECOMPRESS_SEQUENTIAL;
449 [[fallthrough]]; // to decompress sequential JPEG.
452 case JPEG_DECOMPRESS_SEQUENTIAL: {
453 if (mState == JPEG_DECOMPRESS_SEQUENTIAL) {
454 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
455 "nsJPEGDecoder::Write -- "
456 "JPEG_DECOMPRESS_SEQUENTIAL case");
458 switch (OutputScanlines()) {
459 case WriteState::NEED_MORE_DATA:
460 MOZ_LOG(
461 sJPEGDecoderAccountingLog, LogLevel::Debug,
462 ("} (I/O suspension after OutputScanlines() - SEQUENTIAL)"));
463 return Transition::ContinueUnbuffered(
464 State::JPEG_DATA); // I/O suspension
465 case WriteState::FINISHED:
466 NS_ASSERTION(mInfo.output_scanline == mInfo.output_height,
467 "We didn't process all of the data!");
468 mState = JPEG_DONE;
469 break;
470 case WriteState::FAILURE:
471 mState = JPEG_ERROR;
472 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
473 ("} (Error in pipeline from OutputScalines())"));
474 return Transition::TerminateFailure();
477 [[fallthrough]]; // to decompress progressive JPEG.
480 case JPEG_DECOMPRESS_PROGRESSIVE: {
481 if (mState == JPEG_DECOMPRESS_PROGRESSIVE) {
482 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
483 "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case");
484 auto AllComponentsSeen = [](jpeg_decompress_struct& info) {
485 bool all_components_seen = true;
486 if (info.coef_bits) {
487 for (int c = 0; c < info.num_components; ++c) {
488 bool current_component_seen = info.coef_bits[c][0] != -1;
489 all_components_seen &= current_component_seen;
492 return all_components_seen;
494 int status;
495 int scan_to_display_first = 0;
496 bool all_components_seen;
497 all_components_seen = AllComponentsSeen(mInfo);
498 if (all_components_seen) {
499 scan_to_display_first = mInfo.input_scan_number;
502 do {
503 status = jpeg_consume_input(&mInfo);
505 if (status == JPEG_REACHED_SOS || status == JPEG_REACHED_EOI ||
506 status == JPEG_SUSPENDED) {
507 // record the first scan where all components are present
508 all_components_seen = AllComponentsSeen(mInfo);
509 if (!scan_to_display_first && all_components_seen) {
510 scan_to_display_first = mInfo.input_scan_number;
513 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI));
515 if (!all_components_seen) {
516 return Transition::ContinueUnbuffered(
517 State::JPEG_DATA); // I/O suspension
519 // make sure we never try to access the non-exsitent scan 0
520 if (!scan_to_display_first) {
521 scan_to_display_first = 1;
523 while (mState != JPEG_DONE) {
524 if (mInfo.output_scanline == 0) {
525 int scan = mInfo.input_scan_number;
527 // if we haven't displayed anything yet (output_scan_number==0)
528 // and we have enough data for a complete scan, force output
529 // of the last full scan, but only if this last scan has seen
530 // DC data from all components
531 if ((mInfo.output_scan_number == 0) &&
532 (scan > scan_to_display_first) &&
533 (status != JPEG_REACHED_EOI)) {
534 scan--;
536 MOZ_ASSERT(scan > 0, "scan number to small!");
537 if (!jpeg_start_output(&mInfo, scan)) {
538 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
539 ("} (I/O suspension after jpeg_start_output() -"
540 " PROGRESSIVE)"));
541 return Transition::ContinueUnbuffered(
542 State::JPEG_DATA); // I/O suspension
546 if (mInfo.output_scanline == 0xffffff) {
547 mInfo.output_scanline = 0;
550 switch (OutputScanlines()) {
551 case WriteState::NEED_MORE_DATA:
552 if (mInfo.output_scanline == 0) {
553 // didn't manage to read any lines - flag so we don't call
554 // jpeg_start_output() multiple times for the same scan
555 mInfo.output_scanline = 0xffffff;
557 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
558 ("} (I/O suspension after OutputScanlines() - "
559 "PROGRESSIVE)"));
560 return Transition::ContinueUnbuffered(
561 State::JPEG_DATA); // I/O suspension
562 case WriteState::FINISHED:
563 NS_ASSERTION(mInfo.output_scanline == mInfo.output_height,
564 "We didn't process all of the data!");
566 if (!jpeg_finish_output(&mInfo)) {
567 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
568 ("} (I/O suspension after jpeg_finish_output() -"
569 " PROGRESSIVE)"));
570 return Transition::ContinueUnbuffered(
571 State::JPEG_DATA); // I/O suspension
574 if (jpeg_input_complete(&mInfo) &&
575 (mInfo.input_scan_number == mInfo.output_scan_number)) {
576 mState = JPEG_DONE;
577 } else {
578 mInfo.output_scanline = 0;
579 mPipe.ResetToFirstRow();
581 break;
582 case WriteState::FAILURE:
583 mState = JPEG_ERROR;
584 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
585 ("} (Error in pipeline from OutputScalines())"));
586 return Transition::TerminateFailure();
590 [[fallthrough]]; // to finish decompressing.
593 case JPEG_DONE: {
594 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
595 "nsJPEGDecoder::ProcessData -- entering"
596 " JPEG_DONE case");
598 // Step 7: Finish decompression
600 if (jpeg_finish_decompress(&mInfo) == FALSE) {
601 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
602 ("} (I/O suspension after jpeg_finish_decompress() - DONE)"));
603 return Transition::ContinueUnbuffered(
604 State::JPEG_DATA); // I/O suspension
607 // Make sure we don't feed any more data to libjpeg-turbo.
608 mState = JPEG_SINK_NON_JPEG_TRAILER;
610 // We're done.
611 return Transition::TerminateSuccess();
613 case JPEG_SINK_NON_JPEG_TRAILER:
614 MOZ_LOG(sJPEGLog, LogLevel::Debug,
615 ("[this=%p] nsJPEGDecoder::ProcessData -- entering"
616 " JPEG_SINK_NON_JPEG_TRAILER case\n",
617 this));
619 MOZ_ASSERT_UNREACHABLE(
620 "Should stop getting data after entering state "
621 "JPEG_SINK_NON_JPEG_TRAILER");
623 return Transition::TerminateSuccess();
625 case JPEG_ERROR:
626 MOZ_ASSERT_UNREACHABLE(
627 "Should stop getting data after entering state "
628 "JPEG_ERROR");
630 return Transition::TerminateFailure();
633 MOZ_ASSERT_UNREACHABLE("Escaped the JPEG decoder state machine");
634 return Transition::TerminateFailure();
635 } // namespace image
637 LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::FinishedJPEGData() {
638 // Since we set up an unbuffered read for SIZE_MAX bytes, if we actually read
639 // all that data something is really wrong.
640 MOZ_ASSERT_UNREACHABLE("Read the entire address space?");
641 return Transition::TerminateFailure();
644 EXIFData nsJPEGDecoder::ReadExifData() const {
645 jpeg_saved_marker_ptr marker;
647 // Locate the APP1 marker, where EXIF data is stored, in the marker list.
648 for (marker = mInfo.marker_list; marker != nullptr; marker = marker->next) {
649 if (marker->marker == JPEG_APP0 + 1) {
650 break;
654 // If we're at the end of the list, there's no EXIF data.
655 if (!marker) {
656 return EXIFData();
659 return EXIFParser::Parse(marker->data,
660 static_cast<uint32_t>(marker->data_length),
661 gfx::IntSize(mInfo.image_width, mInfo.image_height));
664 void nsJPEGDecoder::NotifyDone() {
665 PostFrameStop(Opacity::FULLY_OPAQUE);
666 PostDecodeDone();
669 WriteState nsJPEGDecoder::OutputScanlines() {
670 auto result = mPipe.WritePixelBlocks<uint32_t>(
671 [&](uint32_t* aPixelBlock, int32_t aBlockSize) {
672 JSAMPROW sampleRow = (JSAMPROW)(mCMSLine ? mCMSLine : aPixelBlock);
673 if (jpeg_read_scanlines(&mInfo, &sampleRow, 1) != 1) {
674 return std::make_tuple(/* aWritten */ 0,
675 Some(WriteState::NEED_MORE_DATA));
678 switch (mInfo.out_color_space) {
679 default:
680 // Already outputted directly to aPixelBlock as BGRA.
681 MOZ_ASSERT(!mCMSLine);
682 break;
683 case JCS_GRAYSCALE:
684 // The transform here does both color management, and converts the
685 // pixels from grayscale to BGRA. This is why we do it here, instead
686 // of using ColorManagementFilter in the SurfacePipe, because the
687 // other filters (e.g. DownscalingFilter) require BGRA pixels.
688 MOZ_ASSERT(mCMSLine);
689 qcms_transform_data(mTransform, mCMSLine, aPixelBlock,
690 mInfo.output_width);
691 break;
692 case JCS_CMYK:
693 // Convert from CMYK to BGRA
694 MOZ_ASSERT(mCMSLine);
695 cmyk_convert_bgra(mCMSLine, aPixelBlock, aBlockSize);
696 break;
699 return std::make_tuple(aBlockSize, Maybe<WriteState>());
702 Maybe<SurfaceInvalidRect> invalidRect = mPipe.TakeInvalidRect();
703 if (invalidRect) {
704 PostInvalidation(invalidRect->mInputSpaceRect,
705 Some(invalidRect->mOutputSpaceRect));
708 return result;
711 // Override the standard error method in the IJG JPEG decoder code.
712 METHODDEF(void)
713 my_error_exit(j_common_ptr cinfo) {
714 decoder_error_mgr* err = (decoder_error_mgr*)cinfo->err;
716 // Convert error to a browser error code
717 nsresult error_code;
718 switch (err->pub.msg_code) {
719 case JERR_OUT_OF_MEMORY:
720 error_code = NS_ERROR_OUT_OF_MEMORY;
721 break;
722 case JERR_UNKNOWN_MARKER:
723 error_code = NS_ERROR_ILLEGAL_VALUE;
724 break;
725 case JERR_SOF_UNSUPPORTED:
726 error_code = NS_ERROR_INVALID_CONTENT_ENCODING;
727 break;
728 default:
729 error_code = NS_ERROR_FAILURE;
732 #ifdef DEBUG
733 char buffer[JMSG_LENGTH_MAX];
735 // Create the message
736 (*err->pub.format_message)(cinfo, buffer);
738 fprintf(stderr, "JPEG decoding error:\n%s\n", buffer);
739 #endif
741 // Return control to the setjmp point. We pass an nsresult masquerading as
742 // an int, which works because the setjmp() caller casts it back.
743 longjmp(err->setjmp_buffer, static_cast<int>(error_code));
746 static void progress_monitor(j_common_ptr info) {
747 int scan = ((j_decompress_ptr)info)->input_scan_number;
748 // Progressive images with a very large number of scans can cause the decoder
749 // to hang. Here we use the progress monitor to abort on a very large number
750 // of scans. 1000 is arbitrary, but much larger than the number of scans we
751 // might expect in a normal image.
752 if (scan >= 1000) {
753 my_error_exit(info);
757 /*******************************************************************************
758 * This is the callback routine from the IJG JPEG library used to supply new
759 * data to the decompressor when its input buffer is exhausted. It juggles
760 * multiple buffers in an attempt to avoid unnecessary copying of input data.
762 * (A simpler scheme is possible: It's much easier to use only a single
763 * buffer; when fill_input_buffer() is called, move any unconsumed data
764 * (beyond the current pointer/count) down to the beginning of this buffer and
765 * then load new data into the remaining buffer space. This approach requires
766 * a little more data copying but is far easier to get right.)
768 * At any one time, the JPEG decompressor is either reading from the necko
769 * input buffer, which is volatile across top-level calls to the IJG library,
770 * or the "backtrack" buffer. The backtrack buffer contains the remaining
771 * unconsumed data from the necko buffer after parsing was suspended due
772 * to insufficient data in some previous call to the IJG library.
774 * When suspending, the decompressor will back up to a convenient restart
775 * point (typically the start of the current MCU). The variables
776 * next_input_byte & bytes_in_buffer indicate where the restart point will be
777 * if the current call returns FALSE. Data beyond this point must be
778 * rescanned after resumption, so it must be preserved in case the decompressor
779 * decides to backtrack.
781 * Returns:
782 * TRUE if additional data is available, FALSE if no data present and
783 * the JPEG library should therefore suspend processing of input stream
784 ******************************************************************************/
786 /******************************************************************************/
787 /* data source manager method */
788 /******************************************************************************/
790 /******************************************************************************/
791 /* data source manager method
792 Initialize source. This is called by jpeg_read_header() before any
793 data is actually read. May leave
794 bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
795 will occur immediately).
797 METHODDEF(void)
798 init_source(j_decompress_ptr jd) {}
800 /******************************************************************************/
801 /* data source manager method
802 Skip num_bytes worth of data. The buffer pointer and count should
803 be advanced over num_bytes input bytes, refilling the buffer as
804 needed. This is used to skip over a potentially large amount of
805 uninteresting data (such as an APPn marker). In some applications
806 it may be possible to optimize away the reading of the skipped data,
807 but it's not clear that being smart is worth much trouble; large
808 skips are uncommon. bytes_in_buffer may be zero on return.
809 A zero or negative skip count should be treated as a no-op.
811 METHODDEF(void)
812 skip_input_data(j_decompress_ptr jd, long num_bytes) {
813 struct jpeg_source_mgr* src = jd->src;
814 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
816 if (num_bytes > (long)src->bytes_in_buffer) {
817 // Can't skip it all right now until we get more data from
818 // network stream. Set things up so that fill_input_buffer
819 // will skip remaining amount.
820 decoder->mBytesToSkip = (size_t)num_bytes - src->bytes_in_buffer;
821 src->next_input_byte += src->bytes_in_buffer;
822 src->bytes_in_buffer = 0;
824 } else {
825 // Simple case. Just advance buffer pointer
827 src->bytes_in_buffer -= (size_t)num_bytes;
828 src->next_input_byte += num_bytes;
832 /******************************************************************************/
833 /* data source manager method
834 This is called whenever bytes_in_buffer has reached zero and more
835 data is wanted. In typical applications, it should read fresh data
836 into the buffer (ignoring the current state of next_input_byte and
837 bytes_in_buffer), reset the pointer & count to the start of the
838 buffer, and return TRUE indicating that the buffer has been reloaded.
839 It is not necessary to fill the buffer entirely, only to obtain at
840 least one more byte. bytes_in_buffer MUST be set to a positive value
841 if TRUE is returned. A FALSE return should only be used when I/O
842 suspension is desired.
844 METHODDEF(boolean)
845 fill_input_buffer(j_decompress_ptr jd) {
846 struct jpeg_source_mgr* src = jd->src;
847 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
849 if (decoder->mReading) {
850 const JOCTET* new_buffer = decoder->mSegment;
851 uint32_t new_buflen = decoder->mSegmentLen;
853 if (!new_buffer || new_buflen == 0) {
854 return false; // suspend
857 decoder->mSegmentLen = 0;
859 if (decoder->mBytesToSkip) {
860 if (decoder->mBytesToSkip < new_buflen) {
861 // All done skipping bytes; Return what's left.
862 new_buffer += decoder->mBytesToSkip;
863 new_buflen -= decoder->mBytesToSkip;
864 decoder->mBytesToSkip = 0;
865 } else {
866 // Still need to skip some more data in the future
867 decoder->mBytesToSkip -= (size_t)new_buflen;
868 return false; // suspend
872 decoder->mBackBufferUnreadLen = src->bytes_in_buffer;
874 src->next_input_byte = new_buffer;
875 src->bytes_in_buffer = (size_t)new_buflen;
876 decoder->mReading = false;
878 return true;
881 if (src->next_input_byte != decoder->mSegment) {
882 // Backtrack data has been permanently consumed.
883 decoder->mBackBufferUnreadLen = 0;
884 decoder->mBackBufferLen = 0;
887 // Save remainder of netlib buffer in backtrack buffer
888 const uint32_t new_backtrack_buflen =
889 src->bytes_in_buffer + decoder->mBackBufferLen;
891 // Make sure backtrack buffer is big enough to hold new data.
892 if (decoder->mBackBufferSize < new_backtrack_buflen) {
893 // Check for malformed MARKER segment lengths, before allocating space
894 // for it
895 if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) {
896 my_error_exit((j_common_ptr)(&decoder->mInfo));
899 // Round up to multiple of 256 bytes.
900 const size_t roundup_buflen = ((new_backtrack_buflen + 255) >> 8) << 8;
901 JOCTET* buf = (JOCTET*)realloc(decoder->mBackBuffer, roundup_buflen);
902 // Check for OOM
903 if (!buf) {
904 decoder->mInfo.err->msg_code = JERR_OUT_OF_MEMORY;
905 my_error_exit((j_common_ptr)(&decoder->mInfo));
907 decoder->mBackBuffer = buf;
908 decoder->mBackBufferSize = roundup_buflen;
911 // Ensure we actually have a backtrack buffer. Without it, then we know that
912 // there is no data to copy and bytes_in_buffer is already zero.
913 if (decoder->mBackBuffer) {
914 // Copy remainder of netlib segment into backtrack buffer.
915 memmove(decoder->mBackBuffer + decoder->mBackBufferLen,
916 src->next_input_byte, src->bytes_in_buffer);
917 } else {
918 MOZ_ASSERT(src->bytes_in_buffer == 0);
919 MOZ_ASSERT(decoder->mBackBufferLen == 0);
920 MOZ_ASSERT(decoder->mBackBufferUnreadLen == 0);
923 // Point to start of data to be rescanned.
924 src->next_input_byte = decoder->mBackBuffer + decoder->mBackBufferLen -
925 decoder->mBackBufferUnreadLen;
926 src->bytes_in_buffer += decoder->mBackBufferUnreadLen;
927 decoder->mBackBufferLen = (size_t)new_backtrack_buflen;
928 decoder->mReading = true;
930 return false;
933 /******************************************************************************/
934 /* data source manager method */
936 * Terminate source --- called by jpeg_finish_decompress() after all
937 * data has been read to clean up JPEG source manager. NOT called by
938 * jpeg_abort() or jpeg_destroy().
940 METHODDEF(void)
941 term_source(j_decompress_ptr jd) {
942 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
944 // This function shouldn't be called if we ran into an error we didn't
945 // recover from.
946 MOZ_ASSERT(decoder->mState != JPEG_ERROR,
947 "Calling term_source on a JPEG with mState == JPEG_ERROR!");
949 // Notify using a helper method to get around protectedness issues.
950 decoder->NotifyDone();
953 } // namespace image
954 } // namespace mozilla
956 ///*************** Inverted CMYK -> RGB conversion *************************
957 /// Input is (Inverted) CMYK stored as 4 bytes per pixel.
958 /// Output is RGB stored as 3 bytes per pixel.
959 /// @param aInput Points to row buffer containing the CMYK bytes for each pixel
960 /// in the row.
961 /// @param aOutput Points to row buffer to write BGRA to.
962 /// @param aWidth Number of pixels in the row.
963 static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput,
964 int32_t aWidth) {
965 uint8_t* input = reinterpret_cast<uint8_t*>(aInput);
967 for (int32_t i = 0; i < aWidth; ++i) {
968 // Source is 'Inverted CMYK', output is RGB.
969 // See: http://www.easyrgb.com/math.php?MATH=M12#text12
970 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
972 // From CMYK to CMY
973 // C = ( C * ( 1 - K ) + K )
974 // M = ( M * ( 1 - K ) + K )
975 // Y = ( Y * ( 1 - K ) + K )
977 // From Inverted CMYK to CMY is thus:
978 // C = ( (1-iC) * (1 - (1-iK)) + (1-iK) ) => 1 - iC*iK
979 // Same for M and Y
981 // Convert from CMY (0..1) to RGB (0..1)
982 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK
983 // G = 1 - M => 1 - (1 - iM*iK) => iM*iK
984 // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
986 // Convert from Inverted CMYK (0..255) to RGB (0..255)
987 const uint32_t iC = input[0];
988 const uint32_t iM = input[1];
989 const uint32_t iY = input[2];
990 const uint32_t iK = input[3];
992 const uint8_t r = iC * iK / 255;
993 const uint8_t g = iM * iK / 255;
994 const uint8_t b = iY * iK / 255;
996 *aOutput++ = (0xFF << mozilla::gfx::SurfaceFormatBit::OS_A) |
997 (r << mozilla::gfx::SurfaceFormatBit::OS_R) |
998 (g << mozilla::gfx::SurfaceFormatBit::OS_G) |
999 (b << mozilla::gfx::SurfaceFormatBit::OS_B);
1000 input += 4;