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"
14 #include "Orientation.h"
16 #include "SurfacePipeFactory.h"
24 #include "gfxPlatform.h"
25 #include "mozilla/EndianUtils.h"
26 #include "mozilla/gfx/Types.h"
27 #include "mozilla/Telemetry.h"
34 # define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_XRGB
36 # define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_BGRX
39 static void cmyk_convert_bgra(uint32_t* aInput
, uint32_t* aOutput
,
42 using mozilla::gfx::SurfaceFormat
;
47 static mozilla::LazyLogModule
sJPEGLog("JPEGDecoder");
49 static mozilla::LazyLogModule
sJPEGDecoderAccountingLog(
50 "JPEGDecoderAccounting");
52 static qcms_profile
* GetICCProfile(struct jpeg_decompress_struct
& info
) {
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
);
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
)
78 mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA
,
79 State::JPEG_DATA
, SIZE_MAX
),
80 Transition::TerminateSuccess()),
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;
100 mImageData
= nullptr;
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;
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
121 jpeg_destroy_decompress(&mInfo
);
124 mBackBuffer
= nullptr;
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
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);
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()) {
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
) {
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.
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
))) !=
219 if (error_code
== NS_ERROR_FAILURE
) {
220 // Error due to corrupt data. Make sure that we don't feed any more data
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;
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.
243 return Transition::TerminateSuccess();
246 // Error for another reason. (Possibly OOM.)
248 MOZ_LOG(sJPEGDecoderAccountingLog
, LogLevel::Debug
,
249 ("} (setjmp returned an error)"));
253 return Transition::TerminateFailure();
257 MOZ_LOG(sJPEGLog
, LogLevel::Debug
,
258 ("[this=%p] nsJPEGDecoder::Write -- processing JPEG data\n", this));
262 LOG_SCOPE((mozilla::LogModule
*)sJPEGLog
,
263 "nsJPEGDecoder::Write -- entering JPEG_HEADER"
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
,
278 if (WantsFrameCount()) {
279 PostFrameCount(/* aFrameCount */ 1);
282 // Setting the size led to an 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
) {
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
;
303 case SurfaceFormat::X8R8G8B8
:
304 mInfo
.out_color_space
= JCS_EXT_XRGB
;
306 case SurfaceFormat::R8G8B8X8
:
307 mInfo
.out_color_space
= JCS_EXT_RGBX
;
311 return Transition::TerminateFailure();
316 // libjpeg can convert from YCCK to CMYK, but not to XRGB.
317 mInfo
.out_color_space
= JCS_CMYK
;
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
);
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);
358 // Calculate rendering intent.
359 int intent
= gfxPlatform::GetRenderingIntent();
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
];
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
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());
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
:
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!");
470 case WriteState::FAILURE
:
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
;
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
;
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
)) {
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() -"
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() - "
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() -"
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
)) {
578 mInfo
.output_scanline
= 0;
579 mPipe
.ResetToFirstRow();
582 case WriteState::FAILURE
:
584 MOZ_LOG(sJPEGDecoderAccountingLog
, LogLevel::Debug
,
585 ("} (Error in pipeline from OutputScalines())"));
586 return Transition::TerminateFailure();
590 [[fallthrough
]]; // to finish decompressing.
594 LOG_SCOPE((mozilla::LogModule
*)sJPEGLog
,
595 "nsJPEGDecoder::ProcessData -- entering"
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
;
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",
619 MOZ_ASSERT_UNREACHABLE(
620 "Should stop getting data after entering state "
621 "JPEG_SINK_NON_JPEG_TRAILER");
623 return Transition::TerminateSuccess();
626 MOZ_ASSERT_UNREACHABLE(
627 "Should stop getting data after entering state "
630 return Transition::TerminateFailure();
633 MOZ_ASSERT_UNREACHABLE("Escaped the JPEG decoder state machine");
634 return Transition::TerminateFailure();
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) {
654 // If we're at the end of the list, there's no EXIF data.
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
);
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
) {
680 // Already outputted directly to aPixelBlock as BGRA.
681 MOZ_ASSERT(!mCMSLine
);
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
,
693 // Convert from CMYK to BGRA
694 MOZ_ASSERT(mCMSLine
);
695 cmyk_convert_bgra(mCMSLine
, aPixelBlock
, aBlockSize
);
699 return std::make_tuple(aBlockSize
, Maybe
<WriteState
>());
702 Maybe
<SurfaceInvalidRect
> invalidRect
= mPipe
.TakeInvalidRect();
704 PostInvalidation(invalidRect
->mInputSpaceRect
,
705 Some(invalidRect
->mOutputSpaceRect
));
711 // Override the standard error method in the IJG JPEG decoder code.
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
718 switch (err
->pub
.msg_code
) {
719 case JERR_OUT_OF_MEMORY
:
720 error_code
= NS_ERROR_OUT_OF_MEMORY
;
722 case JERR_UNKNOWN_MARKER
:
723 error_code
= NS_ERROR_ILLEGAL_VALUE
;
725 case JERR_SOF_UNSUPPORTED
:
726 error_code
= NS_ERROR_INVALID_CONTENT_ENCODING
;
729 error_code
= NS_ERROR_FAILURE
;
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
);
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.
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.
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).
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.
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;
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.
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;
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;
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
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
);
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
);
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;
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().
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
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();
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
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
,
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
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
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
);