OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2006 Apple Computer, Inc. | 2 * Copyright (C) 2006 Apple Computer, Inc. |
3 * | 3 * |
4 * Portions are Copyright (C) 2001-6 mozilla.org | 4 * Portions are Copyright (C) 2001-6 mozilla.org |
5 * | 5 * |
6 * Other contributors: | 6 * Other contributors: |
7 * Stuart Parmenter <stuart@mozilla.com> | 7 * Stuart Parmenter <stuart@mozilla.com> |
8 * | 8 * |
9 * Copyright (C) 2007-2009 Torch Mobile, Inc. | 9 * Copyright (C) 2007-2009 Torch Mobile, Inc. |
10 * | 10 * |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 | 106 |
107 enum jstate { | 107 enum jstate { |
108 JPEG_HEADER, // Reading JFIF headers | 108 JPEG_HEADER, // Reading JFIF headers |
109 JPEG_START_DECOMPRESS, | 109 JPEG_START_DECOMPRESS, |
110 JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels | 110 JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels |
111 JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels | 111 JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels |
112 JPEG_DONE, | 112 JPEG_DONE, |
113 JPEG_ERROR | 113 JPEG_ERROR |
114 }; | 114 }; |
115 | 115 |
116 enum yuv_subsampling { | |
117 YUV_UNKNOWN, | |
118 YUV_410, | |
119 YUV_411, | |
120 YUV_420, | |
121 YUV_422, | |
122 YUV_440, | |
123 YUV_444 | |
124 }; | |
125 | |
116 void init_source(j_decompress_ptr jd); | 126 void init_source(j_decompress_ptr jd); |
117 boolean fill_input_buffer(j_decompress_ptr jd); | 127 boolean fill_input_buffer(j_decompress_ptr jd); |
118 void skip_input_data(j_decompress_ptr jd, long num_bytes); | 128 void skip_input_data(j_decompress_ptr jd, long num_bytes); |
119 void term_source(j_decompress_ptr jd); | 129 void term_source(j_decompress_ptr jd); |
120 void error_exit(j_common_ptr cinfo); | 130 void error_exit(j_common_ptr cinfo); |
121 | 131 |
122 // Implementation of a JPEG src object that understands our state machine | 132 // Implementation of a JPEG src object that understands our state machine |
123 struct decoder_source_mgr { | 133 struct decoder_source_mgr { |
124 // public fields; must be first in this struct! | 134 // public fields; must be first in this struct! |
125 struct jpeg_source_mgr pub; | 135 struct jpeg_source_mgr pub; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 ignoreProfile = true; | 245 ignoreProfile = true; |
236 | 246 |
237 ASSERT(colorProfile.isEmpty()); | 247 ASSERT(colorProfile.isEmpty()); |
238 if (!ignoreProfile) | 248 if (!ignoreProfile) |
239 colorProfile.append(profileData, profileLength); | 249 colorProfile.append(profileData, profileLength); |
240 free(profile); | 250 free(profile); |
241 #endif | 251 #endif |
242 } | 252 } |
243 #endif | 253 #endif |
244 | 254 |
255 static IntSize computeUVSize(const jpeg_decompress_struct* info) | |
256 { | |
257 int h = info->cur_comp_info[0]->h_samp_factor; | |
258 int v = info->cur_comp_info[0]->v_samp_factor; | |
259 return IntSize((info->output_width + h - 1) / h, (info->output_height + v - 1) / v); | |
Stephen White
2014/07/25 17:10:55
Note: interesting that we have to round up here. T
| |
260 } | |
261 | |
262 static yuv_subsampling getYUVSubsampling(const jpeg_decompress_struct& info) | |
263 { | |
264 if ((DCTSIZE == 8) | |
265 && (info.num_components == 3) | |
266 && (info.scale_denom <= 8) | |
267 && (info.cur_comp_info[1]->h_samp_factor == 1) | |
268 && (info.cur_comp_info[1]->v_samp_factor == 1) | |
269 && (info.cur_comp_info[2]->h_samp_factor == 1) | |
270 && (info.cur_comp_info[2]->v_samp_factor == 1)) { | |
271 int h = info.cur_comp_info[0]->h_samp_factor; | |
272 int v = info.cur_comp_info[0]->v_samp_factor; | |
273 // 4:4:4 : (h == 1) && (v == 1) | |
274 // 4:4:0 : (h == 1) && (v == 2) | |
275 // 4:2:2 : (h == 2) && (v == 1) | |
276 // 4:2:0 : (h == 2) && (v == 2) | |
277 // 4:1:1 : (h == 4) && (v == 1) | |
278 // 4:1:0 : (h == 4) && (v == 2) | |
279 if (v == 1) { | |
280 switch (h) { | |
281 case 1: | |
282 return YUV_444; | |
283 case 2: | |
284 return YUV_422; | |
285 case 4: | |
286 return YUV_411; | |
287 default: | |
288 break; | |
289 } | |
290 } else if (v == 2) { | |
291 switch (h) { | |
292 case 1: | |
293 return YUV_440; | |
294 case 2: | |
295 return YUV_420; | |
296 case 4: | |
297 return YUV_410; | |
298 default: | |
299 break; | |
300 } | |
301 } | |
302 } | |
303 | |
304 return YUV_UNKNOWN; | |
305 } | |
306 | |
245 class JPEGImageReader { | 307 class JPEGImageReader { |
246 WTF_MAKE_FAST_ALLOCATED; | 308 WTF_MAKE_FAST_ALLOCATED; |
247 public: | 309 public: |
248 JPEGImageReader(JPEGImageDecoder* decoder) | 310 JPEGImageReader(JPEGImageDecoder* decoder) |
249 : m_decoder(decoder) | 311 : m_decoder(decoder) |
250 , m_bufferLength(0) | 312 , m_bufferLength(0) |
251 , m_bytesToSkip(0) | 313 , m_bytesToSkip(0) |
252 , m_state(JPEG_HEADER) | 314 , m_state(JPEG_HEADER) |
253 , m_samples(0) | 315 , m_samples(0) |
254 #if USE(QCMSLIB) | 316 #if USE(QCMSLIB) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 if (setjmp(m_err.setjmp_buffer)) | 402 if (setjmp(m_err.setjmp_buffer)) |
341 return m_decoder->setFailed(); | 403 return m_decoder->setFailed(); |
342 | 404 |
343 switch (m_state) { | 405 switch (m_state) { |
344 case JPEG_HEADER: | 406 case JPEG_HEADER: |
345 // Read file parameters with jpeg_read_header(). | 407 // Read file parameters with jpeg_read_header(). |
346 if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) | 408 if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) |
347 return false; // I/O suspension. | 409 return false; // I/O suspension. |
348 | 410 |
349 switch (m_info.jpeg_color_space) { | 411 switch (m_info.jpeg_color_space) { |
412 case JCS_YCbCr: | |
413 // libjpeg can convert YCbCr image pixels to RGB. | |
414 m_info.out_color_space = rgbOutputColorSpace(); | |
415 if (m_decoder->YUVDecoding() && (getYUVSubsampling(m_info) != YU V_UNKNOWN)) { | |
416 m_info.out_color_space = JCS_YCbCr; | |
417 m_info.raw_data_out = TRUE; | |
418 } | |
419 break; | |
350 case JCS_GRAYSCALE: | 420 case JCS_GRAYSCALE: |
351 case JCS_RGB: | 421 case JCS_RGB: |
352 case JCS_YCbCr: | 422 // libjpeg can convert GRAYSCALE image pixels to RGB. |
353 // libjpeg can convert GRAYSCALE and YCbCr image pixels to RGB. | |
354 m_info.out_color_space = rgbOutputColorSpace(); | 423 m_info.out_color_space = rgbOutputColorSpace(); |
355 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 424 #if defined(TURBO_JPEG_RGB_SWIZZLE) |
356 if (m_info.saw_JFIF_marker) | 425 if (m_info.saw_JFIF_marker) |
357 break; | 426 break; |
358 // FIXME: Swizzle decoding does not support Adobe transform=0 | 427 // FIXME: Swizzle decoding does not support Adobe transform=0 |
359 // images (yet), so revert to using JSC_RGB in that case. | 428 // images (yet), so revert to using JSC_RGB in that case. |
360 if (m_info.saw_Adobe_marker && !m_info.Adobe_transform) | 429 if (m_info.saw_Adobe_marker && !m_info.Adobe_transform) |
361 m_info.out_color_space = JCS_RGB; | 430 m_info.out_color_space = JCS_RGB; |
362 #endif | 431 #endif |
363 break; | 432 break; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 m_info.do_fancy_upsampling = doFancyUpsampling(); | 489 m_info.do_fancy_upsampling = doFancyUpsampling(); |
421 m_info.enable_2pass_quant = false; | 490 m_info.enable_2pass_quant = false; |
422 m_info.do_block_smoothing = true; | 491 m_info.do_block_smoothing = true; |
423 | 492 |
424 // Make a one-row-high sample array that will go away when done with | 493 // Make a one-row-high sample array that will go away when done with |
425 // image. Always make it big enough to hold an RGB row. Since this | 494 // image. Always make it big enough to hold an RGB row. Since this |
426 // uses the IJG memory manager, it must be allocated before the call | 495 // uses the IJG memory manager, it must be allocated before the call |
427 // to jpeg_start_compress(). | 496 // to jpeg_start_compress(). |
428 // FIXME: note that some output color spaces do not need the samples | 497 // FIXME: note that some output color spaces do not need the samples |
429 // buffer. Remove this allocation for those color spaces. | 498 // buffer. Remove this allocation for those color spaces. |
430 m_samples = (*m_info.mem->alloc_sarray)(reinterpret_cast<j_common_pt r>(&m_info), JPOOL_IMAGE, m_info.output_width * 4, 1); | 499 m_samples = (*m_info.mem->alloc_sarray)(reinterpret_cast<j_common_pt r>(&m_info), JPOOL_IMAGE, m_info.output_width * 4, m_info.out_color_space == JCS _YCbCr ? 2 : 1); |
431 | 500 |
432 // Start decompressor. | 501 // Start decompressor. |
433 if (!jpeg_start_decompress(&m_info)) | 502 if (!jpeg_start_decompress(&m_info)) |
434 return false; // I/O suspension. | 503 return false; // I/O suspension. |
435 | 504 |
436 // If this is a progressive JPEG ... | 505 // If this is a progressive JPEG ... |
437 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JP EG_DECOMPRESS_SEQUENTIAL; | 506 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JP EG_DECOMPRESS_SEQUENTIAL; |
438 // FALL THROUGH | 507 // FALL THROUGH |
439 | 508 |
440 case JPEG_DECOMPRESS_SEQUENTIAL: | 509 case JPEG_DECOMPRESS_SEQUENTIAL: |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
622 | 691 |
623 setDecodedSize(width, height); | 692 setDecodedSize(width, height); |
624 return true; | 693 return true; |
625 } | 694 } |
626 | 695 |
627 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) | 696 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) |
628 { | 697 { |
629 m_decodedSize = IntSize(width, height); | 698 m_decodedSize = IntSize(width, height); |
630 } | 699 } |
631 | 700 |
701 IntSize JPEGImageDecoder::decodedYUVSize(int component) const | |
702 { | |
703 if (((component == 1) || (component == 2)) && m_reader.get()) { // Asking fo r U or V | |
704 const jpeg_decompress_struct* info = m_reader->info(); | |
705 if (info && (info->out_color_space == JCS_YCbCr)) { | |
706 return computeUVSize(info); | |
707 } | |
708 } | |
709 | |
710 return m_decodedSize; | |
711 } | |
712 | |
632 unsigned JPEGImageDecoder::desiredScaleNumerator() const | 713 unsigned JPEGImageDecoder::desiredScaleNumerator() const |
633 { | 714 { |
634 size_t originalBytes = size().width() * size().height() * 4; | 715 size_t originalBytes = size().width() * size().height() * 4; |
635 if (originalBytes <= m_maxDecodedBytes) { | 716 if (originalBytes <= m_maxDecodedBytes) { |
636 return scaleDenominator; | 717 return scaleDenominator; |
637 } | 718 } |
638 | 719 |
639 // Downsample according to the maximum decoded size. | 720 // Downsample according to the maximum decoded size. |
640 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt( | 721 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt( |
641 // MSVC needs explicit parameter type for sqrt(). | 722 // MSVC needs explicit parameter type for sqrt(). |
642 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat or / originalBytes)))); | 723 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat or / originalBytes)))); |
643 | 724 |
644 return scaleNumerator; | 725 return scaleNumerator; |
645 } | 726 } |
646 | 727 |
728 bool JPEGImageDecoder::decodeToYUV() | |
729 { | |
730 PlatformInstrumentation::willDecodeImage("JPEG"); | |
731 decode(false); | |
732 PlatformInstrumentation::didDecodeImage(); | |
733 return !failed(); | |
734 } | |
735 | |
647 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index) | 736 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index) |
648 { | 737 { |
649 if (index) | 738 if (index) |
650 return 0; | 739 return 0; |
651 | 740 |
652 if (m_frameBufferCache.isEmpty()) { | 741 if (m_frameBufferCache.isEmpty()) { |
653 m_frameBufferCache.resize(1); | 742 m_frameBufferCache.resize(1); |
654 m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); | 743 m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); |
655 } | 744 } |
656 | 745 |
657 ImageFrame& frame = m_frameBufferCache[0]; | 746 ImageFrame& frame = m_frameBufferCache[0]; |
658 if (frame.status() != ImageFrame::FrameComplete) { | 747 if (frame.status() != ImageFrame::FrameComplete) { |
659 PlatformInstrumentation::willDecodeImage("JPEG"); | 748 PlatformInstrumentation::willDecodeImage("JPEG"); |
660 decode(false); | 749 decode(false); |
661 PlatformInstrumentation::didDecodeImage(); | 750 PlatformInstrumentation::didDecodeImage(); |
662 } | 751 } |
663 | 752 |
664 frame.notifyBitmapIfPixelsChanged(); | 753 frame.notifyBitmapIfPixelsChanged(); |
665 return &frame; | 754 return &frame; |
666 } | 755 } |
667 | 756 |
668 bool JPEGImageDecoder::setFailed() | 757 bool JPEGImageDecoder::setFailed() |
669 { | 758 { |
670 m_reader.clear(); | 759 m_reader.clear(); |
671 return ImageDecoder::setFailed(); | 760 return ImageDecoder::setFailed(); |
672 } | 761 } |
673 | 762 |
763 void JPEGImageDecoder::setImagePlanes(OwnPtr<ImagePlanes>& imagePlanes) | |
764 { | |
765 m_imagePlanes = imagePlanes.release(); | |
766 } | |
767 | |
674 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame ::PixelData* pixel, JSAMPARRAY samples, int column) | 768 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame ::PixelData* pixel, JSAMPARRAY samples, int column) |
675 { | 769 { |
676 JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4); | 770 ASSERT_NOT_REACHED(); |
771 } | |
677 | 772 |
678 switch (colorSpace) { | 773 template <> void setPixel<JCS_RGB>(ImageFrame& buffer, ImageFrame::PixelData* pi xel, JSAMPARRAY samples, int column) |
679 case JCS_RGB: | 774 { |
680 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); | 775 JSAMPLE* jsample = *samples + column * 3; |
681 break; | 776 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); |
682 case JCS_CMYK: | 777 } |
683 // Source is 'Inverted CMYK', output is RGB. | 778 |
684 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 | 779 template <> void setPixel<JCS_CMYK>(ImageFrame& buffer, ImageFrame::PixelData* p ixel, JSAMPARRAY samples, int column) |
685 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb | 780 { |
686 // From CMYK to CMY: | 781 JSAMPLE* jsample = *samples + column * 4; |
687 // X = X * (1 - K ) + K [for X = C, M, or Y] | 782 |
688 // Thus, from Inverted CMYK to CMY is: | 783 // Source is 'Inverted CMYK', output is RGB. |
689 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK | 784 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 |
690 // From CMY (0..1) to RGB (0..1): | 785 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb |
691 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] | 786 // From CMYK to CMY: |
692 unsigned k = jsample[3]; | 787 // X = X * (1 - K ) + K [for X = C, M, or Y] |
693 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsa mple[2] * k / 255, 255); | 788 // Thus, from Inverted CMYK to CMY is: |
694 break; | 789 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK |
695 } | 790 // From CMY (0..1) to RGB (0..1): |
791 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] | |
792 unsigned k = jsample[3]; | |
793 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample [2] * k / 255, 255); | |
696 } | 794 } |
697 | 795 |
698 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima geFrame& buffer) | 796 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima geFrame& buffer) |
699 { | 797 { |
700 JSAMPARRAY samples = reader->samples(); | 798 JSAMPARRAY samples = reader->samples(); |
701 jpeg_decompress_struct* info = reader->info(); | 799 jpeg_decompress_struct* info = reader->info(); |
702 int width = info->output_width; | 800 int width = info->output_width; |
703 | 801 |
704 while (info->output_scanline < info->output_height) { | 802 while (info->output_scanline < info->output_height) { |
705 // jpeg_read_scanlines will increase the scanline counter, so we | 803 // jpeg_read_scanlines will increase the scanline counter, so we |
706 // save the scanline before calling it. | 804 // save the scanline before calling it. |
707 int y = info->output_scanline; | 805 int y = info->output_scanline; |
708 // Request one scanline: returns 0 or 1 scanlines. | 806 // Request one scanline: returns 0 or 1 scanlines. |
709 if (jpeg_read_scanlines(info, samples, 1) != 1) | 807 if (jpeg_read_scanlines(info, samples, 1) != 1) |
710 return false; | 808 return false; |
711 #if USE(QCMSLIB) | 809 #if USE(QCMSLIB) |
712 if (reader->colorTransform() && colorSpace == JCS_RGB) | 810 if (reader->colorTransform() && colorSpace == JCS_RGB) |
713 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi dth); | 811 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi dth); |
714 #endif | 812 #endif |
715 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); | 813 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); |
716 for (int x = 0; x < width; ++pixel, ++x) | 814 for (int x = 0; x < width; ++pixel, ++x) |
717 setPixel<colorSpace>(buffer, pixel, samples, x); | 815 setPixel<colorSpace>(buffer, pixel, samples, x); |
718 } | 816 } |
719 | 817 |
720 buffer.setPixelsChanged(true); | 818 buffer.setPixelsChanged(true); |
721 return true; | 819 return true; |
722 } | 820 } |
723 | 821 |
822 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) | |
823 { | |
824 JSAMPARRAY samples = reader->samples(); | |
825 jpeg_decompress_struct* info = reader->info(); | |
826 JSAMPARRAY bufferraw[3]; | |
827 JSAMPROW bufferraw2[32]; | |
828 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) | |
829 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) | |
830 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) | |
831 int yWidth = info->output_width; | |
832 int yHeight = info->output_height; | |
833 int yMaxH = yHeight - 1; | |
834 int v = info->cur_comp_info[0]->v_samp_factor; | |
835 IntSize uvSize = computeUVSize(info); | |
836 int uvMaxH = uvSize.height() - 1; | |
837 JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0)); | |
838 JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1)); | |
839 JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2)); | |
840 size_t rowBytesY = imagePlanes->rowBytes(0); | |
841 size_t rowBytesU = imagePlanes->rowBytes(1); | |
842 size_t rowBytesV = imagePlanes->rowBytes(2); | |
843 | |
844 int yScanlinesToRead = DCTSIZE * v; | |
845 JSAMPROW yLastRow = *samples; | |
846 JSAMPROW uLastRow = yLastRow + 2 * yWidth; | |
847 JSAMPROW vLastRow = uLastRow + 2 * yWidth; | |
848 JSAMPROW dummyRow = vLastRow + 2 * yWidth; | |
849 | |
850 while (info->output_scanline < info->output_height) { | |
851 // Request 8 or 16 scanlines: returns 0 or more scanlines. | |
852 bool hasYLastRow(false), hasUVLastRow(false); | |
853 // Assign 8 or 16 rows of memory to read the Y channel. | |
854 for (int i = 0; i < yScanlinesToRead; ++i) { | |
855 int scanline = (info->output_scanline + i); | |
856 if (scanline < yMaxH) { | |
857 bufferraw2[i] = &outputY[scanline * rowBytesY]; | |
858 } else if (scanline == yMaxH) { | |
859 bufferraw2[i] = yLastRow; | |
860 hasYLastRow = true; | |
861 } else { | |
862 bufferraw2[i] = dummyRow; | |
863 } | |
864 } | |
865 int scaledScanline = info->output_scanline / v; | |
866 // Assign 8 rows of memory to read the U and V channels. | |
867 for (int i = 0; i < 8; ++i) { | |
868 int scanline = (scaledScanline + i); | |
869 if (scanline < uvMaxH) { | |
870 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; | |
871 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; | |
872 } else if (scanline == uvMaxH) { | |
873 bufferraw2[16 + i] = uLastRow; | |
874 bufferraw2[24 + i] = vLastRow; | |
875 hasUVLastRow = true; | |
876 } else { | |
877 bufferraw2[16 + i] = dummyRow; | |
878 bufferraw2[24 + i] = dummyRow; | |
879 } | |
880 } | |
881 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline sToRead); | |
882 | |
883 if (scanlinesRead == 0) | |
884 return false; | |
885 | |
886 if (hasYLastRow) { | |
887 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); | |
888 } | |
889 if (hasUVLastRow) { | |
890 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); | |
891 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width()); | |
892 } | |
893 } | |
894 | |
895 info->output_scanline = std::min(info->output_scanline, info->output_height) ; | |
896 | |
897 return true; | |
898 } | |
899 | |
724 bool JPEGImageDecoder::outputScanlines() | 900 bool JPEGImageDecoder::outputScanlines() |
725 { | 901 { |
726 if (m_frameBufferCache.isEmpty()) | 902 if (m_frameBufferCache.isEmpty()) |
727 return false; | 903 return false; |
728 | 904 |
729 jpeg_decompress_struct* info = m_reader->info(); | 905 jpeg_decompress_struct* info = m_reader->info(); |
730 | 906 |
907 if (m_imagePlanes.get()) { | |
908 return outputRawData(m_reader.get(), m_imagePlanes.get()); | |
909 } | |
910 | |
731 // Initialize the framebuffer if needed. | 911 // Initialize the framebuffer if needed. |
732 ImageFrame& buffer = m_frameBufferCache[0]; | 912 ImageFrame& buffer = m_frameBufferCache[0]; |
733 if (buffer.status() == ImageFrame::FrameEmpty) { | 913 if (buffer.status() == ImageFrame::FrameEmpty) { |
734 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width ())); | 914 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width ())); |
735 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig ht())); | 915 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig ht())); |
736 | 916 |
737 if (!buffer.setSize(info->output_width, info->output_height)) | 917 if (!buffer.setSize(info->output_width, info->output_height)) |
738 return setFailed(); | 918 return setFailed(); |
739 buffer.setStatus(ImageFrame::FramePartial); | 919 buffer.setStatus(ImageFrame::FramePartial); |
740 // The buffer is transparent outside the decoded area while the image is | 920 // The buffer is transparent outside the decoded area while the image is |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
798 // has failed. | 978 // has failed. |
799 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) | 979 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) |
800 setFailed(); | 980 setFailed(); |
801 // If we're done decoding the image, we don't need the JPEGImageReader | 981 // If we're done decoding the image, we don't need the JPEGImageReader |
802 // anymore. (If we failed, |m_reader| has already been cleared.) | 982 // anymore. (If we failed, |m_reader| has already been cleared.) |
803 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete)) | 983 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete)) |
804 m_reader.clear(); | 984 m_reader.clear(); |
805 } | 985 } |
806 | 986 |
807 } | 987 } |
OLD | NEW |