1/*
2 * Copyright (C) 2006 Apple Inc.
3 *
4 * Portions are Copyright (C) 2001-6 mozilla.org
5 *
6 * Other contributors:
7 * Stuart Parmenter <stuart@mozilla.com>
8 *
9 * Copyright (C) 2007-2009 Torch Mobile, Inc.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 * Alternatively, the contents of this file may be used under the terms
26 * of either the Mozilla Public License Version 1.1, found at
27 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
28 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
29 * (the "GPL"), in which case the provisions of the MPL or the GPL are
30 * applicable instead of those above. If you wish to allow use of your
31 * version of this file only under the terms of one of those two
32 * licenses (the MPL or the GPL) and not to allow others to use your
33 * version of this file under the LGPL, indicate your decision by
34 * deletingthe provisions above and replace them with the notice and
35 * other provisions required by the MPL or the GPL, as the case may be.
36 * If you do not delete the provisions above, a recipient may use your
37 * version of this file under any of the LGPL, the MPL or the GPL.
38 */
39
40#include "config.h"
41#include "JPEGImageDecoder.h"
42
43extern "C" {
44#if USE(ICCJPEG)
45#include <iccjpeg.h>
46#endif
47#include <setjmp.h>
48}
49
50#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
51#define ASSUME_LITTLE_ENDIAN 0
52#else
53#define ASSUME_LITTLE_ENDIAN 1
54#endif
55
56#if defined(JCS_ALPHA_EXTENSIONS) && ASSUME_LITTLE_ENDIAN
57#define TURBO_JPEG_RGB_SWIZZLE
58inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; }
59inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_EXT_RGBA || colorSpace == JCS_EXT_BGRA; }
60inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { return turboSwizzled(colorSpace); }
61#else
62inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; }
63inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { return false; }
64#endif
65
66#if USE(LOW_QUALITY_IMAGE_NO_JPEG_DITHERING)
67inline J_DCT_METHOD dctMethod() { return JDCT_IFAST; }
68inline J_DITHER_MODE ditherMode() { return JDITHER_NONE; }
69#else
70inline J_DCT_METHOD dctMethod() { return JDCT_ISLOW; }
71inline J_DITHER_MODE ditherMode() { return JDITHER_FS; }
72#endif
73
74#if USE(LOW_QUALITY_IMAGE_NO_JPEG_FANCY_UPSAMPLING)
75inline bool doFancyUpsampling() { return false; }
76#else
77inline bool doFancyUpsampling() { return true; }
78#endif
79
80const int exifMarker = JPEG_APP0 + 1;
81
82namespace WebCore {
83
84struct decoder_error_mgr {
85 struct jpeg_error_mgr pub; // "public" fields for IJG library
86 jmp_buf setjmp_buffer; // For handling catastropic errors
87};
88
89enum jstate {
90 JPEG_HEADER, // Reading JFIF headers
91 JPEG_START_DECOMPRESS,
92 JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels
93 JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels
94 JPEG_DONE,
95 JPEG_ERROR
96};
97
98void init_source(j_decompress_ptr jd);
99boolean fill_input_buffer(j_decompress_ptr jd);
100void skip_input_data(j_decompress_ptr jd, long num_bytes);
101void term_source(j_decompress_ptr jd);
102void error_exit(j_common_ptr cinfo);
103
104// Implementation of a JPEG src object that understands our state machine
105struct decoder_source_mgr {
106 // public fields; must be first in this struct!
107 struct jpeg_source_mgr pub;
108
109 JPEGImageReader* decoder;
110};
111
112static unsigned readUint16(JOCTET* data, bool isBigEndian)
113{
114 if (isBigEndian)
115 return (GETJOCTET(data[0]) << 8) | GETJOCTET(data[1]);
116 return (GETJOCTET(data[1]) << 8) | GETJOCTET(data[0]);
117}
118
119static unsigned readUint32(JOCTET* data, bool isBigEndian)
120{
121 if (isBigEndian)
122 return (GETJOCTET(data[0]) << 24) | (GETJOCTET(data[1]) << 16) | (GETJOCTET(data[2]) << 8) | GETJOCTET(data[3]);
123 return (GETJOCTET(data[3]) << 24) | (GETJOCTET(data[2]) << 16) | (GETJOCTET(data[1]) << 8) | GETJOCTET(data[0]);
124}
125
126static bool checkExifHeader(jpeg_saved_marker_ptr marker, bool& isBigEndian, unsigned& ifdOffset)
127{
128 // For exif data, the APP1 block is followed by 'E', 'x', 'i', 'f', '\0',
129 // then a fill byte, and then a tiff file that contains the metadata.
130 // A tiff file starts with 'I', 'I' (intel / little endian byte order) or
131 // 'M', 'M' (motorola / big endian byte order), followed by (uint16_t)42,
132 // followed by an uint32_t with the offset to the tag block, relative to the
133 // tiff file start.
134 const unsigned exifHeaderSize = 14;
135 if (!(marker->marker == exifMarker
136 && marker->data_length >= exifHeaderSize
137 && marker->data[0] == 'E'
138 && marker->data[1] == 'x'
139 && marker->data[2] == 'i'
140 && marker->data[3] == 'f'
141 && marker->data[4] == '\0'
142 // data[5] is a fill byte
143 && ((marker->data[6] == 'I' && marker->data[7] == 'I')
144 || (marker->data[6] == 'M' && marker->data[7] == 'M'))))
145 return false;
146
147 isBigEndian = marker->data[6] == 'M';
148 if (readUint16(marker->data + 8, isBigEndian) != 42)
149 return false;
150
151 ifdOffset = readUint32(marker->data + 10, isBigEndian);
152 return true;
153}
154
155static ImageOrientation readImageOrientation(jpeg_decompress_struct* info)
156{
157 // The JPEG decoder looks at EXIF metadata.
158 // FIXME: Possibly implement XMP and IPTC support.
159 const unsigned orientationTag = 0x112;
160 const unsigned shortType = 3;
161 for (jpeg_saved_marker_ptr marker = info->marker_list; marker; marker = marker->next) {
162 bool isBigEndian;
163 unsigned ifdOffset;
164 if (!checkExifHeader(marker, isBigEndian, ifdOffset))
165 continue;
166 const unsigned offsetToTiffData = 6; // Account for 'Exif\0<fill byte>' header.
167 if (marker->data_length < offsetToTiffData || ifdOffset >= marker->data_length - offsetToTiffData)
168 continue;
169 ifdOffset += offsetToTiffData;
170
171 // The jpeg exif container format contains a tiff block for metadata.
172 // A tiff image file directory (ifd) consists of a uint16_t describing
173 // the number of ifd entries, followed by that many entries.
174 // When touching this code, it's useful to look at the tiff spec:
175 // http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
176 JOCTET* ifd = marker->data + ifdOffset;
177 JOCTET* end = marker->data + marker->data_length;
178 if (end - ifd < 2)
179 continue;
180 unsigned tagCount = readUint16(ifd, isBigEndian);
181 ifd += 2; // Skip over the uint16 that was just read.
182
183 // Every ifd entry is 2 bytes of tag, 2 bytes of contents datatype,
184 // 4 bytes of number-of-elements, and 4 bytes of either offset to the
185 // tag data, or if the data is small enough, the inlined data itself.
186 const int ifdEntrySize = 12;
187 for (unsigned i = 0; i < tagCount && end - ifd >= ifdEntrySize; ++i, ifd += ifdEntrySize) {
188 unsigned tag = readUint16(ifd, isBigEndian);
189 unsigned type = readUint16(ifd + 2, isBigEndian);
190 unsigned count = readUint32(ifd + 4, isBigEndian);
191 if (tag == orientationTag && type == shortType && count == 1)
192 return ImageOrientation::fromEXIFValue(readUint16(ifd + 8, isBigEndian));
193 }
194 }
195
196 return ImageOrientation();
197}
198
199class JPEGImageReader {
200 WTF_MAKE_FAST_ALLOCATED;
201public:
202 JPEGImageReader(JPEGImageDecoder* decoder)
203 : m_decoder(decoder)
204 , m_bufferLength(0)
205 , m_bytesToSkip(0)
206 , m_state(JPEG_HEADER)
207 , m_samples(0)
208 {
209 memset(&m_info, 0, sizeof(jpeg_decompress_struct));
210
211 // We set up the normal JPEG error routines, then override error_exit.
212 m_info.err = jpeg_std_error(&m_err.pub);
213 m_err.pub.error_exit = error_exit;
214
215 // Allocate and initialize JPEG decompression object.
216 jpeg_create_decompress(&m_info);
217
218 decoder_source_mgr* src = 0;
219 if (!m_info.src) {
220 src = (decoder_source_mgr*)fastCalloc(sizeof(decoder_source_mgr), 1);
221 if (!src) {
222 m_state = JPEG_ERROR;
223 return;
224 }
225 }
226
227 m_info.src = (jpeg_source_mgr*)src;
228
229 // Set up callback functions.
230 src->pub.init_source = init_source;
231 src->pub.fill_input_buffer = fill_input_buffer;
232 src->pub.skip_input_data = skip_input_data;
233 src->pub.resync_to_restart = jpeg_resync_to_restart;
234 src->pub.term_source = term_source;
235 src->decoder = this;
236
237#if USE(ICCJPEG)
238 // Retain ICC color profile markers for color management.
239 setup_read_icc_profile(&m_info);
240#endif
241
242 // Keep APP1 blocks, for obtaining exif data.
243 jpeg_save_markers(&m_info, exifMarker, 0xFFFF);
244 }
245
246 ~JPEGImageReader()
247 {
248 close();
249 }
250
251 void close()
252 {
253 decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
254 if (src)
255 fastFree(src);
256 m_info.src = 0;
257
258 jpeg_destroy_decompress(&m_info);
259 }
260
261 void skipBytes(long numBytes)
262 {
263 decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
264 long bytesToSkip = std::min(numBytes, (long)src->pub.bytes_in_buffer);
265 src->pub.bytes_in_buffer -= (size_t)bytesToSkip;
266 src->pub.next_input_byte += bytesToSkip;
267
268 m_bytesToSkip = std::max(numBytes - bytesToSkip, static_cast<long>(0));
269 }
270
271 bool decode(const SharedBuffer& data, bool onlySize)
272 {
273 m_decodingSizeOnly = onlySize;
274
275 unsigned newByteCount = data.size() - m_bufferLength;
276 unsigned readOffset = m_bufferLength - m_info.src->bytes_in_buffer;
277
278 m_info.src->bytes_in_buffer += newByteCount;
279 m_info.src->next_input_byte = (JOCTET*)(data.data()) + readOffset;
280
281 // If we still have bytes to skip, try to skip those now.
282 if (m_bytesToSkip)
283 skipBytes(m_bytesToSkip);
284
285 m_bufferLength = data.size();
286
287 // We need to do the setjmp here. Otherwise bad things will happen
288 if (setjmp(m_err.setjmp_buffer))
289 return m_decoder->setFailed();
290
291 switch (m_state) {
292 case JPEG_HEADER:
293 // Read file parameters with jpeg_read_header().
294 if (jpeg_read_header(&m_info, TRUE) == JPEG_SUSPENDED)
295 return false; // I/O suspension.
296
297 switch (m_info.jpeg_color_space) {
298 case JCS_GRAYSCALE:
299 case JCS_RGB:
300 case JCS_YCbCr:
301 // libjpeg can convert GRAYSCALE and YCbCr image pixels to RGB.
302 m_info.out_color_space = rgbOutputColorSpace();
303#if defined(TURBO_JPEG_RGB_SWIZZLE)
304 if (m_info.saw_JFIF_marker)
305 break;
306 // FIXME: Swizzle decoding does not support Adobe transform=0
307 // images (yet), so revert to using JSC_RGB in that case.
308 if (m_info.saw_Adobe_marker && !m_info.Adobe_transform)
309 m_info.out_color_space = JCS_RGB;
310#endif
311 break;
312 case JCS_CMYK:
313 case JCS_YCCK:
314 // libjpeg can convert YCCK to CMYK, but neither to RGB, so we
315 // manually convert CMKY to RGB.
316 m_info.out_color_space = JCS_CMYK;
317 break;
318 default:
319 return m_decoder->setFailed();
320 }
321
322 m_state = JPEG_START_DECOMPRESS;
323
324 // We can fill in the size now that the header is available.
325 if (!m_decoder->setSize(IntSize(m_info.image_width, m_info.image_height)))
326 return false;
327
328 m_decoder->setOrientation(readImageOrientation(info()));
329
330 // Don't allocate a giant and superfluous memory buffer when the
331 // image is a sequential JPEG.
332 m_info.buffered_image = jpeg_has_multiple_scans(&m_info);
333
334 // Used to set up image size so arrays can be allocated.
335 jpeg_calc_output_dimensions(&m_info);
336
337 // Make a one-row-high sample array that will go away when done with
338 // image. Always make it big enough to hold an RGB row. Since this
339 // uses the IJG memory manager, it must be allocated before the call
340 // to jpeg_start_compress().
341 // FIXME: note that some output color spaces do not need the samples
342 // buffer. Remove this allocation for those color spaces.
343 m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, JPOOL_IMAGE, m_info.output_width * 4, 1);
344
345 if (m_decodingSizeOnly) {
346 // We can stop here. Reduce our buffer length and available data.
347 m_bufferLength -= m_info.src->bytes_in_buffer;
348 m_info.src->bytes_in_buffer = 0;
349 return true;
350 }
351 // FALL THROUGH
352
353 case JPEG_START_DECOMPRESS:
354 // Set parameters for decompression.
355 // FIXME -- Should reset dct_method and dither mode for final pass
356 // of progressive JPEG.
357 m_info.dct_method = dctMethod();
358 m_info.dither_mode = ditherMode();
359 m_info.do_fancy_upsampling = doFancyUpsampling() ? TRUE : FALSE;
360 m_info.enable_2pass_quant = FALSE;
361 m_info.do_block_smoothing = TRUE;
362
363 // Start decompressor.
364 if (!jpeg_start_decompress(&m_info))
365 return false; // I/O suspension.
366
367 // If this is a progressive JPEG ...
368 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL;
369 // FALL THROUGH
370
371 case JPEG_DECOMPRESS_SEQUENTIAL:
372 if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) {
373
374 if (!m_decoder->outputScanlines())
375 return false; // I/O suspension.
376
377 // If we've completed image output...
378 ASSERT(m_info.output_scanline == m_info.output_height);
379 m_state = JPEG_DONE;
380 }
381 // FALL THROUGH
382
383 case JPEG_DECOMPRESS_PROGRESSIVE:
384 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) {
385 int status;
386 do {
387 status = jpeg_consume_input(&m_info);
388 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI));
389
390 for (;;) {
391 if (!m_info.output_scanline) {
392 int scan = m_info.input_scan_number;
393
394 // If we haven't displayed anything yet
395 // (output_scan_number == 0) and we have enough data for
396 // a complete scan, force output of the last full scan.
397 if (!m_info.output_scan_number && (scan > 1) && (status != JPEG_REACHED_EOI))
398 --scan;
399
400 if (!jpeg_start_output(&m_info, scan))
401 return false; // I/O suspension.
402 }
403
404 if (m_info.output_scanline == 0xffffff)
405 m_info.output_scanline = 0;
406
407 // If outputScanlines() fails, it deletes |this|. Therefore,
408 // copy the decoder pointer and use it to check for failure
409 // to avoid member access in the failure case.
410 JPEGImageDecoder* decoder = m_decoder;
411 if (!decoder->outputScanlines()) {
412 if (decoder->failed()) // Careful; |this| is deleted.
413 return false;
414 if (!m_info.output_scanline)
415 // Didn't manage to read any lines - flag so we
416 // don't call jpeg_start_output() multiple times for
417 // the same scan.
418 m_info.output_scanline = 0xffffff;
419 return false; // I/O suspension.
420 }
421
422 if (m_info.output_scanline == m_info.output_height) {
423 if (!jpeg_finish_output(&m_info))
424 return false; // I/O suspension.
425
426 if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number))
427 break;
428
429 m_info.output_scanline = 0;
430 }
431 }
432
433 m_state = JPEG_DONE;
434 }
435 // FALL THROUGH
436
437 case JPEG_DONE:
438 // Finish decompression.
439 return jpeg_finish_decompress(&m_info);
440
441 case JPEG_ERROR:
442 // We can get here if the constructor failed.
443 return m_decoder->setFailed();
444 }
445
446 return true;
447 }
448
449 jpeg_decompress_struct* info() { return &m_info; }
450 JSAMPARRAY samples() const { return m_samples; }
451 JPEGImageDecoder* decoder() { return m_decoder; }
452
453private:
454 JPEGImageDecoder* m_decoder;
455 unsigned m_bufferLength;
456 int m_bytesToSkip;
457 bool m_decodingSizeOnly;
458
459 jpeg_decompress_struct m_info;
460 decoder_error_mgr m_err;
461 jstate m_state;
462
463 JSAMPARRAY m_samples;
464};
465
466// Override the standard error method in the IJG JPEG decoder code.
467void error_exit(j_common_ptr cinfo)
468{
469 // Return control to the setjmp point.
470 decoder_error_mgr *err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->err);
471 longjmp(err->setjmp_buffer, -1);
472}
473
474void init_source(j_decompress_ptr)
475{
476}
477
478void skip_input_data(j_decompress_ptr jd, long num_bytes)
479{
480 decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
481 src->decoder->skipBytes(num_bytes);
482}
483
484boolean fill_input_buffer(j_decompress_ptr)
485{
486 // Our decode step always sets things up properly, so if this method is ever
487 // called, then we have hit the end of the buffer. A return value of false
488 // indicates that we have no data to supply yet.
489 return FALSE;
490}
491
492void term_source(j_decompress_ptr jd)
493{
494 decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
495 src->decoder->decoder()->jpegComplete();
496}
497
498JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
499 : ScalableImageDecoder(alphaOption, gammaAndColorProfileOption)
500{
501}
502
503JPEGImageDecoder::~JPEGImageDecoder() = default;
504
505bool JPEGImageDecoder::setSize(const IntSize& size)
506{
507 if (!ScalableImageDecoder::setSize(size))
508 return false;
509
510 prepareScaleDataIfNecessary();
511 return true;
512}
513
514ScalableImageDecoderFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index)
515{
516 if (index)
517 return 0;
518
519 if (m_frameBufferCache.isEmpty())
520 m_frameBufferCache.grow(1);
521
522 auto& frame = m_frameBufferCache[0];
523 if (!frame.isComplete())
524 decode(false, isAllDataReceived());
525 return &frame;
526}
527
528bool JPEGImageDecoder::setFailed()
529{
530 m_reader = nullptr;
531 return ScalableImageDecoder::setFailed();
532}
533
534template <J_COLOR_SPACE colorSpace>
535void setPixel(ScalableImageDecoderFrame& buffer, uint32_t* currentAddress, JSAMPARRAY samples, int column)
536{
537 JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4);
538
539 switch (colorSpace) {
540 case JCS_RGB:
541 buffer.backingStore()->setPixel(currentAddress, jsample[0], jsample[1], jsample[2], 0xFF);
542 break;
543 case JCS_CMYK:
544 // Source is 'Inverted CMYK', output is RGB.
545 // See: http://www.easyrgb.com/math.php?MATH=M12#text12
546 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
547 // From CMYK to CMY:
548 // X = X * (1 - K ) + K [for X = C, M, or Y]
549 // Thus, from Inverted CMYK to CMY is:
550 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
551 // From CMY (0..1) to RGB (0..1):
552 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar]
553 unsigned k = jsample[3];
554 buffer.backingStore()->setPixel(currentAddress, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
555 break;
556 }
557}
558
559template <J_COLOR_SPACE colorSpace, bool isScaled>
560bool JPEGImageDecoder::outputScanlines(ScalableImageDecoderFrame& buffer)
561{
562 JSAMPARRAY samples = m_reader->samples();
563 jpeg_decompress_struct* info = m_reader->info();
564 int width = isScaled ? m_scaledColumns.size() : info->output_width;
565
566 while (info->output_scanline < info->output_height) {
567 // jpeg_read_scanlines will increase the scanline counter, so we
568 // save the scanline before calling it.
569 int sourceY = info->output_scanline;
570 /* Request one scanline. Returns 0 or 1 scanlines. */
571 if (jpeg_read_scanlines(info, samples, 1) != 1)
572 return false;
573
574 int destY = scaledY(sourceY);
575 if (destY < 0)
576 continue;
577
578 auto* currentAddress = buffer.backingStore()->pixelAt(0, destY);
579 for (int x = 0; x < width; ++x) {
580 setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
581 ++currentAddress;
582 }
583 }
584 return true;
585}
586
587template <J_COLOR_SPACE colorSpace>
588bool JPEGImageDecoder::outputScanlines(ScalableImageDecoderFrame& buffer)
589{
590 return m_scaled ? outputScanlines<colorSpace, true>(buffer) : outputScanlines<colorSpace, false>(buffer);
591}
592
593bool JPEGImageDecoder::outputScanlines()
594{
595 if (m_frameBufferCache.isEmpty())
596 return false;
597
598 // Initialize the framebuffer if needed.
599 auto& buffer = m_frameBufferCache[0];
600 if (buffer.isInvalid()) {
601 if (!buffer.initialize(scaledSize(), m_premultiplyAlpha))
602 return setFailed();
603 buffer.setDecodingStatus(DecodingStatus::Partial);
604 // The buffer is transparent outside the decoded area while the image is
605 // loading. The completed image will be marked fully opaque in jpegComplete().
606 buffer.setHasAlpha(true);
607 }
608
609 jpeg_decompress_struct* info = m_reader->info();
610
611#if defined(TURBO_JPEG_RGB_SWIZZLE)
612 if (!m_scaled && turboSwizzled(info->out_color_space)) {
613 while (info->output_scanline < info->output_height) {
614 unsigned char* row = reinterpret_cast<unsigned char*>(buffer.backingStore()->pixelAt(0, info->output_scanline));
615 if (jpeg_read_scanlines(info, &row, 1) != 1)
616 return false;
617 }
618 return true;
619 }
620#endif
621
622 switch (info->out_color_space) {
623 // The code inside outputScanlines<int, bool> will be executed
624 // for each pixel, so we want to avoid any extra comparisons there.
625 // That is why we use template and template specializations here so
626 // the proper code will be generated at compile time.
627 case JCS_RGB:
628 return outputScanlines<JCS_RGB>(buffer);
629 case JCS_CMYK:
630 return outputScanlines<JCS_CMYK>(buffer);
631 default:
632 ASSERT_NOT_REACHED();
633 }
634
635 return setFailed();
636}
637
638void JPEGImageDecoder::jpegComplete()
639{
640 if (m_frameBufferCache.isEmpty())
641 return;
642
643 // Hand back an appropriately sized buffer, even if the image ended up being
644 // empty.
645 auto& buffer = m_frameBufferCache[0];
646 buffer.setHasAlpha(false);
647 buffer.setDecodingStatus(DecodingStatus::Complete);
648}
649
650void JPEGImageDecoder::decode(bool onlySize, bool allDataReceived)
651{
652 if (failed())
653 return;
654
655 if (!m_reader)
656 m_reader = std::make_unique<JPEGImageReader>(this);
657
658 // If we couldn't decode the image but we've received all the data, decoding
659 // has failed.
660 if (!m_reader->decode(*m_data, onlySize) && allDataReceived)
661 setFailed();
662 // If we're done decoding the image, we don't need the JPEGImageReader
663 // anymore. (If we failed, |m_reader| has already been cleared.)
664 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].isComplete()))
665 m_reader = nullptr;
666}
667
668}
669