Bumping manifests a=b2g-bump
[gecko.git] / image / decoders / nsJPEGDecoder.cpp
blobe1dfc672d028a781ee594ffe6f249642c273b2f2
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"
8 #include "nsJPEGDecoder.h"
9 #include "Orientation.h"
10 #include "EXIF.h"
12 #include "nsIInputStream.h"
14 #include "nspr.h"
15 #include "nsCRT.h"
16 #include "gfxColor.h"
18 #include "jerror.h"
20 #include "gfxPlatform.h"
22 extern "C" {
23 #include "iccjpeg.h"
26 #if defined(IS_BIG_ENDIAN)
27 #define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_XRGB
28 #else
29 #define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_BGRX
30 #endif
32 static void cmyk_convert_rgb(JSAMPROW row, JDIMENSION width);
34 namespace mozilla {
35 namespace image {
37 #if defined(PR_LOGGING)
38 static PRLogModuleInfo*
39 GetJPEGLog()
41 static PRLogModuleInfo* sJPEGLog;
42 if (!sJPEGLog) {
43 sJPEGLog = PR_NewLogModule("JPEGDecoder");
45 return sJPEGLog;
48 static PRLogModuleInfo*
49 GetJPEGDecoderAccountingLog()
51 static PRLogModuleInfo* sJPEGDecoderAccountingLog;
52 if (!sJPEGDecoderAccountingLog) {
53 sJPEGDecoderAccountingLog = PR_NewLogModule("JPEGDecoderAccounting");
55 return sJPEGDecoderAccountingLog;
57 #else
58 #define GetJPEGLog()
59 #define GetJPEGDecoderAccountingLog()
60 #endif
62 static qcms_profile*
63 GetICCProfile(struct jpeg_decompress_struct& info)
65 JOCTET* profilebuf;
66 uint32_t profileLength;
67 qcms_profile* profile = nullptr;
69 if (read_icc_profile(&info, &profilebuf, &profileLength)) {
70 profile = qcms_profile_from_memory(profilebuf, profileLength);
71 free(profilebuf);
74 return profile;
77 METHODDEF(void) init_source (j_decompress_ptr jd);
78 METHODDEF(boolean) fill_input_buffer (j_decompress_ptr jd);
79 METHODDEF(void) skip_input_data (j_decompress_ptr jd, long num_bytes);
80 METHODDEF(void) term_source (j_decompress_ptr jd);
81 METHODDEF(void) my_error_exit (j_common_ptr cinfo);
83 // Normal JFIF markers can't have more bytes than this.
84 #define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1)
87 nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
88 Decoder::DecodeStyle aDecodeStyle)
89 : Decoder(aImage)
90 , mDecodeStyle(aDecodeStyle)
92 mState = JPEG_HEADER;
93 mReading = true;
94 mImageData = nullptr;
96 mBytesToSkip = 0;
97 memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
98 memset(&mSourceMgr, 0, sizeof(mSourceMgr));
99 mInfo.client_data = (void*)this;
101 mSegment = nullptr;
102 mSegmentLen = 0;
104 mBackBuffer = nullptr;
105 mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0;
107 mInProfile = nullptr;
108 mTransform = nullptr;
110 mCMSMode = 0;
112 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
113 ("nsJPEGDecoder::nsJPEGDecoder: Creating JPEG decoder %p",
114 this));
117 nsJPEGDecoder::~nsJPEGDecoder()
119 // Step 8: Release JPEG decompression object
120 mInfo.src = nullptr;
121 jpeg_destroy_decompress(&mInfo);
123 PR_FREEIF(mBackBuffer);
124 if (mTransform) {
125 qcms_transform_release(mTransform);
127 if (mInProfile) {
128 qcms_profile_release(mInProfile);
131 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
132 ("nsJPEGDecoder::~nsJPEGDecoder: Destroying JPEG decoder %p",
133 this));
136 Telemetry::ID
137 nsJPEGDecoder::SpeedHistogram()
139 return Telemetry::IMAGE_DECODE_SPEED_JPEG;
142 void
143 nsJPEGDecoder::InitInternal()
145 mCMSMode = gfxPlatform::GetCMSMode();
146 if (GetDecodeFlags() & imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION) {
147 mCMSMode = eCMSMode_Off;
150 // We set up the normal JPEG error routines, then override error_exit.
151 mInfo.err = jpeg_std_error(&mErr.pub);
152 // mInfo.err = jpeg_std_error(&mErr.pub);
153 mErr.pub.error_exit = my_error_exit;
154 // Establish the setjmp return context for my_error_exit to use.
155 if (setjmp(mErr.setjmp_buffer)) {
156 // If we get here, the JPEG code has signaled an error.
157 // We need to clean up the JPEG object, close the input file, and return.
158 PostDecoderError(NS_ERROR_FAILURE);
159 return;
162 // Step 1: allocate and initialize JPEG decompression object
163 jpeg_create_decompress(&mInfo);
164 // Set the source manager
165 mInfo.src = &mSourceMgr;
167 // Step 2: specify data source (eg, a file)
169 // Setup callback functions.
170 mSourceMgr.init_source = init_source;
171 mSourceMgr.fill_input_buffer = fill_input_buffer;
172 mSourceMgr.skip_input_data = skip_input_data;
173 mSourceMgr.resync_to_restart = jpeg_resync_to_restart;
174 mSourceMgr.term_source = term_source;
176 // Record app markers for ICC data
177 for (uint32_t m = 0; m < 16; m++)
178 jpeg_save_markers(&mInfo, JPEG_APP0 + m, 0xFFFF);
181 void
182 nsJPEGDecoder::FinishInternal()
184 // If we're not in any sort of error case, force our state to JPEG_DONE.
185 if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
186 (mState != JPEG_ERROR) &&
187 !IsSizeDecode()) {
188 mState = JPEG_DONE;
192 void
193 nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
195 mSegment = (const JOCTET*)aBuffer;
196 mSegmentLen = aCount;
198 NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
200 // Return here if there is a fatal error within libjpeg.
201 nsresult error_code;
202 // This cast to nsresult makes sense because setjmp() returns whatever we
203 // passed to longjmp(), which was actually an nsresult.
204 if ((error_code = (nsresult)setjmp(mErr.setjmp_buffer)) != NS_OK) {
205 if (error_code == NS_ERROR_FAILURE) {
206 PostDataError();
207 // Error due to corrupt stream - return NS_OK and consume silently
208 // so that ImageLib doesn't throw away a partial image load
209 mState = JPEG_SINK_NON_JPEG_TRAILER;
210 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
211 ("} (setjmp returned NS_ERROR_FAILURE)"));
212 return;
213 } else {
214 // Error due to reasons external to the stream (probably out of
215 // memory) - let ImageLib attempt to clean up, even though
216 // mozilla is seconds away from falling flat on its face.
217 PostDecoderError(error_code);
218 mState = JPEG_ERROR;
219 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
220 ("} (setjmp returned an error)"));
221 return;
225 PR_LOG(GetJPEGLog(), PR_LOG_DEBUG,
226 ("[this=%p] nsJPEGDecoder::Write -- processing JPEG data\n", this));
228 switch (mState) {
229 case JPEG_HEADER: {
230 LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- entering JPEG_HEADER"
231 " case");
233 // Step 3: read file parameters with jpeg_read_header()
234 if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED) {
235 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
236 ("} (JPEG_SUSPENDED)"));
237 return; // I/O suspension
240 int sampleSize = mImage->GetRequestedSampleSize();
241 if (sampleSize > 0) {
242 mInfo.scale_num = 1;
243 mInfo.scale_denom = sampleSize;
246 // Used to set up image size so arrays can be allocated
247 jpeg_calc_output_dimensions(&mInfo);
249 // Post our size to the superclass
250 PostSize(mInfo.output_width, mInfo.output_height,
251 ReadOrientationFromEXIF());
252 if (HasError()) {
253 // Setting the size led to an error.
254 mState = JPEG_ERROR;
255 return;
258 // If we're doing a size decode, we're done.
259 if (IsSizeDecode()) {
260 return;
263 // We're doing a full decode.
264 if (mCMSMode != eCMSMode_Off &&
265 (mInProfile = GetICCProfile(mInfo)) != nullptr) {
266 uint32_t profileSpace = qcms_profile_get_color_space(mInProfile);
267 bool mismatch = false;
269 #ifdef DEBUG_tor
270 fprintf(stderr, "JPEG profileSpace: 0x%08X\n", profileSpace);
271 #endif
272 switch (mInfo.jpeg_color_space) {
273 case JCS_GRAYSCALE:
274 if (profileSpace == icSigRgbData) {
275 mInfo.out_color_space = JCS_RGB;
276 } else if (profileSpace != icSigGrayData) {
277 mismatch = true;
279 break;
280 case JCS_RGB:
281 if (profileSpace != icSigRgbData) {
282 mismatch = true;
284 break;
285 case JCS_YCbCr:
286 if (profileSpace == icSigRgbData) {
287 mInfo.out_color_space = JCS_RGB;
288 } else {
289 // qcms doesn't support ycbcr
290 mismatch = true;
292 break;
293 case JCS_CMYK:
294 case JCS_YCCK:
295 // qcms doesn't support cmyk
296 mismatch = true;
297 break;
298 default:
299 mState = JPEG_ERROR;
300 PostDataError();
301 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
302 ("} (unknown colorpsace (1))"));
303 return;
306 if (!mismatch) {
307 qcms_data_type type;
308 switch (mInfo.out_color_space) {
309 case JCS_GRAYSCALE:
310 type = QCMS_DATA_GRAY_8;
311 break;
312 case JCS_RGB:
313 type = QCMS_DATA_RGB_8;
314 break;
315 default:
316 mState = JPEG_ERROR;
317 PostDataError();
318 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
319 ("} (unknown colorpsace (2))"));
320 return;
322 #if 0
323 // We don't currently support CMYK profiles. The following
324 // code dealt with lcms types. Add something like this
325 // back when we gain support for CMYK.
327 // Adobe Photoshop writes YCCK/CMYK files with inverted data
328 if (mInfo.out_color_space == JCS_CMYK) {
329 type |= FLAVOR_SH(mInfo.saw_Adobe_marker ? 1 : 0);
331 #endif
333 if (gfxPlatform::GetCMSOutputProfile()) {
335 // Calculate rendering intent.
336 int intent = gfxPlatform::GetRenderingIntent();
337 if (intent == -1) {
338 intent = qcms_profile_get_rendering_intent(mInProfile);
341 // Create the color management transform.
342 mTransform = qcms_transform_create(mInProfile,
343 type,
344 gfxPlatform::GetCMSOutputProfile(),
345 QCMS_DATA_RGB_8,
346 (qcms_intent)intent);
348 } else {
349 #ifdef DEBUG_tor
350 fprintf(stderr, "ICM profile colorspace mismatch\n");
351 #endif
355 if (!mTransform) {
356 switch (mInfo.jpeg_color_space) {
357 case JCS_GRAYSCALE:
358 case JCS_RGB:
359 case JCS_YCbCr:
360 // if we're not color managing we can decode directly to
361 // MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB
362 if (mCMSMode != eCMSMode_All) {
363 mInfo.out_color_space = MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB;
364 mInfo.out_color_components = 4;
365 } else {
366 mInfo.out_color_space = JCS_RGB;
368 break;
369 case JCS_CMYK:
370 case JCS_YCCK:
371 // libjpeg can convert from YCCK to CMYK, but not to RGB
372 mInfo.out_color_space = JCS_CMYK;
373 break;
374 default:
375 mState = JPEG_ERROR;
376 PostDataError();
377 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
378 ("} (unknown colorpsace (3))"));
379 return;
380 break;
384 // Don't allocate a giant and superfluous memory buffer
385 // when not doing a progressive decode.
386 mInfo.buffered_image = mDecodeStyle == PROGRESSIVE &&
387 jpeg_has_multiple_scans(&mInfo);
389 if (!mImageData) {
390 mState = JPEG_ERROR;
391 PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
392 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
393 ("} (could not initialize image frame)"));
394 return;
397 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
398 (" JPEGDecoderAccounting: nsJPEGDecoder::"
399 "Write -- created image frame with %ux%u pixels",
400 mInfo.output_width, mInfo.output_height));
402 mState = JPEG_START_DECOMPRESS;
405 case JPEG_START_DECOMPRESS: {
406 LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- entering"
407 " JPEG_START_DECOMPRESS case");
408 // Step 4: set parameters for decompression
410 // FIXME -- Should reset dct_method and dither mode
411 // for final pass of progressive JPEG
413 mInfo.dct_method = JDCT_ISLOW;
414 mInfo.dither_mode = JDITHER_FS;
415 mInfo.do_fancy_upsampling = TRUE;
416 mInfo.enable_2pass_quant = FALSE;
417 mInfo.do_block_smoothing = TRUE;
419 // Step 5: Start decompressor
420 if (jpeg_start_decompress(&mInfo) == FALSE) {
421 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
422 ("} (I/O suspension after jpeg_start_decompress())"));
423 return; // I/O suspension
427 // If this is a progressive JPEG ...
428 mState = mInfo.buffered_image ?
429 JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL;
432 case JPEG_DECOMPRESS_SEQUENTIAL: {
433 if (mState == JPEG_DECOMPRESS_SEQUENTIAL) {
434 LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- "
435 "JPEG_DECOMPRESS_SEQUENTIAL case");
437 bool suspend;
438 OutputScanlines(&suspend);
440 if (suspend) {
441 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
442 ("} (I/O suspension after OutputScanlines() - SEQUENTIAL)"));
443 return; // I/O suspension
446 // If we've completed image output ...
447 NS_ASSERTION(mInfo.output_scanline == mInfo.output_height,
448 "We didn't process all of the data!");
449 mState = JPEG_DONE;
453 case JPEG_DECOMPRESS_PROGRESSIVE: {
454 if (mState == JPEG_DECOMPRESS_PROGRESSIVE) {
455 LOG_SCOPE(GetJPEGLog(),
456 "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case");
458 int status;
459 do {
460 status = jpeg_consume_input(&mInfo);
461 } while ((status != JPEG_SUSPENDED) &&
462 (status != JPEG_REACHED_EOI));
464 for (;;) {
465 if (mInfo.output_scanline == 0) {
466 int scan = mInfo.input_scan_number;
468 // if we haven't displayed anything yet (output_scan_number==0)
469 // and we have enough data for a complete scan, force output
470 // of the last full scan
471 if ((mInfo.output_scan_number == 0) &&
472 (scan > 1) &&
473 (status != JPEG_REACHED_EOI))
474 scan--;
476 if (!jpeg_start_output(&mInfo, scan)) {
477 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
478 ("} (I/O suspension after jpeg_start_output() -"
479 " PROGRESSIVE)"));
480 return; // I/O suspension
484 if (mInfo.output_scanline == 0xffffff) {
485 mInfo.output_scanline = 0;
488 bool suspend;
489 OutputScanlines(&suspend);
491 if (suspend) {
492 if (mInfo.output_scanline == 0) {
493 // didn't manage to read any lines - flag so we don't call
494 // jpeg_start_output() multiple times for the same scan
495 mInfo.output_scanline = 0xffffff;
497 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
498 ("} (I/O suspension after OutputScanlines() - PROGRESSIVE)"));
499 return; // I/O suspension
502 if (mInfo.output_scanline == mInfo.output_height) {
503 if (!jpeg_finish_output(&mInfo)) {
504 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
505 ("} (I/O suspension after jpeg_finish_output() -"
506 " PROGRESSIVE)"));
507 return; // I/O suspension
510 if (jpeg_input_complete(&mInfo) &&
511 (mInfo.input_scan_number == mInfo.output_scan_number))
512 break;
514 mInfo.output_scanline = 0;
518 mState = JPEG_DONE;
522 case JPEG_DONE: {
523 LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::ProcessData -- entering"
524 " JPEG_DONE case");
526 // Step 7: Finish decompression
528 if (jpeg_finish_decompress(&mInfo) == FALSE) {
529 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
530 ("} (I/O suspension after jpeg_finish_decompress() - DONE)"));
531 return; // I/O suspension
534 mState = JPEG_SINK_NON_JPEG_TRAILER;
536 // we're done dude
537 break;
539 case JPEG_SINK_NON_JPEG_TRAILER:
540 PR_LOG(GetJPEGLog(), PR_LOG_DEBUG,
541 ("[this=%p] nsJPEGDecoder::ProcessData -- entering"
542 " JPEG_SINK_NON_JPEG_TRAILER case\n", this));
544 break;
546 case JPEG_ERROR:
547 NS_ABORT_IF_FALSE(0, "Should always return immediately after error and"
548 " not re-enter decoder");
551 PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
552 ("} (end of function)"));
553 return;
556 Orientation
557 nsJPEGDecoder::ReadOrientationFromEXIF()
559 jpeg_saved_marker_ptr marker;
561 // Locate the APP1 marker, where EXIF data is stored, in the marker list.
562 for (marker = mInfo.marker_list ; marker != nullptr ; marker = marker->next) {
563 if (marker->marker == JPEG_APP0 + 1) {
564 break;
568 // If we're at the end of the list, there's no EXIF data.
569 if (!marker) {
570 return Orientation();
573 // Extract the orientation information.
574 EXIFData exif = EXIFParser::Parse(marker->data,
575 static_cast<uint32_t>(marker->data_length));
576 return exif.orientation;
579 void
580 nsJPEGDecoder::NotifyDone()
582 PostFrameStop(Opacity::OPAQUE);
583 PostDecodeDone();
586 void
587 nsJPEGDecoder::OutputScanlines(bool* suspend)
589 *suspend = false;
591 const uint32_t top = mInfo.output_scanline;
593 while ((mInfo.output_scanline < mInfo.output_height)) {
594 // Use the Cairo image buffer as scanline buffer
595 uint32_t* imageRow = ((uint32_t*)mImageData) +
596 (mInfo.output_scanline * mInfo.output_width);
598 if (mInfo.out_color_space == MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB) {
599 // Special case: scanline will be directly converted into packed ARGB
600 if (jpeg_read_scanlines(&mInfo, (JSAMPARRAY)&imageRow, 1) != 1) {
601 *suspend = true; // suspend
602 break;
604 continue; // all done for this row!
607 JSAMPROW sampleRow = (JSAMPROW)imageRow;
608 if (mInfo.output_components == 3) {
609 // Put the pixels at end of row to enable in-place expansion
610 sampleRow += mInfo.output_width;
613 // Request one scanline. Returns 0 or 1 scanlines.
614 if (jpeg_read_scanlines(&mInfo, &sampleRow, 1) != 1) {
615 *suspend = true; // suspend
616 break;
619 if (mTransform) {
620 JSAMPROW source = sampleRow;
621 if (mInfo.out_color_space == JCS_GRAYSCALE) {
622 // Convert from the 1byte grey pixels at begin of row
623 // to the 3byte RGB byte pixels at 'end' of row
624 sampleRow += mInfo.output_width;
626 qcms_transform_data(mTransform, source, sampleRow, mInfo.output_width);
627 // Move 3byte RGB data to end of row
628 if (mInfo.out_color_space == JCS_CMYK) {
629 memmove(sampleRow + mInfo.output_width,
630 sampleRow,
631 3 * mInfo.output_width);
632 sampleRow += mInfo.output_width;
634 } else {
635 if (mInfo.out_color_space == JCS_CMYK) {
636 // Convert from CMYK to RGB
637 // We cannot convert directly to Cairo, as the CMSRGBTransform
638 // may wants to do a RGB transform...
639 // Would be better to have platform CMSenabled transformation
640 // from CMYK to (A)RGB...
641 cmyk_convert_rgb((JSAMPROW)imageRow, mInfo.output_width);
642 sampleRow += mInfo.output_width;
644 if (mCMSMode == eCMSMode_All) {
645 // No embedded ICC profile - treat as sRGB
646 qcms_transform* transform = gfxPlatform::GetCMSRGBTransform();
647 if (transform) {
648 qcms_transform_data(transform, sampleRow, sampleRow,
649 mInfo.output_width);
654 // counter for while() loops below
655 uint32_t idx = mInfo.output_width;
657 // copy as bytes until source pointer is 32-bit-aligned
658 for (; (NS_PTR_TO_UINT32(sampleRow) & 0x3) && idx; --idx) {
659 *imageRow++ = gfxPackedPixel(0xFF, sampleRow[0], sampleRow[1],
660 sampleRow[2]);
661 sampleRow += 3;
664 // copy pixels in blocks of 4
665 while (idx >= 4) {
666 GFX_BLOCK_RGB_TO_FRGB(sampleRow, imageRow);
667 idx -= 4;
668 sampleRow += 12;
669 imageRow += 4;
672 // copy remaining pixel(s)
673 while (idx--) {
674 // 32-bit read of final pixel will exceed buffer, so read bytes
675 *imageRow++ = gfxPackedPixel(0xFF, sampleRow[0], sampleRow[1],
676 sampleRow[2]);
677 sampleRow += 3;
681 if (top != mInfo.output_scanline) {
682 nsIntRect r(0, top, mInfo.output_width, mInfo.output_scanline-top);
683 PostInvalidation(r);
689 // Override the standard error method in the IJG JPEG decoder code.
690 METHODDEF(void)
691 my_error_exit (j_common_ptr cinfo)
693 decoder_error_mgr* err = (decoder_error_mgr*) cinfo->err;
695 // Convert error to a browser error code
696 nsresult error_code = err->pub.msg_code == JERR_OUT_OF_MEMORY
697 ? NS_ERROR_OUT_OF_MEMORY
698 : NS_ERROR_FAILURE;
700 #ifdef DEBUG
701 char buffer[JMSG_LENGTH_MAX];
703 // Create the message
704 (*err->pub.format_message) (cinfo, buffer);
706 fprintf(stderr, "JPEG decoding error:\n%s\n", buffer);
707 #endif
709 // Return control to the setjmp point. We pass an nsresult masquerading as
710 // an int, which works because the setjmp() caller casts it back.
711 longjmp(err->setjmp_buffer, static_cast<int>(error_code));
714 /*******************************************************************************
715 * This is the callback routine from the IJG JPEG library used to supply new
716 * data to the decompressor when its input buffer is exhausted. It juggles
717 * multiple buffers in an attempt to avoid unnecessary copying of input data.
719 * (A simpler scheme is possible: It's much easier to use only a single
720 * buffer; when fill_input_buffer() is called, move any unconsumed data
721 * (beyond the current pointer/count) down to the beginning of this buffer and
722 * then load new data into the remaining buffer space. This approach requires
723 * a little more data copying but is far easier to get right.)
725 * At any one time, the JPEG decompressor is either reading from the necko
726 * input buffer, which is volatile across top-level calls to the IJG library,
727 * or the "backtrack" buffer. The backtrack buffer contains the remaining
728 * unconsumed data from the necko buffer after parsing was suspended due
729 * to insufficient data in some previous call to the IJG library.
731 * When suspending, the decompressor will back up to a convenient restart
732 * point (typically the start of the current MCU). The variables
733 * next_input_byte & bytes_in_buffer indicate where the restart point will be
734 * if the current call returns FALSE. Data beyond this point must be
735 * rescanned after resumption, so it must be preserved in case the decompressor
736 * decides to backtrack.
738 * Returns:
739 * TRUE if additional data is available, FALSE if no data present and
740 * the JPEG library should therefore suspend processing of input stream
741 ******************************************************************************/
743 /******************************************************************************/
744 /* data source manager method */
745 /******************************************************************************/
747 /******************************************************************************/
748 /* data source manager method
749 Initialize source. This is called by jpeg_read_header() before any
750 data is actually read. May leave
751 bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
752 will occur immediately).
754 METHODDEF(void)
755 init_source (j_decompress_ptr jd)
759 /******************************************************************************/
760 /* data source manager method
761 Skip num_bytes worth of data. The buffer pointer and count should
762 be advanced over num_bytes input bytes, refilling the buffer as
763 needed. This is used to skip over a potentially large amount of
764 uninteresting data (such as an APPn marker). In some applications
765 it may be possible to optimize away the reading of the skipped data,
766 but it's not clear that being smart is worth much trouble; large
767 skips are uncommon. bytes_in_buffer may be zero on return.
768 A zero or negative skip count should be treated as a no-op.
770 METHODDEF(void)
771 skip_input_data (j_decompress_ptr jd, long num_bytes)
773 struct jpeg_source_mgr* src = jd->src;
774 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
776 if (num_bytes > (long)src->bytes_in_buffer) {
777 // Can't skip it all right now until we get more data from
778 // network stream. Set things up so that fill_input_buffer
779 // will skip remaining amount.
780 decoder->mBytesToSkip = (size_t)num_bytes - src->bytes_in_buffer;
781 src->next_input_byte += src->bytes_in_buffer;
782 src->bytes_in_buffer = 0;
784 } else {
785 // Simple case. Just advance buffer pointer
787 src->bytes_in_buffer -= (size_t)num_bytes;
788 src->next_input_byte += num_bytes;
793 /******************************************************************************/
794 /* data source manager method
795 This is called whenever bytes_in_buffer has reached zero and more
796 data is wanted. In typical applications, it should read fresh data
797 into the buffer (ignoring the current state of next_input_byte and
798 bytes_in_buffer), reset the pointer & count to the start of the
799 buffer, and return TRUE indicating that the buffer has been reloaded.
800 It is not necessary to fill the buffer entirely, only to obtain at
801 least one more byte. bytes_in_buffer MUST be set to a positive value
802 if TRUE is returned. A FALSE return should only be used when I/O
803 suspension is desired.
805 METHODDEF(boolean)
806 fill_input_buffer (j_decompress_ptr jd)
808 struct jpeg_source_mgr* src = jd->src;
809 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
811 if (decoder->mReading) {
812 const JOCTET* new_buffer = decoder->mSegment;
813 uint32_t new_buflen = decoder->mSegmentLen;
815 if (!new_buffer || new_buflen == 0) {
816 return false; // suspend
819 decoder->mSegmentLen = 0;
821 if (decoder->mBytesToSkip) {
822 if (decoder->mBytesToSkip < new_buflen) {
823 // All done skipping bytes; Return what's left.
824 new_buffer += decoder->mBytesToSkip;
825 new_buflen -= decoder->mBytesToSkip;
826 decoder->mBytesToSkip = 0;
827 } else {
828 // Still need to skip some more data in the future
829 decoder->mBytesToSkip -= (size_t)new_buflen;
830 return false; // suspend
834 decoder->mBackBufferUnreadLen = src->bytes_in_buffer;
836 src->next_input_byte = new_buffer;
837 src->bytes_in_buffer = (size_t)new_buflen;
838 decoder->mReading = false;
840 return true;
843 if (src->next_input_byte != decoder->mSegment) {
844 // Backtrack data has been permanently consumed.
845 decoder->mBackBufferUnreadLen = 0;
846 decoder->mBackBufferLen = 0;
849 // Save remainder of netlib buffer in backtrack buffer
850 const uint32_t new_backtrack_buflen = src->bytes_in_buffer +
851 decoder->mBackBufferLen;
853 // Make sure backtrack buffer is big enough to hold new data.
854 if (decoder->mBackBufferSize < new_backtrack_buflen) {
855 // Check for malformed MARKER segment lengths, before allocating space
856 // for it
857 if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) {
858 my_error_exit((j_common_ptr)(&decoder->mInfo));
861 // Round up to multiple of 256 bytes.
862 const size_t roundup_buflen = ((new_backtrack_buflen + 255) >> 8) << 8;
863 JOCTET* buf = (JOCTET*)PR_REALLOC(decoder->mBackBuffer, roundup_buflen);
864 // Check for OOM
865 if (!buf) {
866 decoder->mInfo.err->msg_code = JERR_OUT_OF_MEMORY;
867 my_error_exit((j_common_ptr)(&decoder->mInfo));
869 decoder->mBackBuffer = buf;
870 decoder->mBackBufferSize = roundup_buflen;
873 // Copy remainder of netlib segment into backtrack buffer.
874 memmove(decoder->mBackBuffer + decoder->mBackBufferLen,
875 src->next_input_byte,
876 src->bytes_in_buffer);
878 // Point to start of data to be rescanned.
879 src->next_input_byte = decoder->mBackBuffer + decoder->mBackBufferLen -
880 decoder->mBackBufferUnreadLen;
881 src->bytes_in_buffer += decoder->mBackBufferUnreadLen;
882 decoder->mBackBufferLen = (size_t)new_backtrack_buflen;
883 decoder->mReading = true;
885 return false;
888 /******************************************************************************/
889 /* data source manager method */
891 * Terminate source --- called by jpeg_finish_decompress() after all
892 * data has been read to clean up JPEG source manager. NOT called by
893 * jpeg_abort() or jpeg_destroy().
895 METHODDEF(void)
896 term_source (j_decompress_ptr jd)
898 nsJPEGDecoder* decoder = (nsJPEGDecoder*)(jd->client_data);
900 // This function shouldn't be called if we ran into an error we didn't
901 // recover from.
902 NS_ABORT_IF_FALSE(decoder->mState != JPEG_ERROR,
903 "Calling term_source on a JPEG with mState == JPEG_ERROR!");
905 // Notify using a helper method to get around protectedness issues.
906 decoder->NotifyDone();
909 } // namespace image
910 } // namespace mozilla
913 ///*************** Inverted CMYK -> RGB conversion *************************
914 /// Input is (Inverted) CMYK stored as 4 bytes per pixel.
915 /// Output is RGB stored as 3 bytes per pixel.
916 /// @param row Points to row buffer containing the CMYK bytes for each pixel
917 /// in the row.
918 /// @param width Number of pixels in the row.
919 static void cmyk_convert_rgb(JSAMPROW row, JDIMENSION width)
921 // Work from end to front to shrink from 4 bytes per pixel to 3
922 JSAMPROW in = row + width*4;
923 JSAMPROW out = in;
925 for (uint32_t i = width; i > 0; i--) {
926 in -= 4;
927 out -= 3;
929 // Source is 'Inverted CMYK', output is RGB.
930 // See: http://www.easyrgb.com/math.php?MATH=M12#text12
931 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
933 // From CMYK to CMY
934 // C = ( C * ( 1 - K ) + K )
935 // M = ( M * ( 1 - K ) + K )
936 // Y = ( Y * ( 1 - K ) + K )
938 // From Inverted CMYK to CMY is thus:
939 // C = ( (1-iC) * (1 - (1-iK)) + (1-iK) ) => 1 - iC*iK
940 // Same for M and Y
942 // Convert from CMY (0..1) to RGB (0..1)
943 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK
944 // G = 1 - M => 1 - (1 - iM*iK) => iM*iK
945 // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
947 // Convert from Inverted CMYK (0..255) to RGB (0..255)
948 const uint32_t iC = in[0];
949 const uint32_t iM = in[1];
950 const uint32_t iY = in[2];
951 const uint32_t iK = in[3];
952 out[0] = iC*iK/255; // Red
953 out[1] = iM*iK/255; // Green
954 out[2] = iY*iK/255; // Blue