Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

Issue 418653002: Allowing YUV data to be retrieved from the JPEG Decoder. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added missing PLATFORM_EXPORT Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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);
260 }
261
262 static yuv_subsampling getYUVSubsampling(const jpeg_decompress_struct& info)
263 {
Noel Gordon 2014/07/28 07:29:07 yuvSubsampling(...)
sugoi1 2014/08/19 20:28:47 Done.
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
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;
Noel Gordon 2014/07/28 07:29:07 You should somehow record that YCbCr decoding is a
sugoi1 2014/08/19 20:28:47 Done.
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 20 matching lines...) Expand all
384 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height) ; 453 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height) ;
385 454
386 m_decoder->setOrientation(readImageOrientation(info())); 455 m_decoder->setOrientation(readImageOrientation(info()));
387 456
388 #if USE(QCMSLIB) 457 #if USE(QCMSLIB)
389 // Allow color management of the decoded RGBA pixels if possible. 458 // Allow color management of the decoded RGBA pixels if possible.
390 if (!m_decoder->ignoresGammaAndColorProfile()) { 459 if (!m_decoder->ignoresGammaAndColorProfile()) {
391 ColorProfile colorProfile; 460 ColorProfile colorProfile;
392 readColorProfile(info(), colorProfile); 461 readColorProfile(info(), colorProfile);
393 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out _color_space)); 462 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out _color_space));
463 if (m_transform && m_info.out_color_space == JCS_YCbCr) {
Noel Gordon 2014/07/28 07:29:07 ... because this code in this block is broken by a
sugoi1 2014/08/19 20:28:47 Done.
464 m_info.out_color_space = rgbOutputColorSpace();
465 m_info.raw_data_out = FALSE;
466 }
394 #if defined(TURBO_JPEG_RGB_SWIZZLE) 467 #if defined(TURBO_JPEG_RGB_SWIZZLE)
395 // Input RGBA data to qcms. Note: restored to BGRA on output. 468 // Input RGBA data to qcms. Note: restored to BGRA on output.
396 if (m_transform && m_info.out_color_space == JCS_EXT_BGRA) 469 if (m_transform && m_info.out_color_space == JCS_EXT_BGRA)
397 m_info.out_color_space = JCS_EXT_RGBA; 470 m_info.out_color_space = JCS_EXT_RGBA;
398 #endif 471 #endif
399 m_decoder->setHasColorProfile(!!m_transform); 472 m_decoder->setHasColorProfile(!!m_transform);
400 } 473 }
401 #endif 474 #endif
402 // Don't allocate a giant and superfluous memory buffer when the 475 // Don't allocate a giant and superfluous memory buffer when the
Noel Gordon 2014/07/28 07:29:07 ... and make a deferred yuv test around here if
sugoi1 2014/08/19 20:28:47 Done. In that case, the planes wouldn't be used. T
403 // image is a sequential JPEG. 476 // image is a sequential JPEG.
404 m_info.buffered_image = jpeg_has_multiple_scans(&m_info); 477 m_info.buffered_image = jpeg_has_multiple_scans(&m_info);
405 478
406 if (onlySize) { 479 if (onlySize) {
407 // We can stop here. Reduce our buffer length and available data . 480 // We can stop here. Reduce our buffer length and available data .
408 m_bufferLength -= m_info.src->bytes_in_buffer; 481 m_bufferLength -= m_info.src->bytes_in_buffer;
409 m_info.src->bytes_in_buffer = 0; 482 m_info.src->bytes_in_buffer = 0;
410 return true; 483 return true;
411 } 484 }
412 // FALL THROUGH 485 // FALL THROUGH
413 486
414 case JPEG_START_DECOMPRESS: 487 case JPEG_START_DECOMPRESS:
415 // Set parameters for decompression. 488 // Set parameters for decompression.
416 // FIXME -- Should reset dct_method and dither mode for final pass 489 // FIXME -- Should reset dct_method and dither mode for final pass
417 // of progressive JPEG. 490 // of progressive JPEG.
418 m_info.dct_method = dctMethod(); 491 m_info.dct_method = dctMethod();
419 m_info.dither_mode = ditherMode(); 492 m_info.dither_mode = ditherMode();
420 m_info.do_fancy_upsampling = doFancyUpsampling(); 493 m_info.do_fancy_upsampling = doFancyUpsampling();
421 m_info.enable_2pass_quant = false; 494 m_info.enable_2pass_quant = false;
422 m_info.do_block_smoothing = true; 495 m_info.do_block_smoothing = true;
423 496
424 // Make a one-row-high sample array that will go away when done with 497 // 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 498 // 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 499 // uses the IJG memory manager, it must be allocated before the call
427 // to jpeg_start_compress(). 500 // to jpeg_start_compress().
428 // FIXME: note that some output color spaces do not need the samples 501 // FIXME: note that some output color spaces do not need the samples
429 // buffer. Remove this allocation for those color spaces. 502 // 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); 503 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 504
432 // Start decompressor. 505 // Start decompressor.
433 if (!jpeg_start_decompress(&m_info)) 506 if (!jpeg_start_decompress(&m_info))
434 return false; // I/O suspension. 507 return false; // I/O suspension.
435 508
436 // If this is a progressive JPEG ... 509 // If this is a progressive JPEG ...
437 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JP EG_DECOMPRESS_SEQUENTIAL; 510 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JP EG_DECOMPRESS_SEQUENTIAL;
438 // FALL THROUGH 511 // FALL THROUGH
439 512
440 case JPEG_DECOMPRESS_SEQUENTIAL: 513 case JPEG_DECOMPRESS_SEQUENTIAL:
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 695
623 setDecodedSize(width, height); 696 setDecodedSize(width, height);
624 return true; 697 return true;
625 } 698 }
626 699
627 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) 700 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height)
628 { 701 {
629 m_decodedSize = IntSize(width, height); 702 m_decodedSize = IntSize(width, height);
630 } 703 }
631 704
705 IntSize JPEGImageDecoder::decodedYUVSize(int component) const
706 {
707 if (((component == 1) || (component == 2)) && m_reader.get()) { // Asking fo r U or V
708 const jpeg_decompress_struct* info = m_reader->info();
709 if (info && (info->out_color_space == JCS_YCbCr)) {
710 return computeUVSize(info);
711 }
712 }
713
714 return m_decodedSize;
715 }
716
632 unsigned JPEGImageDecoder::desiredScaleNumerator() const 717 unsigned JPEGImageDecoder::desiredScaleNumerator() const
633 { 718 {
634 size_t originalBytes = size().width() * size().height() * 4; 719 size_t originalBytes = size().width() * size().height() * 4;
635 if (originalBytes <= m_maxDecodedBytes) { 720 if (originalBytes <= m_maxDecodedBytes) {
636 return scaleDenominator; 721 return scaleDenominator;
637 } 722 }
638 723
639 // Downsample according to the maximum decoded size. 724 // Downsample according to the maximum decoded size.
640 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt( 725 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt(
641 // MSVC needs explicit parameter type for sqrt(). 726 // MSVC needs explicit parameter type for sqrt().
642 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat or / originalBytes)))); 727 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat or / originalBytes))));
643 728
644 return scaleNumerator; 729 return scaleNumerator;
645 } 730 }
646 731
732 bool JPEGImageDecoder::decodeToYUV()
733 {
734 PlatformInstrumentation::willDecodeImage("JPEG");
735 decode(false);
736 PlatformInstrumentation::didDecodeImage();
737 return !failed();
738 }
739
647 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index) 740 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index)
648 { 741 {
649 if (index) 742 if (index)
650 return 0; 743 return 0;
651 744
652 if (m_frameBufferCache.isEmpty()) { 745 if (m_frameBufferCache.isEmpty()) {
653 m_frameBufferCache.resize(1); 746 m_frameBufferCache.resize(1);
654 m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); 747 m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
655 } 748 }
656 749
657 ImageFrame& frame = m_frameBufferCache[0]; 750 ImageFrame& frame = m_frameBufferCache[0];
658 if (frame.status() != ImageFrame::FrameComplete) { 751 if (frame.status() != ImageFrame::FrameComplete) {
659 PlatformInstrumentation::willDecodeImage("JPEG"); 752 PlatformInstrumentation::willDecodeImage("JPEG");
660 decode(false); 753 decode(false);
661 PlatformInstrumentation::didDecodeImage(); 754 PlatformInstrumentation::didDecodeImage();
662 } 755 }
663 756
664 frame.notifyBitmapIfPixelsChanged(); 757 frame.notifyBitmapIfPixelsChanged();
665 return &frame; 758 return &frame;
666 } 759 }
667 760
668 bool JPEGImageDecoder::setFailed() 761 bool JPEGImageDecoder::setFailed()
669 { 762 {
670 m_reader.clear(); 763 m_reader.clear();
671 return ImageDecoder::setFailed(); 764 return ImageDecoder::setFailed();
672 } 765 }
673 766
767 void JPEGImageDecoder::setImagePlanes(OwnPtr<ImagePlanes>& imagePlanes)
768 {
769 m_imagePlanes = imagePlanes.release();
770 }
771
674 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame ::PixelData* pixel, JSAMPARRAY samples, int column) 772 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame ::PixelData* pixel, JSAMPARRAY samples, int column)
675 { 773 {
676 JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4); 774 ASSERT_NOT_REACHED();
775 }
677 776
678 switch (colorSpace) { 777 template <> void setPixel<JCS_RGB>(ImageFrame& buffer, ImageFrame::PixelData* pi xel, JSAMPARRAY samples, int column)
679 case JCS_RGB: 778 {
680 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); 779 JSAMPLE* jsample = *samples + column * 3;
681 break; 780 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255);
682 case JCS_CMYK: 781 }
683 // Source is 'Inverted CMYK', output is RGB. 782
684 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 783 template <> void setPixel<JCS_CMYK>(ImageFrame& buffer, ImageFrame::PixelData* p ixel, JSAMPARRAY samples, int column)
685 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb 784 {
686 // From CMYK to CMY: 785 JSAMPLE* jsample = *samples + column * 4;
687 // X = X * (1 - K ) + K [for X = C, M, or Y] 786
688 // Thus, from Inverted CMYK to CMY is: 787 // Source is 'Inverted CMYK', output is RGB.
689 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK 788 // See: http://www.easyrgb.com/math.php?MATH=M12#text12
690 // From CMY (0..1) to RGB (0..1): 789 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
691 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] 790 // From CMYK to CMY:
692 unsigned k = jsample[3]; 791 // 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); 792 // Thus, from Inverted CMYK to CMY is:
694 break; 793 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
695 } 794 // From CMY (0..1) to RGB (0..1):
795 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar]
796 unsigned k = jsample[3];
797 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample [2] * k / 255, 255);
696 } 798 }
697 799
698 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima geFrame& buffer) 800 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima geFrame& buffer)
699 { 801 {
700 JSAMPARRAY samples = reader->samples(); 802 JSAMPARRAY samples = reader->samples();
701 jpeg_decompress_struct* info = reader->info(); 803 jpeg_decompress_struct* info = reader->info();
702 int width = info->output_width; 804 int width = info->output_width;
703 805
704 while (info->output_scanline < info->output_height) { 806 while (info->output_scanline < info->output_height) {
705 // jpeg_read_scanlines will increase the scanline counter, so we 807 // jpeg_read_scanlines will increase the scanline counter, so we
706 // save the scanline before calling it. 808 // save the scanline before calling it.
707 int y = info->output_scanline; 809 int y = info->output_scanline;
708 // Request one scanline: returns 0 or 1 scanlines. 810 // Request one scanline: returns 0 or 1 scanlines.
709 if (jpeg_read_scanlines(info, samples, 1) != 1) 811 if (jpeg_read_scanlines(info, samples, 1) != 1)
710 return false; 812 return false;
711 #if USE(QCMSLIB) 813 #if USE(QCMSLIB)
712 if (reader->colorTransform() && colorSpace == JCS_RGB) 814 if (reader->colorTransform() && colorSpace == JCS_RGB)
713 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi dth); 815 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi dth);
714 #endif 816 #endif
715 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); 817 ImageFrame::PixelData* pixel = buffer.getAddr(0, y);
716 for (int x = 0; x < width; ++pixel, ++x) 818 for (int x = 0; x < width; ++pixel, ++x)
717 setPixel<colorSpace>(buffer, pixel, samples, x); 819 setPixel<colorSpace>(buffer, pixel, samples, x);
718 } 820 }
719 821
720 buffer.setPixelsChanged(true); 822 buffer.setPixelsChanged(true);
721 return true; 823 return true;
722 } 824 }
723 825
826 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes)
827 {
828 JSAMPARRAY samples = reader->samples();
829 jpeg_decompress_struct* info = reader->info();
830 JSAMPARRAY bufferraw[3];
831 JSAMPROW bufferraw2[32];
832 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
833 bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
834 bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
835 int yWidth = info->output_width;
836 int yHeight = info->output_height;
837 int yMaxH = yHeight - 1;
838 int v = info->cur_comp_info[0]->v_samp_factor;
839 IntSize uvSize = computeUVSize(info);
840 int uvMaxH = uvSize.height() - 1;
841 JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0));
842 JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1));
843 JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2));
844 size_t rowBytesY = imagePlanes->rowBytes(0);
845 size_t rowBytesU = imagePlanes->rowBytes(1);
846 size_t rowBytesV = imagePlanes->rowBytes(2);
847
848 int yScanlinesToRead = DCTSIZE * v;
849 JSAMPROW yLastRow = *samples;
850 JSAMPROW uLastRow = yLastRow + 2 * yWidth;
851 JSAMPROW vLastRow = uLastRow + 2 * yWidth;
852 JSAMPROW dummyRow = vLastRow + 2 * yWidth;
853
854 while (info->output_scanline < info->output_height) {
855 // Request 8 or 16 scanlines: returns 0 or more scanlines.
856 bool hasYLastRow(false), hasUVLastRow(false);
857 // Assign 8 or 16 rows of memory to read the Y channel.
858 for (int i = 0; i < yScanlinesToRead; ++i) {
859 int scanline = (info->output_scanline + i);
860 if (scanline < yMaxH) {
861 bufferraw2[i] = &outputY[scanline * rowBytesY];
862 } else if (scanline == yMaxH) {
863 bufferraw2[i] = yLastRow;
864 hasYLastRow = true;
865 } else {
866 bufferraw2[i] = dummyRow;
867 }
868 }
869 int scaledScanline = info->output_scanline / v;
870 // Assign 8 rows of memory to read the U and V channels.
871 for (int i = 0; i < 8; ++i) {
872 int scanline = (scaledScanline + i);
873 if (scanline < uvMaxH) {
874 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
875 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
876 } else if (scanline == uvMaxH) {
877 bufferraw2[16 + i] = uLastRow;
878 bufferraw2[24 + i] = vLastRow;
879 hasUVLastRow = true;
880 } else {
881 bufferraw2[16 + i] = dummyRow;
882 bufferraw2[24 + i] = dummyRow;
883 }
884 }
885 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline sToRead);
886
887 if (scanlinesRead == 0)
888 return false;
889
890 if (hasYLastRow) {
891 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
892 }
893 if (hasUVLastRow) {
894 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
895 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
896 }
897 }
898
899 info->output_scanline = std::min(info->output_scanline, info->output_height) ;
900
901 return true;
902 }
903
724 bool JPEGImageDecoder::outputScanlines() 904 bool JPEGImageDecoder::outputScanlines()
725 { 905 {
726 if (m_frameBufferCache.isEmpty()) 906 if (m_frameBufferCache.isEmpty())
727 return false; 907 return false;
728 908
729 jpeg_decompress_struct* info = m_reader->info(); 909 jpeg_decompress_struct* info = m_reader->info();
730 910
911 if (m_imagePlanes.get()) {
Noel Gordon 2014/07/28 07:29:07 Can you have imagePlanes but be decoding into RGBA
sugoi1 2014/08/19 20:28:47 This shouldn't happen. Once the header is read (us
912 return outputRawData(m_reader.get(), m_imagePlanes.get());
913 }
914
731 // Initialize the framebuffer if needed. 915 // Initialize the framebuffer if needed.
732 ImageFrame& buffer = m_frameBufferCache[0]; 916 ImageFrame& buffer = m_frameBufferCache[0];
733 if (buffer.status() == ImageFrame::FrameEmpty) { 917 if (buffer.status() == ImageFrame::FrameEmpty) {
734 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width ())); 918 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width ()));
735 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig ht())); 919 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig ht()));
736 920
737 if (!buffer.setSize(info->output_width, info->output_height)) 921 if (!buffer.setSize(info->output_width, info->output_height))
738 return setFailed(); 922 return setFailed();
739 buffer.setStatus(ImageFrame::FramePartial); 923 buffer.setStatus(ImageFrame::FramePartial);
740 // The buffer is transparent outside the decoded area while the image is 924 // The buffer is transparent outside the decoded area while the image is
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 // has failed. 982 // has failed.
799 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) 983 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived())
800 setFailed(); 984 setFailed();
801 // If we're done decoding the image, we don't need the JPEGImageReader 985 // If we're done decoding the image, we don't need the JPEGImageReader
802 // anymore. (If we failed, |m_reader| has already been cleared.) 986 // anymore. (If we failed, |m_reader| has already been cleared.)
803 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete)) 987 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete))
804 m_reader.clear(); 988 m_reader.clear();
805 } 989 }
806 990
807 } 991 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698