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

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: Removed changes to ImageFrameGenerator for now 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBA; } 66 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBA; }
67 #else // Output little-endian BGRA pixels. 67 #else // Output little-endian BGRA pixels.
68 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; } 68 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; }
69 #endif 69 #endif
70 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_E XT_RGBA || colorSpace == JCS_EXT_BGRA; } 70 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_E XT_RGBA || colorSpace == JCS_EXT_BGRA; }
71 inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { return turboSwizzled( colorSpace); } 71 inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { return turboSwizzled( colorSpace); }
72 #else 72 #else
73 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; } 73 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; }
74 inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { return false; } 74 inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { return false; }
75 #endif 75 #endif
76 76
Noel Gordon 2014/07/25 15:55:01 I think we need to define yuvOutputColorSpace() so
77 #if USE(LOW_QUALITY_IMAGE_NO_JPEG_DITHERING) 77 #if USE(LOW_QUALITY_IMAGE_NO_JPEG_DITHERING)
78 inline J_DCT_METHOD dctMethod() { return JDCT_IFAST; } 78 inline J_DCT_METHOD dctMethod() { return JDCT_IFAST; }
79 inline J_DITHER_MODE ditherMode() { return JDITHER_NONE; } 79 inline J_DITHER_MODE ditherMode() { return JDITHER_NONE; }
80 #else 80 #else
81 inline J_DCT_METHOD dctMethod() { return JDCT_ISLOW; } 81 inline J_DCT_METHOD dctMethod() { return JDCT_ISLOW; }
82 inline J_DITHER_MODE ditherMode() { return JDITHER_FS; } 82 inline J_DITHER_MODE ditherMode() { return JDITHER_FS; }
83 #endif 83 #endif
84 84
85 #if USE(LOW_QUALITY_IMAGE_NO_JPEG_FANCY_UPSAMPLING) 85 #if USE(LOW_QUALITY_IMAGE_NO_JPEG_FANCY_UPSAMPLING)
86 inline bool doFancyUpsampling() { return false; } 86 inline bool doFancyUpsampling() { return false; }
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 ignoreProfile = true; 235 ignoreProfile = true;
236 236
237 ASSERT(colorProfile.isEmpty()); 237 ASSERT(colorProfile.isEmpty());
238 if (!ignoreProfile) 238 if (!ignoreProfile)
239 colorProfile.append(profileData, profileLength); 239 colorProfile.append(profileData, profileLength);
240 free(profile); 240 free(profile);
241 #endif 241 #endif
242 } 242 }
243 #endif 243 #endif
244 244
245 static void computeUVSize(const jpeg_decompress_struct* info, int* width, int* h eight)
246 {
Noel Gordon 2014/07/25 15:55:01 How about this: make this routine return an IntSiz
sugoi1 2014/07/25 16:56:48 Done.
247 int h = info->cur_comp_info[0]->h_samp_factor;
Noel Gordon 2014/07/25 15:55:01 h -> u?
sugoi1 2014/07/25 16:56:48 In this case: h -> horizontal v -> vertical
248 int v = info->cur_comp_info[0]->v_samp_factor;
249 *width = (info->output_width + h - 1) / h;
250 *height = (info->output_height + v - 1) / v;
251 }
252
245 class JPEGImageReader { 253 class JPEGImageReader {
246 WTF_MAKE_FAST_ALLOCATED; 254 WTF_MAKE_FAST_ALLOCATED;
247 public: 255 public:
248 JPEGImageReader(JPEGImageDecoder* decoder) 256 JPEGImageReader(JPEGImageDecoder* decoder)
249 : m_decoder(decoder) 257 : m_decoder(decoder)
250 , m_bufferLength(0) 258 , m_bufferLength(0)
251 , m_bytesToSkip(0) 259 , m_bytesToSkip(0)
252 , m_state(JPEG_HEADER) 260 , m_state(JPEG_HEADER)
253 , m_samples(0) 261 , m_samples(0)
254 #if USE(QCMSLIB) 262 #if USE(QCMSLIB)
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 if (setjmp(m_err.setjmp_buffer)) 348 if (setjmp(m_err.setjmp_buffer))
341 return m_decoder->setFailed(); 349 return m_decoder->setFailed();
342 350
343 switch (m_state) { 351 switch (m_state) {
344 case JPEG_HEADER: 352 case JPEG_HEADER:
345 // Read file parameters with jpeg_read_header(). 353 // Read file parameters with jpeg_read_header().
346 if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) 354 if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED)
347 return false; // I/O suspension. 355 return false; // I/O suspension.
348 356
349 switch (m_info.jpeg_color_space) { 357 switch (m_info.jpeg_color_space) {
358 case JCS_YCbCr:
359 // libjpeg can convert YCbCr image pixels to RGB.
360 m_info.out_color_space = rgbOutputColorSpace();
361 if (m_decoder->acceleratedYUVDecoding()
Alpha Left Google 2014/07/24 23:30:56 What about by default output RGB and only change o
sugoi1 2014/07/25 02:55:13 Isn't that what's already happening here? RGB is s
Noel Gordon 2014/07/25 15:55:01 The code following here could be moved to it's own
sugoi1 2014/07/25 16:56:48 Already done in current patch
362 && (DCTSIZE == 8)
363 && (m_info.num_components == 3)
364 && (m_info.scale_denom <= 8)
365 && (m_info.cur_comp_info[1]->h_samp_factor == 1)
366 && (m_info.cur_comp_info[1]->v_samp_factor == 1)
367 && (m_info.cur_comp_info[2]->h_samp_factor == 1)
368 && (m_info.cur_comp_info[2]->v_samp_factor == 1)) {
369 int h = m_info.cur_comp_info[0]->h_samp_factor;
370 int v = m_info.cur_comp_info[0]->v_samp_factor;
371 // Only set YUV mode if the format is supported
Alpha Left Google 2014/07/24 22:07:27 nit: period at the end of sentence.
sugoi1 2014/07/24 23:16:37 Acknowledged.
372 // 4:4:4 : (h == 1) && (v == 1)
373 // 4:4:0 : (h == 1) && (v == 2)
374 // 4:2:2 : (h == 2) && (v == 1)
375 // 4:2:0 : (h == 2) && (v == 2)
376 // 4:1:1 : (h == 4) && (v == 1)
377 // 4:1:0 : (h == 4) && (v == 2)
378 if (((h == 1) || (h == 2) || (h == 4)) && ((v == 1) || (v == 2))) {
379 m_info.out_color_space = JCS_YCbCr;
380 m_info.raw_data_out = TRUE;
381 }
382 }
383 break;
350 case JCS_GRAYSCALE: 384 case JCS_GRAYSCALE:
351 case JCS_RGB: 385 case JCS_RGB:
352 case JCS_YCbCr: 386 // 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(); 387 m_info.out_color_space = rgbOutputColorSpace();
355 #if defined(TURBO_JPEG_RGB_SWIZZLE) 388 #if defined(TURBO_JPEG_RGB_SWIZZLE)
356 if (m_info.saw_JFIF_marker) 389 if (m_info.saw_JFIF_marker)
357 break; 390 break;
358 // FIXME: Swizzle decoding does not support Adobe transform=0 391 // FIXME: Swizzle decoding does not support Adobe transform=0
359 // images (yet), so revert to using JSC_RGB in that case. 392 // images (yet), so revert to using JSC_RGB in that case.
360 if (m_info.saw_Adobe_marker && !m_info.Adobe_transform) 393 if (m_info.saw_Adobe_marker && !m_info.Adobe_transform)
361 m_info.out_color_space = JCS_RGB; 394 m_info.out_color_space = JCS_RGB;
362 #endif 395 #endif
363 break; 396 break;
(...skipping 16 matching lines...) Expand all
380 // Calculate and set decoded size. 413 // Calculate and set decoded size.
381 m_info.scale_num = m_decoder->desiredScaleNumerator(); 414 m_info.scale_num = m_decoder->desiredScaleNumerator();
382 m_info.scale_denom = scaleDenominator; 415 m_info.scale_denom = scaleDenominator;
383 jpeg_calc_output_dimensions(&m_info); 416 jpeg_calc_output_dimensions(&m_info);
384 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height) ; 417 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height) ;
385 418
386 m_decoder->setOrientation(readImageOrientation(info())); 419 m_decoder->setOrientation(readImageOrientation(info()));
387 420
388 #if USE(QCMSLIB) 421 #if USE(QCMSLIB)
389 // Allow color management of the decoded RGBA pixels if possible. 422 // Allow color management of the decoded RGBA pixels if possible.
390 if (!m_decoder->ignoresGammaAndColorProfile()) { 423 if (!m_decoder->ignoresGammaAndColorProfile()) {
Noel Gordon 2014/07/25 15:55:01 Most web jpeg images are YCbCr, and many are photo
sugoi1 2014/07/25 17:20:26 Oh yeah, I know about the color profiles, I don't
391 ColorProfile colorProfile; 424 ColorProfile colorProfile;
392 readColorProfile(info(), colorProfile); 425 readColorProfile(info(), colorProfile);
393 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out _color_space)); 426 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out _color_space));
394 #if defined(TURBO_JPEG_RGB_SWIZZLE) 427 #if defined(TURBO_JPEG_RGB_SWIZZLE)
395 // Input RGBA data to qcms. Note: restored to BGRA on output. 428 // Input RGBA data to qcms. Note: restored to BGRA on output.
396 if (m_transform && m_info.out_color_space == JCS_EXT_BGRA) 429 if (m_transform && m_info.out_color_space == JCS_EXT_BGRA)
397 m_info.out_color_space = JCS_EXT_RGBA; 430 m_info.out_color_space = JCS_EXT_RGBA;
398 #endif 431 #endif
399 m_decoder->setHasColorProfile(!!m_transform); 432 m_decoder->setHasColorProfile(!!m_transform);
400 } 433 }
(...skipping 19 matching lines...) Expand all
420 m_info.do_fancy_upsampling = doFancyUpsampling(); 453 m_info.do_fancy_upsampling = doFancyUpsampling();
421 m_info.enable_2pass_quant = false; 454 m_info.enable_2pass_quant = false;
422 m_info.do_block_smoothing = true; 455 m_info.do_block_smoothing = true;
423 456
424 // Make a one-row-high sample array that will go away when done with 457 // 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 458 // 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 459 // uses the IJG memory manager, it must be allocated before the call
427 // to jpeg_start_compress(). 460 // to jpeg_start_compress().
428 // FIXME: note that some output color spaces do not need the samples 461 // FIXME: note that some output color spaces do not need the samples
429 // buffer. Remove this allocation for those color spaces. 462 // 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); 463 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 464
432 // Start decompressor. 465 // Start decompressor.
433 if (!jpeg_start_decompress(&m_info)) 466 if (!jpeg_start_decompress(&m_info))
434 return false; // I/O suspension. 467 return false; // I/O suspension.
435 468
436 // If this is a progressive JPEG ... 469 // If this is a progressive JPEG ...
437 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JP EG_DECOMPRESS_SEQUENTIAL; 470 m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JP EG_DECOMPRESS_SEQUENTIAL;
438 // FALL THROUGH 471 // FALL THROUGH
439 472
440 case JPEG_DECOMPRESS_SEQUENTIAL: 473 case JPEG_DECOMPRESS_SEQUENTIAL:
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 { 623 {
591 decoder_source_mgr *src = (decoder_source_mgr *)jd->src; 624 decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
592 src->decoder->decoder()->jpegComplete(); 625 src->decoder->decoder()->jpegComplete();
593 } 626 }
594 627
595 JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption, 628 JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption,
596 ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption, 629 ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption,
597 size_t maxDecodedBytes) 630 size_t maxDecodedBytes)
598 : ImageDecoder(alphaOption, gammaAndColorProfileOption, maxDecodedBytes) 631 : ImageDecoder(alphaOption, gammaAndColorProfileOption, maxDecodedBytes)
599 , m_hasColorProfile(false) 632 , m_hasColorProfile(false)
633 , m_acceleratedYUVDecoding(false)
600 { 634 {
601 } 635 }
602 636
603 JPEGImageDecoder::~JPEGImageDecoder() 637 JPEGImageDecoder::~JPEGImageDecoder()
604 { 638 {
605 } 639 }
606 640
607 bool JPEGImageDecoder::isSizeAvailable() 641 bool JPEGImageDecoder::isSizeAvailable()
608 { 642 {
609 if (!ImageDecoder::isSizeAvailable()) 643 if (!ImageDecoder::isSizeAvailable())
(...skipping 12 matching lines...) Expand all
622 656
623 setDecodedSize(width, height); 657 setDecodedSize(width, height);
624 return true; 658 return true;
625 } 659 }
626 660
627 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) 661 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height)
628 { 662 {
629 m_decodedSize = IntSize(width, height); 663 m_decodedSize = IntSize(width, height);
630 } 664 }
631 665
666 IntSize JPEGImageDecoder::decodedSize(int component) const
667 {
Noel Gordon 2014/07/25 15:55:01 Did you consider using a separate function that ex
sugoi1 2014/07/25 16:56:48 Already done in current patch.
668 if (((component == 1) || (component == 2)) && m_reader.get()) { // Asking fo r U or V
669 const jpeg_decompress_struct* info = m_reader->info();
670 if (info && (info->out_color_space == JCS_YCbCr)) {
671 int w, h;
672 computeUVSize(info, &w, &h);
673 return IntSize(w, h);
674 }
675 }
676
677 return m_decodedSize;
678 }
679
632 unsigned JPEGImageDecoder::desiredScaleNumerator() const 680 unsigned JPEGImageDecoder::desiredScaleNumerator() const
633 { 681 {
634 size_t originalBytes = size().width() * size().height() * 4; 682 size_t originalBytes = size().width() * size().height() * 4;
635 if (originalBytes <= m_maxDecodedBytes) { 683 if (originalBytes <= m_maxDecodedBytes) {
636 return scaleDenominator; 684 return scaleDenominator;
637 } 685 }
638 686
639 // Downsample according to the maximum decoded size. 687 // Downsample according to the maximum decoded size.
640 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt( 688 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt(
641 // MSVC needs explicit parameter type for sqrt(). 689 // MSVC needs explicit parameter type for sqrt().
642 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat or / originalBytes)))); 690 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat or / originalBytes))));
643 691
644 return scaleNumerator; 692 return scaleNumerator;
645 } 693 }
646 694
695 bool JPEGImageDecoder::doAcceleratedYUVDecoding()
696 {
Noel Gordon 2014/07/25 15:55:01 Would yuvDecode() or decodeToYUV() better describe
sugoi1 2014/07/25 16:56:48 Accelerated has already been removed from the name
697 setAcceleratedYUVDecoding(true);
698 PlatformInstrumentation::willDecodeImage("JPEG");
699 decode(false);
700 PlatformInstrumentation::didDecodeImage();
701 return !failed();
702 }
703
647 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index) 704 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index)
648 { 705 {
649 if (index) 706 if (index)
650 return 0; 707 return 0;
651 708
652 if (m_frameBufferCache.isEmpty()) { 709 if (m_frameBufferCache.isEmpty()) {
653 m_frameBufferCache.resize(1); 710 m_frameBufferCache.resize(1);
654 m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); 711 m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
655 } 712 }
656 713
657 ImageFrame& frame = m_frameBufferCache[0]; 714 ImageFrame& frame = m_frameBufferCache[0];
658 if (frame.status() != ImageFrame::FrameComplete) { 715 if (frame.status() != ImageFrame::FrameComplete) {
659 PlatformInstrumentation::willDecodeImage("JPEG"); 716 PlatformInstrumentation::willDecodeImage("JPEG");
660 decode(false); 717 decode(false);
661 PlatformInstrumentation::didDecodeImage(); 718 PlatformInstrumentation::didDecodeImage();
662 } 719 }
663 720
664 frame.notifyBitmapIfPixelsChanged(); 721 frame.notifyBitmapIfPixelsChanged();
665 return &frame; 722 return &frame;
666 } 723 }
667 724
668 bool JPEGImageDecoder::setFailed() 725 bool JPEGImageDecoder::setFailed()
669 { 726 {
670 m_reader.clear(); 727 m_reader.clear();
671 return ImageDecoder::setFailed(); 728 return ImageDecoder::setFailed();
672 } 729 }
673 730
731 void JPEGImageDecoder::setDecodingBuffers(OwnPtr<DecodingBuffers>& decodingBuffe rs)
732 {
733 m_decodingBuffers = decodingBuffers.release();
734 }
735
674 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame ::PixelData* pixel, JSAMPARRAY samples, int column) 736 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame ::PixelData* pixel, JSAMPARRAY samples, int column)
675 { 737 {
676 JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4); 738 ASSERT_NOT_REACHED();
739 }
677 740
678 switch (colorSpace) { 741 template <> void setPixel<JCS_RGB>(ImageFrame& buffer, ImageFrame::PixelData* pi xel, JSAMPARRAY samples, int column)
Noel Gordon 2014/07/25 15:55:01 The setPixel() code from lines 736-762 changed, I'
sugoi1 2014/07/25 16:56:48 This is cleanup. Using template arguments in condi
679 case JCS_RGB: 742 {
680 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); 743 JSAMPLE* jsample = *samples + column * 3;
681 break; 744 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255);
682 case JCS_CMYK: 745 }
683 // Source is 'Inverted CMYK', output is RGB. 746
684 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 747 template <> void setPixel<JCS_CMYK>(ImageFrame& buffer, ImageFrame::PixelData* p ixel, JSAMPARRAY samples, int column)
685 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb 748 {
686 // From CMYK to CMY: 749 JSAMPLE* jsample = *samples + column * 4;
687 // X = X * (1 - K ) + K [for X = C, M, or Y] 750
688 // Thus, from Inverted CMYK to CMY is: 751 // Source is 'Inverted CMYK', output is RGB.
689 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK 752 // See: http://www.easyrgb.com/math.php?MATH=M12#text12
690 // From CMY (0..1) to RGB (0..1): 753 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
691 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] 754 // From CMYK to CMY:
692 unsigned k = jsample[3]; 755 // 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); 756 // Thus, from Inverted CMYK to CMY is:
694 break; 757 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
695 } 758 // From CMY (0..1) to RGB (0..1):
759 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar]
760 unsigned k = jsample[3];
761 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample [2] * k / 255, 255);
696 } 762 }
697 763
698 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima geFrame& buffer) 764 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima geFrame& buffer)
699 { 765 {
700 JSAMPARRAY samples = reader->samples(); 766 JSAMPARRAY samples = reader->samples();
701 jpeg_decompress_struct* info = reader->info(); 767 jpeg_decompress_struct* info = reader->info();
702 int width = info->output_width; 768 int width = info->output_width;
703 769
704 while (info->output_scanline < info->output_height) { 770 while (info->output_scanline < info->output_height) {
705 // jpeg_read_scanlines will increase the scanline counter, so we 771 // jpeg_read_scanlines will increase the scanline counter, so we
706 // save the scanline before calling it. 772 // save the scanline before calling it.
707 int y = info->output_scanline; 773 int y = info->output_scanline;
708 // Request one scanline: returns 0 or 1 scanlines. 774 // Request one scanline: returns 0 or 1 scanlines.
709 if (jpeg_read_scanlines(info, samples, 1) != 1) 775 if (jpeg_read_scanlines(info, samples, 1) != 1)
710 return false; 776 return false;
711 #if USE(QCMSLIB) 777 #if USE(QCMSLIB)
712 if (reader->colorTransform() && colorSpace == JCS_RGB) 778 if (reader->colorTransform() && colorSpace == JCS_RGB)
713 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi dth); 779 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi dth);
714 #endif 780 #endif
715 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); 781 ImageFrame::PixelData* pixel = buffer.getAddr(0, y);
716 for (int x = 0; x < width; ++pixel, ++x) 782 for (int x = 0; x < width; ++pixel, ++x)
717 setPixel<colorSpace>(buffer, pixel, samples, x); 783 setPixel<colorSpace>(buffer, pixel, samples, x);
718 } 784 }
719 785
720 buffer.setPixelsChanged(true); 786 buffer.setPixelsChanged(true);
721 return true; 787 return true;
722 } 788 }
723 789
790 static bool outputRawData(JPEGImageReader* reader, DecodingBuffers* decodingBuff ers)
791 {
792 JSAMPARRAY samples = reader->samples();
793 jpeg_decompress_struct* info = reader->info();
794 JSAMPARRAY bufferraw[3];
795 JSAMPROW bufferraw2[32];
796 bufferraw[0] = &bufferraw2[0];
Alpha Left Google 2014/07/24 22:07:27 Please document why.
797 bufferraw[1] = &bufferraw2[16];
798 bufferraw[2] = &bufferraw2[24];
799 int yWidth = info->output_width;
800 int yHeight = info->output_height;
801 int yMaxH = yHeight - 1;
802 int v = info->cur_comp_info[0]->v_samp_factor;
803 int uvWidth(0), uvHeight(0);
804 computeUVSize(info, &uvWidth, &uvHeight);
805 int uvMaxH = uvHeight - 1;
806 JSAMPROW outputY = static_cast<JSAMPROW>(decodingBuffers->getPlane(0));
807 JSAMPROW outputU = static_cast<JSAMPROW>(decodingBuffers->getPlane(1));
808 JSAMPROW outputV = static_cast<JSAMPROW>(decodingBuffers->getPlane(2));
809 size_t rowBytesY = decodingBuffers->getRowBytes(0);
810 size_t rowBytesU = decodingBuffers->getRowBytes(1);
811 size_t rowBytesV = decodingBuffers->getRowBytes(2);
812
813 int scanlinesToRead = DCTSIZE * v;
Alpha Left Google 2014/07/24 22:07:27 nit: This should be yScanlinesToRead.
sugoi1 2014/07/24 23:16:36 Acknowledged.
814 JSAMPROW yLastRow = *samples;
815 JSAMPROW uLastRow = yLastRow + 2 * yWidth;
816 JSAMPROW vLastRow = uLastRow + 2 * yWidth;
817 JSAMPROW dummyRow = vLastRow + 2 * yWidth;
818
819 while (info->output_scanline < info->output_height) {
820 // Request 8 or 16 scanlines: returns 0 or more scanlines.
821 bool hasYLastRow(false), hasUVLastRow(false);
822 for (int i = 0; i < scanlinesToRead; ++i) {
Alpha Left Google 2014/07/24 22:07:27 nit: Add a comment that this is reading the Y scan
sugoi1 2014/07/24 23:16:37 Acknowledged.
823 int scanline = (info->output_scanline + i);
824 if (scanline < yMaxH) {
825 bufferraw2[i] = &outputY[scanline * rowBytesY];
826 } else if (scanline == yMaxH) {
827 bufferraw2[i] = yLastRow;
828 hasYLastRow = true;
829 } else {
830 bufferraw2[i] = dummyRow;
831 }
832 }
833 int scaledScanline = info->output_scanline / v;
834 for (int i = 0; i < 8; ++i) {
Alpha Left Google 2014/07/24 22:07:27 Add a comment saying this is reading the UV scanli
sugoi1 2014/07/24 23:16:36 Acknowledged.
835 int scanline = (scaledScanline + i);
836 if (scanline < uvMaxH) {
837 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
838 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
839 } else if (scanline == uvMaxH) {
840 bufferraw2[16 + i] = uLastRow;
841 bufferraw2[24 + i] = vLastRow;
842 hasUVLastRow = true;
843 } else {
844 bufferraw2[16 + i] = dummyRow;
845 bufferraw2[24 + i] = dummyRow;
846 }
847 }
848 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, scanlines ToRead);
849
850 if (scanlinesRead == 0)
851 return false;
852
853 if (hasYLastRow) {
854 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
Noel Gordon 2014/07/25 15:55:01 memcpy: it's perhaps the best way to kill decoding
sugoi1 2014/07/25 16:56:48 This is only the last row of a jpeg image, if the
855 }
856 if (hasUVLastRow) {
857 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvWidth);
858 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvWidth);
859 }
860 }
861
862 info->output_scanline = std::min(info->output_scanline, info->output_height) ;
863
864 return true;
865 }
866
724 bool JPEGImageDecoder::outputScanlines() 867 bool JPEGImageDecoder::outputScanlines()
725 { 868 {
726 if (m_frameBufferCache.isEmpty()) 869 if (m_frameBufferCache.isEmpty())
727 return false; 870 return false;
Noel Gordon 2014/07/25 15:55:02 If you pass this point and go on to yuv decode, a
728 871
729 jpeg_decompress_struct* info = m_reader->info(); 872 jpeg_decompress_struct* info = m_reader->info();
730 873
874 if ((JCS_YCbCr == info->out_color_space) && (m_decodingBuffers.get())) {
Alpha Left Google 2014/07/24 22:07:27 If you have set YUV decoding but didn't assign the
sugoi1 2014/07/24 23:16:37 If it fails for any reason, the caller should fall
875 return outputRawData(m_reader.get(), m_decodingBuffers.get());
876 }
877
731 // Initialize the framebuffer if needed. 878 // Initialize the framebuffer if needed.
732 ImageFrame& buffer = m_frameBufferCache[0]; 879 ImageFrame& buffer = m_frameBufferCache[0];
733 if (buffer.status() == ImageFrame::FrameEmpty) { 880 if (buffer.status() == ImageFrame::FrameEmpty) {
734 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width ())); 881 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width ()));
735 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig ht())); 882 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig ht()));
736 883
737 if (!buffer.setSize(info->output_width, info->output_height)) 884 if (!buffer.setSize(info->output_width, info->output_height))
738 return setFailed(); 885 return setFailed();
739 buffer.setStatus(ImageFrame::FramePartial); 886 buffer.setStatus(ImageFrame::FramePartial);
740 // The buffer is transparent outside the decoded area while the image is 887 // 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. 945 // has failed.
799 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) 946 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived())
800 setFailed(); 947 setFailed();
801 // If we're done decoding the image, we don't need the JPEGImageReader 948 // If we're done decoding the image, we don't need the JPEGImageReader
802 // anymore. (If we failed, |m_reader| has already been cleared.) 949 // anymore. (If we failed, |m_reader| has already been cleared.)
803 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete)) 950 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete))
804 m_reader.clear(); 951 m_reader.clear();
805 } 952 }
806 953
807 } 954 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698