Bug 1686838 [wpt PR 27194] - Update wpt metadata, a=testonly
[gecko.git] / image / decoders / nsJPEGDecoder.cpp
blobc2a27ba3aff618a129c0776ec9630798e1a05b25
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);
71 // Normal JFIF markers can't have more bytes than this.
72 #define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1)
74 nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
75 Decoder::DecodeStyle aDecodeStyle)
76 : Decoder(aImage),
77 mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA,
78 State::JPEG_DATA, SIZE_MAX),
79 Transition::TerminateSuccess()),
80 mProfile(nullptr),
81 mProfileLength(0),
82 mCMSLine(nullptr),
83 mDecodeStyle(aDecodeStyle) {
84 this->mErr.pub.error_exit = nullptr;
85 this->mErr.pub.emit_message = nullptr;
86 this->mErr.pub.output_message = nullptr;
87 this->mErr.pub.format_message = nullptr;
88 this->mErr.pub.reset_error_mgr = nullptr;
89 this->mErr.pub.msg_code = 0;
90 this->mErr.pub.trace_level = 0;
91 this->mErr.pub.num_warnings = 0;
92 this->mErr.pub.jpeg_message_table = nullptr;
93 this->mErr.pub.last_jpeg_message = 0;
94 this->mErr.pub.addon_message_table = nullptr;
95 this->mErr.pub.first_addon_message = 0;
96 this->mErr.pub.last_addon_message = 0;
97 mState = JPEG_HEADER;
98 mReading = true;
99 mImageData = nullptr;
101 mBytesToSkip = 0;
102 memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
103 memset(&mSourceMgr, 0, sizeof(mSourceMgr));
104 mInfo.client_data = (void*)this;
106 mSegment = nullptr;
107 mSegmentLen = 0;
109 mBackBuffer = nullptr;
110 mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0;
112 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
113 ("nsJPEGDecoder::nsJPEGDecoder: Creating JPEG decoder %p", this));
116 nsJPEGDecoder::~nsJPEGDecoder() {
117 // Step 8: Release JPEG decompression object
118 mInfo.src = nullptr;
119 jpeg_destroy_decompress(&mInfo);
121 free(mBackBuffer);
122 mBackBuffer = nullptr;
124 delete[] mCMSLine;
126 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
127 ("nsJPEGDecoder::~nsJPEGDecoder: Destroying JPEG decoder %p", this));
130 Maybe<Telemetry::HistogramID> nsJPEGDecoder::SpeedHistogram() const {
131 return Some(Telemetry::IMAGE_DECODE_SPEED_JPEG);
134 nsresult nsJPEGDecoder::InitInternal() {
135 // We set up the normal JPEG error routines, then override error_exit.
136 mInfo.err = jpeg_std_error(&mErr.pub);
137 // mInfo.err = jpeg_std_error(&mErr.pub);
138 mErr.pub.error_exit = my_error_exit;
139 // Establish the setjmp return context for my_error_exit to use.
140 if (setjmp(mErr.setjmp_buffer)) {
141 // If we get here, the JPEG code has signaled an error, and initialization
142 // has failed.
143 return NS_ERROR_FAILURE;
146 // Step 1: allocate and initialize JPEG decompression object
147 jpeg_create_decompress(&mInfo);
148 // Set the source manager
149 mInfo.src = &mSourceMgr;
151 // Step 2: specify data source (eg, a file)
153 // Setup callback functions.
154 mSourceMgr.init_source = init_source;
155 mSourceMgr.fill_input_buffer = fill_input_buffer;
156 mSourceMgr.skip_input_data = skip_input_data;
157 mSourceMgr.resync_to_restart = jpeg_resync_to_restart;
158 mSourceMgr.term_source = term_source;
160 // Record app markers for ICC data
161 for (uint32_t m = 0; m < 16; m++) {
162 jpeg_save_markers(&mInfo, JPEG_APP0 + m, 0xFFFF);
165 return NS_OK;
168 nsresult nsJPEGDecoder::FinishInternal() {
169 // If we're not in any sort of error case, force our state to JPEG_DONE.
170 if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
171 (mState != JPEG_ERROR) && !IsMetadataDecode()) {
172 mState = JPEG_DONE;
175 return NS_OK;
178 LexerResult nsJPEGDecoder::DoDecode(SourceBufferIterator& aIterator,
179 IResumable* aOnResume) {
180 MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
182 return mLexer.Lex(aIterator, aOnResume,
183 [=](State aState, const char* aData, size_t aLength) {
184 switch (aState) {
185 case State::JPEG_DATA:
186 return ReadJPEGData(aData, aLength);
187 case State::FINISHED_JPEG_DATA:
188 return FinishedJPEGData();
190 MOZ_CRASH("Unknown State");
194 LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData(
195 const char* aData, size_t aLength) {
196 mSegment = reinterpret_cast<const JOCTET*>(aData);
197 mSegmentLen = aLength;
199 // Return here if there is a fatal error within libjpeg.
200 nsresult error_code;
201 // This cast to nsresult makes sense because setjmp() returns whatever we
202 // passed to longjmp(), which was actually an nsresult.
203 if ((error_code = static_cast<nsresult>(setjmp(mErr.setjmp_buffer))) !=
204 NS_OK) {
205 if (error_code == NS_ERROR_FAILURE) {
206 // Error due to corrupt data. Make sure that we don't feed any more data
207 // to libjpeg-turbo.
208 mState = JPEG_SINK_NON_JPEG_TRAILER;
209 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
210 ("} (setjmp returned NS_ERROR_FAILURE)"));
211 } else {
212 // Error for another reason. (Possibly OOM.)
213 mState = JPEG_ERROR;
214 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
215 ("} (setjmp returned an error)"));
218 return Transition::TerminateFailure();
221 MOZ_LOG(sJPEGLog, LogLevel::Debug,
222 ("[this=%p] nsJPEGDecoder::Write -- processing JPEG data\n", this));
224 switch (mState) {
225 case JPEG_HEADER: {
226 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
227 "nsJPEGDecoder::Write -- entering JPEG_HEADER"
228 " case");
230 // Step 3: read file parameters with jpeg_read_header()
231 if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED) {
232 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
233 ("} (JPEG_SUSPENDED)"));
234 return Transition::ContinueUnbuffered(
235 State::JPEG_DATA); // I/O suspension
238 // Post our size to the superclass
239 PostSize(mInfo.image_width, mInfo.image_height,
240 ReadOrientationFromEXIF());
241 if (HasError()) {
242 // Setting the size led to an error.
243 mState = JPEG_ERROR;
244 return Transition::TerminateFailure();
247 // If we're doing a metadata decode, we're done.
248 if (IsMetadataDecode()) {
249 return Transition::TerminateSuccess();
252 // We're doing a full decode.
253 switch (mInfo.jpeg_color_space) {
254 case JCS_GRAYSCALE:
255 case JCS_RGB:
256 case JCS_YCbCr:
257 // By default, we will output directly to BGRA. If we need to apply
258 // special color transforms, this may change.
259 switch (SurfaceFormat::OS_RGBX) {
260 case SurfaceFormat::B8G8R8X8:
261 mInfo.out_color_space = JCS_EXT_BGRX;
262 break;
263 case SurfaceFormat::X8R8G8B8:
264 mInfo.out_color_space = JCS_EXT_XRGB;
265 break;
266 case SurfaceFormat::R8G8B8X8:
267 mInfo.out_color_space = JCS_EXT_RGBX;
268 break;
269 default:
270 mState = JPEG_ERROR;
271 return Transition::TerminateFailure();
273 break;
274 case JCS_CMYK:
275 case JCS_YCCK:
276 // libjpeg can convert from YCCK to CMYK, but not to XRGB.
277 mInfo.out_color_space = JCS_CMYK;
278 break;
279 default:
280 mState = JPEG_ERROR;
281 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
282 ("} (unknown colorspace (3))"));
283 return Transition::TerminateFailure();
286 if (mCMSMode != eCMSMode_Off) {
287 if ((mInProfile = GetICCProfile(mInfo)) != nullptr &&
288 GetCMSOutputProfile()) {
289 uint32_t profileSpace = qcms_profile_get_color_space(mInProfile);
291 qcms_data_type outputType = gfxPlatform::GetCMSOSRGBAType();
292 Maybe<qcms_data_type> inputType;
293 if (profileSpace == icSigRgbData) {
294 // We can always color manage RGB profiles since it happens at the
295 // end of the pipeline.
296 inputType.emplace(outputType);
297 } else if (profileSpace == icSigGrayData &&
298 mInfo.jpeg_color_space == JCS_GRAYSCALE) {
299 // We can only color manage gray profiles if the original color
300 // space is grayscale. This means we must downscale after color
301 // management since the downscaler assumes BGRA.
302 mInfo.out_color_space = JCS_GRAYSCALE;
303 inputType.emplace(QCMS_DATA_GRAY_8);
306 #if 0
307 // We don't currently support CMYK profiles. The following
308 // code dealt with lcms types. Add something like this
309 // back when we gain support for CMYK.
311 // Adobe Photoshop writes YCCK/CMYK files with inverted data
312 if (mInfo.out_color_space == JCS_CMYK) {
313 type |= FLAVOR_SH(mInfo.saw_Adobe_marker ? 1 : 0);
315 #endif
317 if (inputType) {
318 // Calculate rendering intent.
319 int intent = gfxPlatform::GetRenderingIntent();
320 if (intent == -1) {
321 intent = qcms_profile_get_rendering_intent(mInProfile);
324 // Create the color management transform.
325 mTransform = qcms_transform_create(mInProfile, *inputType,
326 GetCMSOutputProfile(),
327 outputType, (qcms_intent)intent);
329 } else if (mCMSMode == eCMSMode_All) {
330 mTransform = GetCMSsRGBTransform(SurfaceFormat::OS_RGBX);
334 // We don't want to use the pipe buffers directly because we don't want
335 // any reads on non-BGRA formatted data.
336 if (mInfo.out_color_space == JCS_GRAYSCALE ||
337 mInfo.out_color_space == JCS_CMYK) {
338 mCMSLine = new (std::nothrow) uint32_t[mInfo.image_width];
339 if (!mCMSLine) {
340 mState = JPEG_ERROR;
341 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
342 ("} (could allocate buffer for color conversion)"));
343 return Transition::TerminateFailure();
347 // Don't allocate a giant and superfluous memory buffer
348 // when not doing a progressive decode.
349 mInfo.buffered_image =
350 mDecodeStyle == PROGRESSIVE && jpeg_has_multiple_scans(&mInfo);
352 /* Used to set up image size so arrays can be allocated */
353 jpeg_calc_output_dimensions(&mInfo);
355 // We handle the transform outside the pipeline if we are outputting in
356 // grayscale, because the pipeline wants BGRA pixels, particularly the
357 // downscaling filter, so we can't handle it after downscaling as would
358 // be optimal.
359 qcms_transform* pipeTransform =
360 mInfo.out_color_space != JCS_GRAYSCALE ? mTransform : nullptr;
362 Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
363 this, Size(), OutputSize(), FullFrame(), SurfaceFormat::OS_RGBX,
364 SurfaceFormat::OS_RGBX, Nothing(), pipeTransform, SurfacePipeFlags());
365 if (!pipe) {
366 mState = JPEG_ERROR;
367 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
368 ("} (could not initialize surface pipe)"));
369 return Transition::TerminateFailure();
372 mPipe = std::move(*pipe);
374 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
375 (" JPEGDecoderAccounting: nsJPEGDecoder::"
376 "Write -- created image frame with %ux%u pixels",
377 mInfo.image_width, mInfo.image_height));
379 mState = JPEG_START_DECOMPRESS;
380 [[fallthrough]]; // to start decompressing.
383 case JPEG_START_DECOMPRESS: {
384 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
385 "nsJPEGDecoder::Write -- entering"
386 " JPEG_START_DECOMPRESS case");
387 // Step 4: set parameters for decompression
389 // FIXME -- Should reset dct_method and dither mode
390 // for final pass of progressive JPEG
392 mInfo.dct_method = JDCT_ISLOW;
393 mInfo.dither_mode = JDITHER_FS;
394 mInfo.do_fancy_upsampling = TRUE;
395 mInfo.enable_2pass_quant = FALSE;
396 mInfo.do_block_smoothing = TRUE;
398 // Step 5: Start decompressor
399 if (jpeg_start_decompress(&mInfo) == FALSE) {
400 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
401 ("} (I/O suspension after jpeg_start_decompress())"));
402 return Transition::ContinueUnbuffered(
403 State::JPEG_DATA); // I/O suspension
406 // If this is a progressive JPEG ...
407 mState = mInfo.buffered_image ? JPEG_DECOMPRESS_PROGRESSIVE
408 : JPEG_DECOMPRESS_SEQUENTIAL;
409 [[fallthrough]]; // to decompress sequential JPEG.
412 case JPEG_DECOMPRESS_SEQUENTIAL: {
413 if (mState == JPEG_DECOMPRESS_SEQUENTIAL) {
414 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
415 "nsJPEGDecoder::Write -- "
416 "JPEG_DECOMPRESS_SEQUENTIAL case");
418 switch (OutputScanlines()) {
419 case WriteState::NEED_MORE_DATA:
420 MOZ_LOG(
421 sJPEGDecoderAccountingLog, LogLevel::Debug,
422 ("} (I/O suspension after OutputScanlines() - SEQUENTIAL)"));
423 return Transition::ContinueUnbuffered(
424 State::JPEG_DATA); // I/O suspension
425 case WriteState::FINISHED:
426 NS_ASSERTION(mInfo.output_scanline == mInfo.output_height,
427 "We didn't process all of the data!");
428 mState = JPEG_DONE;
429 break;
430 case WriteState::FAILURE:
431 mState = JPEG_ERROR;
432 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
433 ("} (Error in pipeline from OutputScalines())"));
434 return Transition::TerminateFailure();
437 [[fallthrough]]; // to decompress progressive JPEG.
440 case JPEG_DECOMPRESS_PROGRESSIVE: {
441 if (mState == JPEG_DECOMPRESS_PROGRESSIVE) {
442 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
443 "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case");
444 auto AllComponentsSeen = [](jpeg_decompress_struct& mInfo) {
445 bool all_components_seen = true;
446 if (mInfo.coef_bits) {
447 for (int c = 0; c < mInfo.num_components; ++c) {
448 bool current_component_seen = mInfo.coef_bits[c][0] != -1;
449 all_components_seen &= current_component_seen;
452 return all_components_seen;
454 int status;
455 int scan_to_display_first = 0;
456 bool all_components_seen;
457 all_components_seen = AllComponentsSeen(mInfo);
458 if (all_components_seen) {
459 scan_to_display_first = mInfo.input_scan_number;
462 do {
463 status = jpeg_consume_input(&mInfo);
465 if (status == JPEG_REACHED_SOS || status == JPEG_REACHED_EOI ||
466 status == JPEG_SUSPENDED) {
467 // record the first scan where all components are present
468 all_components_seen = AllComponentsSeen(mInfo);
469 if (!scan_to_display_first && all_components_seen) {
470 scan_to_display_first = mInfo.input_scan_number;
473 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI));
475 if (!all_components_seen) {
476 return Transition::ContinueUnbuffered(
477 State::JPEG_DATA); // I/O suspension
479 // make sure we never try to access the non-exsitent scan 0
480 if (!scan_to_display_first) {
481 scan_to_display_first = 1;
483 while (mState != JPEG_DONE) {
484 if (mInfo.output_scanline == 0) {
485 int scan = mInfo.input_scan_number;
487 // if we haven't displayed anything yet (output_scan_number==0)
488 // and we have enough data for a complete scan, force output
489 // of the last full scan, but only if this last scan has seen
490 // DC data from all components
491 if ((mInfo.output_scan_number == 0) &&
492 (scan > scan_to_display_first) &&
493 (status != JPEG_REACHED_EOI)) {
494 scan--;
496 MOZ_ASSERT(scan > 0, "scan number to small!");
497 if (!jpeg_start_output(&mInfo, scan)) {
498 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
499 ("} (I/O suspension after jpeg_start_output() -"
500 " PROGRESSIVE)"));
501 return Transition::ContinueUnbuffered(
502 State::JPEG_DATA); // I/O suspension
506 if (mInfo.output_scanline == 0xffffff) {
507 mInfo.output_scanline = 0;
510 switch (OutputScanlines()) {
511 case WriteState::NEED_MORE_DATA:
512 if (mInfo.output_scanline == 0) {
513 // didn't manage to read any lines - flag so we don't call
514 // jpeg_start_output() multiple times for the same scan
515 mInfo.output_scanline = 0xffffff;
517 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
518 ("} (I/O suspension after OutputScanlines() - "
519 "PROGRESSIVE)"));
520 return Transition::ContinueUnbuffered(
521 State::JPEG_DATA); // I/O suspension
522 case WriteState::FINISHED:
523 NS_ASSERTION(mInfo.output_scanline == mInfo.output_height,
524 "We didn't process all of the data!");
526 if (!jpeg_finish_output(&mInfo)) {
527 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
528 ("} (I/O suspension after jpeg_finish_output() -"
529 " PROGRESSIVE)"));
530 return Transition::ContinueUnbuffered(
531 State::JPEG_DATA); // I/O suspension
534 if (jpeg_input_complete(&mInfo) &&
535 (mInfo.input_scan_number == mInfo.output_scan_number)) {
536 mState = JPEG_DONE;
537 } else {
538 mInfo.output_scanline = 0;
539 mPipe.ResetToFirstRow();
541 break;
542 case WriteState::FAILURE:
543 mState = JPEG_ERROR;
544 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
545 ("} (Error in pipeline from OutputScalines())"));
546 return Transition::TerminateFailure();
550 [[fallthrough]]; // to finish decompressing.
553 case JPEG_DONE: {
554 LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
555 "nsJPEGDecoder::ProcessData -- entering"
556 " JPEG_DONE case");
558 // Step 7: Finish decompression
560 if (jpeg_finish_decompress(&mInfo) == FALSE) {
561 MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
562 ("} (I/O suspension after jpeg_finish_decompress() - DONE)"));
563 return Transition::ContinueUnbuffered(
564 State::JPEG_DATA); // I/O suspension
567 // Make sure we don't feed any more data to libjpeg-turbo.
568 mState = JPEG_SINK_NON_JPEG_TRAILER;
570 // We're done.
571 return Transition::TerminateSuccess();
573 case JPEG_SINK_NON_JPEG_TRAILER:
574 MOZ_LOG(sJPEGLog, LogLevel::Debug,
575 ("[this=%p] nsJPEGDecoder::ProcessData -- entering"
576 " JPEG_SINK_NON_JPEG_TRAILER case\n",
577 this));
579 MOZ_ASSERT_UNREACHABLE(
580 "Should stop getting data after entering state "
581 "JPEG_SINK_NON_JPEG_TRAILER");
583 return Transition::TerminateSuccess();
585 case JPEG_ERROR:
586 MOZ_ASSERT_UNREACHABLE(
587 "Should stop getting data after entering state "
588 "JPEG_ERROR");
590 return Transition::TerminateFailure();
593 MOZ_ASSERT_UNREACHABLE("Escaped the JPEG decoder state machine");
594 return Transition::TerminateFailure();
595 } // namespace image
597 LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::FinishedJPEGData() {
598 // Since we set up an unbuffered read for SIZE_MAX bytes, if we actually read
599 // all that data something is really wrong.
600 MOZ_ASSERT_UNREACHABLE("Read the entire address space?");
601 return Transition::TerminateFailure();
604 Orientation nsJPEGDecoder::ReadOrientationFromEXIF() {
605 jpeg_saved_marker_ptr marker;
607 // Locate the APP1 marker, where EXIF data is stored, in the marker list.
608 for (marker = mInfo.marker_list; marker != nullptr; marker = marker->next) {
609 if (marker->marker == JPEG_APP0 + 1) {
610 break;
614 // If we're at the end of the list, there's no EXIF data.
615 if (!marker) {
616 return Orientation();
619 // Extract the orientation information.
620 EXIFData exif = EXIFParser::Parse(marker->data,
621 static_cast<uint32_t>(marker->data_length));
622 return exif.orientation;
625 void nsJPEGDecoder::NotifyDone() {
626 PostFrameStop(Opacity::FULLY_OPAQUE);
627 PostDecodeDone();
630 WriteState nsJPEGDecoder::OutputScanlines() {
631 auto result = mPipe.WritePixelBlocks<uint32_t>(
632 [&](uint32_t* aPixelBlock, int32_t aBlockSize) {
633 JSAMPROW sampleRow = (JSAMPROW)(mCMSLine ? mCMSLine : aPixelBlock);
634 if (jpeg_read_scanlines(&mInfo, &sampleRow, 1) != 1) {
635 return MakeTuple(/* aWritten */ 0, Some(WriteState::NEED_MORE_DATA));
638 switch (mInfo.out_color_space) {
639 default:
640 // Already outputted directly to aPixelBlock as BGRA.
641 MOZ_ASSERT(!mCMSLine);
642 break;
643 case JCS_GRAYSCALE:
644 // The transform here does both color management, and converts the
645 // pixels from grayscale to BGRA. This is why we do it here, instead
646 // of using ColorManagementFilter in the SurfacePipe, because the
647 // other filters (e.g. DownscalingFilter) require BGRA pixels.
648 MOZ_ASSERT(mCMSLine);
649 qcms_transform_data(mTransform, mCMSLine, aPixelBlock,
650 mInfo.output_width);
651 break;
652 case JCS_CMYK:
653 // Convert from CMYK to BGRA
654 MOZ_ASSERT(mCMSLine);
655 cmyk_convert_bgra(mCMSLine, aPixelBlock, aBlockSize);
656 break;
659 return MakeTuple(aBlockSize, Maybe<WriteState>());
662 Maybe<SurfaceInvalidRect> invalidRect = mPipe.TakeInvalidRect();
663 if (invalidRect) {
664 PostInvalidation(invalidRect->mInputSpaceRect,
665 Some(invalidRect->mOutputSpaceRect));
668 return result;
671 // Override the standard error method in the IJG JPEG decoder code.
672 METHODDEF(void)
673 my_error_exit(j_common_ptr cinfo) {
674 decoder_error_mgr* err = (decoder_error_mgr*)cinfo->err;
676 // Convert error to a browser error code
677 nsresult error_code = err->pub.msg_code == JERR_OUT_OF_MEMORY
678 ? NS_ERROR_OUT_OF_MEMORY
679 : NS_ERROR_FAILURE;
681 #ifdef DEBUG
682 char buffer[JMSG_LENGTH_MAX];
684 // Create the message
685 (*err->pub.format_message)(cinfo, buffer);
687 fprintf(stderr, "JPEG decoding error:\n%s\n", buffer);
688 #endif
690 // Return control to the setjmp point. We pass an nsresult masquerading as
691 // an int, which works because the setjmp() caller casts it back.
692 longjmp(err->setjmp_buffer, static_cast<int>(error_code));
695 /*******************************************************************************
696 * This is the callback routine from the IJG JPEG library used to supply new
697 * data to the decompressor when its input buffer is exhausted. It juggles
698 * multiple buffers in an attempt to avoid unnecessary copying of input data.
700 * (A simpler scheme is possible: It's much easier to use only a single
701 * buffer; when fill_input_buffer() is called, move any unconsumed data
702 * (beyond the current pointer/count) down to the beginning of this buffer and
703 * then load new data into the remaining buffer space. This approach requires
704 * a little more data copying but is far easier to get right.)
706 * At any one time, the JPEG decompressor is either reading from the necko
707 * input buffer, which is volatile across top-level calls to the IJG library,
708 * or the "backtrack" buffer. The backtrack buffer contains the remaining
709 * unconsumed data from the necko buffer after parsing was suspended due
710 * to insufficient data in some previous call to the IJG library.
712 * When suspending, the decompressor will back up to a convenient restart
713 * point (typically the start of the current MCU). The variables
714 * next_input_byte & bytes_in_buffer indicate where the restart point will be
715 * if the current call returns FALSE. Data beyond this point must be
716 * rescanned after resumption, so it must be preserved in case the decompressor
717 * decides to backtrack.
719 * Returns:
720 * TRUE if additional data is available, FALSE if no data present and
721 * the JPEG library should therefore suspend processing of input stream
722 ******************************************************************************/
724 /******************************************************************************/
725 /* data source manager method */
726 /******************************************************************************/
728 /******************************************************************************/
729 /* data source manager method
730 Initialize source. This is called by jpeg_read_header() before any
731 data is actually read. May leave
732 bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
733 will occur immediately).
735 METHODDEF(void)
736 init_source(j_decompress_ptr jd) {}
738 /******************************************************************************/
739 /* data source manager method
740 Skip num_bytes worth of data. The buffer pointer and count should
741 be advanced over num_bytes input bytes, refilling the buffer as
742 needed. This is used to skip over a potentially large amount of
743 uninteresting data (such as an APPn marker). In some applications
744 it may be possible to optimize away the reading of the skipped data,
745 but it's not clear that being smart is worth much trouble; large
746 skips are uncommon. bytes_in_buffer may be zero on return.
747 A zero or negative skip count should be treated as a no-op.
749 METHODDEF(void)
750 skip_input_data(j_decompress_ptr jd, long num_bytes) {
751 struct jpeg_source_mgr* src = jd->src;
752 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
754 if (num_bytes > (long)src->bytes_in_buffer) {
755 // Can't skip it all right now until we get more data from
756 // network stream. Set things up so that fill_input_buffer
757 // will skip remaining amount.
758 decoder->mBytesToSkip = (size_t)num_bytes - src->bytes_in_buffer;
759 src->next_input_byte += src->bytes_in_buffer;
760 src->bytes_in_buffer = 0;
762 } else {
763 // Simple case. Just advance buffer pointer
765 src->bytes_in_buffer -= (size_t)num_bytes;
766 src->next_input_byte += num_bytes;
770 /******************************************************************************/
771 /* data source manager method
772 This is called whenever bytes_in_buffer has reached zero and more
773 data is wanted. In typical applications, it should read fresh data
774 into the buffer (ignoring the current state of next_input_byte and
775 bytes_in_buffer), reset the pointer & count to the start of the
776 buffer, and return TRUE indicating that the buffer has been reloaded.
777 It is not necessary to fill the buffer entirely, only to obtain at
778 least one more byte. bytes_in_buffer MUST be set to a positive value
779 if TRUE is returned. A FALSE return should only be used when I/O
780 suspension is desired.
782 METHODDEF(boolean)
783 fill_input_buffer(j_decompress_ptr jd) {
784 struct jpeg_source_mgr* src = jd->src;
785 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
787 if (decoder->mReading) {
788 const JOCTET* new_buffer = decoder->mSegment;
789 uint32_t new_buflen = decoder->mSegmentLen;
791 if (!new_buffer || new_buflen == 0) {
792 return false; // suspend
795 decoder->mSegmentLen = 0;
797 if (decoder->mBytesToSkip) {
798 if (decoder->mBytesToSkip < new_buflen) {
799 // All done skipping bytes; Return what's left.
800 new_buffer += decoder->mBytesToSkip;
801 new_buflen -= decoder->mBytesToSkip;
802 decoder->mBytesToSkip = 0;
803 } else {
804 // Still need to skip some more data in the future
805 decoder->mBytesToSkip -= (size_t)new_buflen;
806 return false; // suspend
810 decoder->mBackBufferUnreadLen = src->bytes_in_buffer;
812 src->next_input_byte = new_buffer;
813 src->bytes_in_buffer = (size_t)new_buflen;
814 decoder->mReading = false;
816 return true;
819 if (src->next_input_byte != decoder->mSegment) {
820 // Backtrack data has been permanently consumed.
821 decoder->mBackBufferUnreadLen = 0;
822 decoder->mBackBufferLen = 0;
825 // Save remainder of netlib buffer in backtrack buffer
826 const uint32_t new_backtrack_buflen =
827 src->bytes_in_buffer + decoder->mBackBufferLen;
829 // Make sure backtrack buffer is big enough to hold new data.
830 if (decoder->mBackBufferSize < new_backtrack_buflen) {
831 // Check for malformed MARKER segment lengths, before allocating space
832 // for it
833 if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) {
834 my_error_exit((j_common_ptr)(&decoder->mInfo));
837 // Round up to multiple of 256 bytes.
838 const size_t roundup_buflen = ((new_backtrack_buflen + 255) >> 8) << 8;
839 JOCTET* buf = (JOCTET*)realloc(decoder->mBackBuffer, roundup_buflen);
840 // Check for OOM
841 if (!buf) {
842 decoder->mInfo.err->msg_code = JERR_OUT_OF_MEMORY;
843 my_error_exit((j_common_ptr)(&decoder->mInfo));
845 decoder->mBackBuffer = buf;
846 decoder->mBackBufferSize = roundup_buflen;
849 // Ensure we actually have a backtrack buffer. Without it, then we know that
850 // there is no data to copy and bytes_in_buffer is already zero.
851 if (decoder->mBackBuffer) {
852 // Copy remainder of netlib segment into backtrack buffer.
853 memmove(decoder->mBackBuffer + decoder->mBackBufferLen,
854 src->next_input_byte, src->bytes_in_buffer);
855 } else {
856 MOZ_ASSERT(src->bytes_in_buffer == 0);
857 MOZ_ASSERT(decoder->mBackBufferLen == 0);
858 MOZ_ASSERT(decoder->mBackBufferUnreadLen == 0);
861 // Point to start of data to be rescanned.
862 src->next_input_byte = decoder->mBackBuffer + decoder->mBackBufferLen -
863 decoder->mBackBufferUnreadLen;
864 src->bytes_in_buffer += decoder->mBackBufferUnreadLen;
865 decoder->mBackBufferLen = (size_t)new_backtrack_buflen;
866 decoder->mReading = true;
868 return false;
871 /******************************************************************************/
872 /* data source manager method */
874 * Terminate source --- called by jpeg_finish_decompress() after all
875 * data has been read to clean up JPEG source manager. NOT called by
876 * jpeg_abort() or jpeg_destroy().
878 METHODDEF(void)
879 term_source(j_decompress_ptr jd) {
880 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
882 // This function shouldn't be called if we ran into an error we didn't
883 // recover from.
884 MOZ_ASSERT(decoder->mState != JPEG_ERROR,
885 "Calling term_source on a JPEG with mState == JPEG_ERROR!");
887 // Notify using a helper method to get around protectedness issues.
888 decoder->NotifyDone();
891 } // namespace image
892 } // namespace mozilla
894 ///*************** Inverted CMYK -> RGB conversion *************************
895 /// Input is (Inverted) CMYK stored as 4 bytes per pixel.
896 /// Output is RGB stored as 3 bytes per pixel.
897 /// @param aInput Points to row buffer containing the CMYK bytes for each pixel
898 /// in the row.
899 /// @param aOutput Points to row buffer to write BGRA to.
900 /// @param aWidth Number of pixels in the row.
901 static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput,
902 int32_t aWidth) {
903 uint8_t* input = reinterpret_cast<uint8_t*>(aInput);
905 for (int32_t i = 0; i < aWidth; ++i) {
906 // Source is 'Inverted CMYK', output is RGB.
907 // See: http://www.easyrgb.com/math.php?MATH=M12#text12
908 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
910 // From CMYK to CMY
911 // C = ( C * ( 1 - K ) + K )
912 // M = ( M * ( 1 - K ) + K )
913 // Y = ( Y * ( 1 - K ) + K )
915 // From Inverted CMYK to CMY is thus:
916 // C = ( (1-iC) * (1 - (1-iK)) + (1-iK) ) => 1 - iC*iK
917 // Same for M and Y
919 // Convert from CMY (0..1) to RGB (0..1)
920 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK
921 // G = 1 - M => 1 - (1 - iM*iK) => iM*iK
922 // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
924 // Convert from Inverted CMYK (0..255) to RGB (0..255)
925 const uint32_t iC = input[0];
926 const uint32_t iM = input[1];
927 const uint32_t iY = input[2];
928 const uint32_t iK = input[3];
930 const uint8_t r = iC * iK / 255;
931 const uint8_t g = iM * iK / 255;
932 const uint8_t b = iY * iK / 255;
934 *aOutput++ = (0xFF << mozilla::gfx::SurfaceFormatBit::OS_A) |
935 (r << mozilla::gfx::SurfaceFormatBit::OS_R) |
936 (g << mozilla::gfx::SurfaceFormatBit::OS_G) |
937 (b << mozilla::gfx::SurfaceFormatBit::OS_B);
938 input += 4;