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 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Lesser General Public | 10 * modify it under the terms of the GNU Lesser General Public |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 #error Blink assumes a little-endian target. | 58 #error Blink assumes a little-endian target. |
59 #endif | 59 #endif |
60 | 60 |
61 #if defined(JCS_ALPHA_EXTENSIONS) | 61 #if defined(JCS_ALPHA_EXTENSIONS) |
62 #define TURBO_JPEG_RGB_SWIZZLE | 62 #define TURBO_JPEG_RGB_SWIZZLE |
63 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android). | 63 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android). |
64 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBA; } | 64 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBA; } |
65 #else // Output little-endian BGRA pixels. | 65 #else // Output little-endian BGRA pixels. |
66 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; } | 66 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; } |
67 #endif | 67 #endif |
68 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_E
XT_RGBA || colorSpace == JCS_EXT_BGRA; } | 68 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_E
XT_RGBA || colorSpace == JCS_EXT_BGRA || colorSpace == JCS_RGB565; } |
69 inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { return turboSwizzled(
colorSpace); } | 69 inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { return turboSwizzled(
colorSpace); } |
70 #else | 70 #else |
71 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; } | 71 inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; } |
72 inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { return false; } | 72 inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { return false; } |
73 #endif | 73 #endif |
74 | 74 |
75 namespace { | 75 namespace { |
76 | 76 |
77 const int exifMarker = JPEG_APP0 + 1; | 77 const int exifMarker = JPEG_APP0 + 1; |
78 | 78 |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 return; | 425 return; |
426 | 426 |
427 // Otherwise, empty the buffer, and leave the position the same, so fill
Buffer continues | 427 // Otherwise, empty the buffer, and leave the position the same, so fill
Buffer continues |
428 // reading from the same position in the new SharedBuffer. | 428 // reading from the same position in the new SharedBuffer. |
429 m_nextReadPosition -= m_info.src->bytes_in_buffer; | 429 m_nextReadPosition -= m_info.src->bytes_in_buffer; |
430 clearBuffer(); | 430 clearBuffer(); |
431 } | 431 } |
432 | 432 |
433 bool decode(bool onlySize) | 433 bool decode(bool onlySize) |
434 { | 434 { |
| 435 if ((m_state == JPEG_DECOMPRESS_SEQUENTIAL || m_state == JPEG_DECOMPRESS
_PROGRESSIVE) |
| 436 && m_decoder->hasFramebufferChanged()) { |
| 437 // when previous attempts to decode failed with not all data availab
le, |
| 438 // decoder continues. Once that all data is available (and there is
no alpha) |
| 439 // and client calls decode to rgb565 or downsampling, it is needed t
o restart decompression |
| 440 // FIXME restart decompression without reading header |
| 441 clearBuffer(); |
| 442 m_state = JPEG_HEADER; |
| 443 } |
| 444 |
435 // We need to do the setjmp here. Otherwise bad things will happen | 445 // We need to do the setjmp here. Otherwise bad things will happen |
436 if (setjmp(m_err.setjmp_buffer)) | 446 if (setjmp(m_err.setjmp_buffer)) |
437 return m_decoder->setFailed(); | 447 return m_decoder->setFailed(); |
438 | 448 |
439 J_COLOR_SPACE overrideColorSpace = JCS_UNKNOWN; | 449 J_COLOR_SPACE overrideColorSpace = JCS_UNKNOWN; |
440 switch (m_state) { | 450 switch (m_state) { |
441 case JPEG_HEADER: | 451 case JPEG_HEADER: |
442 // Read file parameters with jpeg_read_header(). | 452 // Read file parameters with jpeg_read_header(). |
443 if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) | 453 if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) |
444 return false; // I/O suspension. | 454 return false; // I/O suspension. |
(...skipping 20 matching lines...) Expand all Loading... |
465 break; | 475 break; |
466 case JCS_CMYK: | 476 case JCS_CMYK: |
467 case JCS_YCCK: | 477 case JCS_YCCK: |
468 // libjpeg can convert YCCK to CMYK, but neither to RGB, so we | 478 // libjpeg can convert YCCK to CMYK, but neither to RGB, so we |
469 // manually convert CMKY to RGB. | 479 // manually convert CMKY to RGB. |
470 m_info.out_color_space = JCS_CMYK; | 480 m_info.out_color_space = JCS_CMYK; |
471 break; | 481 break; |
472 default: | 482 default: |
473 return m_decoder->setFailed(); | 483 return m_decoder->setFailed(); |
474 } | 484 } |
| 485 if (m_decoder->decodeToRGB565Enabled()) { |
| 486 if (m_info.out_color_space == rgbOutputColorSpace()) { |
| 487 // the rest would need to be converted manually on write |
| 488 #if defined (JCS_ALPHA_EXTENSIONS) |
| 489 m_info.out_color_space = JCS_RGB565; |
| 490 #endif |
| 491 #if USE(QCMSLIB) |
| 492 // if there is colorprofile, use JCS_RGB as QCMS is not supp
orting RGB565 |
| 493 // conversion, RGB->RGB565 happens in outputRows<>() |
| 494 if (!m_decoder->ignoresGammaAndColorProfile()) |
| 495 m_info.out_color_space = JCS_RGB; |
| 496 #endif |
| 497 } |
| 498 } |
| 499 // FALL THROUGH |
475 | 500 |
476 m_state = JPEG_START_DECOMPRESS; | 501 m_state = JPEG_START_DECOMPRESS; |
477 | 502 |
478 // We can fill in the size now that the header is available. | 503 // We can fill in the size now that the header is available. |
479 if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) | 504 if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) |
480 return false; | 505 return false; |
481 | 506 |
482 // Calculate and set decoded size. | 507 // Calculate and set decoded size. |
483 m_info.scale_num = m_decoder->desiredScaleNumerator(); | 508 m_info.scale_num = m_decoder->desiredScaleNumerator(); |
484 m_info.scale_denom = scaleDenominator; | 509 m_info.scale_denom = scaleDenominator; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 return false; // I/O suspension. | 606 return false; // I/O suspension. |
582 | 607 |
583 // If we've completed image output... | 608 // If we've completed image output... |
584 ASSERT(m_info.output_scanline == m_info.output_height); | 609 ASSERT(m_info.output_scanline == m_info.output_height); |
585 m_state = JPEG_DONE; | 610 m_state = JPEG_DONE; |
586 } | 611 } |
587 // FALL THROUGH | 612 // FALL THROUGH |
588 | 613 |
589 case JPEG_DECOMPRESS_PROGRESSIVE: | 614 case JPEG_DECOMPRESS_PROGRESSIVE: |
590 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { | 615 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { |
| 616 |
591 int status = 0; | 617 int status = 0; |
592 do { | 618 do { |
593 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_
mgr*>(m_info.err); | 619 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_
mgr*>(m_info.err); |
594 if (err->num_corrupt_warnings) | 620 if (err->num_corrupt_warnings) |
595 break; | 621 break; |
596 status = jpeg_consume_input(&m_info); | 622 status = jpeg_consume_input(&m_info); |
597 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_E
OI)); | 623 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_E
OI)); |
598 | 624 |
599 for (;;) { | 625 for (;;) { |
600 if (!m_info.output_scanline) { | 626 if (!m_info.output_scanline) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 | 799 |
774 void term_source(j_decompress_ptr jd) | 800 void term_source(j_decompress_ptr jd) |
775 { | 801 { |
776 decoder_source_mgr* src = reinterpret_cast_ptr<decoder_source_mgr*>(jd->src)
; | 802 decoder_source_mgr* src = reinterpret_cast_ptr<decoder_source_mgr*>(jd->src)
; |
777 src->decoder->decoder()->complete(); | 803 src->decoder->decoder()->complete(); |
778 } | 804 } |
779 | 805 |
780 JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfile
Option colorOptions, size_t maxDecodedBytes) | 806 JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfile
Option colorOptions, size_t maxDecodedBytes) |
781 : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) | 807 : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) |
782 , m_hasColorProfile(false) | 808 , m_hasColorProfile(false) |
| 809 , m_decodeColor(ImageFrame::RGBA8888) |
| 810 , m_originalMaxDecodedBytes(maxDecodedBytes) |
783 { | 811 { |
784 } | 812 } |
785 | 813 |
786 JPEGImageDecoder::~JPEGImageDecoder() | 814 JPEGImageDecoder::~JPEGImageDecoder() |
787 { | 815 { |
788 } | 816 } |
789 | 817 |
790 bool JPEGImageDecoder::setSize(unsigned width, unsigned height) | 818 bool JPEGImageDecoder::setSize(unsigned width, unsigned height) |
791 { | 819 { |
792 if (!ImageDecoder::setSize(width, height)) | 820 if (!ImageDecoder::setSize(width, height)) |
(...skipping 21 matching lines...) Expand all Loading... |
814 { | 842 { |
815 ASSERT((component >= 0) && (component <= 2) && m_reader); | 843 ASSERT((component >= 0) && (component <= 2) && m_reader); |
816 const jpeg_decompress_struct* info = m_reader->info(); | 844 const jpeg_decompress_struct* info = m_reader->info(); |
817 | 845 |
818 ASSERT(info->out_color_space == JCS_YCbCr); | 846 ASSERT(info->out_color_space == JCS_YCbCr); |
819 return computeYUVSize(info, component, sizeType); | 847 return computeYUVSize(info, component, sizeType); |
820 } | 848 } |
821 | 849 |
822 unsigned JPEGImageDecoder::desiredScaleNumerator() const | 850 unsigned JPEGImageDecoder::desiredScaleNumerator() const |
823 { | 851 { |
824 size_t originalBytes = size().width() * size().height() * 4; | 852 size_t originalBytes = size().width() * size().height() |
| 853 * (decodeToRGB565Enabled() ? 2 : 4); |
825 if (originalBytes <= m_maxDecodedBytes) { | 854 if (originalBytes <= m_maxDecodedBytes) { |
826 return scaleDenominator; | 855 return scaleDenominator; |
827 } | 856 } |
828 | 857 |
829 // Downsample according to the maximum decoded size. | 858 // Downsample according to the maximum decoded size. |
830 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt( | 859 unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt( |
831 // MSVC needs explicit parameter type for sqrt(). | 860 // MSVC needs explicit parameter type for sqrt(). |
832 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat
or / originalBytes)))); | 861 static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominat
or / originalBytes)))); |
833 | 862 |
834 return scaleNumerator; | 863 return scaleNumerator; |
835 } | 864 } |
836 | 865 |
837 bool JPEGImageDecoder::canDecodeToYUV() | 866 bool JPEGImageDecoder::canDecodeToYUV() |
838 { | 867 { |
839 // Calling isSizeAvailable() ensures the reader is created and the output | 868 // Calling isSizeAvailable() ensures the reader is created and the output |
840 // color space is set. | 869 // color space is set. |
841 return isSizeAvailable() && m_reader->info()->out_color_space == JCS_YCbCr; | 870 return isSizeAvailable() && m_reader->info()->out_color_space == JCS_YCbCr; |
842 } | 871 } |
843 | 872 |
| 873 void JPEGImageDecoder::getAvailableDecodeAndScale(ImageFrame::ColorType* outType
, float* scale, float* lowerScale) |
| 874 { |
| 875 if (outType) { |
| 876 if (*outType != ImageFrame::RGBA8888 && *outType != ImageFrame::RGB565) |
| 877 *outType = ImageFrame::RGBA8888; |
| 878 } |
| 879 if (scale) { |
| 880 unsigned upper = static_cast<unsigned>(ceil(*scale * scaleDenominator)); |
| 881 upper = (upper > scaleDenominator) ? scaleDenominator : upper; |
| 882 unsigned lower = upper - 1; |
| 883 *scale = static_cast<float>(upper) / static_cast<float>(scaleDenominator
); |
| 884 |
| 885 if (lowerScale) |
| 886 *lowerScale = static_cast<float>(lower) / static_cast<float>(scaleDe
nominator); |
| 887 return; |
| 888 } |
| 889 if (lowerScale) |
| 890 *lowerScale = 1.0f; |
| 891 } |
| 892 |
| 893 bool JPEGImageDecoder::activateDecodeAndScale(ImageFrame::ColorType outColor, si
ze_t maxDecodedBytes) |
| 894 { |
| 895 ASSERT(m_decodeColor == ImageFrame::RGBA8888); |
| 896 if (outColor == ImageFrame::RGB565) { |
| 897 m_decodeColor = ImageFrame::RGB565; |
| 898 } else { |
| 899 if (outColor != ImageFrame::RGBA8888) { |
| 900 return false; |
| 901 } |
| 902 m_decodeColor = ImageFrame::RGBA8888; |
| 903 } |
| 904 m_originalMaxDecodedBytes = m_maxDecodedBytes; |
| 905 m_maxDecodedBytes = maxDecodedBytes; |
| 906 return true; |
| 907 } |
| 908 |
| 909 void JPEGImageDecoder::disableDecodeAndScale() |
| 910 { |
| 911 m_decodeColor = ImageFrame::RGBA8888; |
| 912 m_maxDecodedBytes = m_originalMaxDecodedBytes; |
| 913 } |
| 914 |
| 915 bool JPEGImageDecoder::hasFramebufferChanged() const |
| 916 { |
| 917 // for decoding that doesn't restart (e.g. when previous decodings didn't ha
ve |
| 918 // all of the data, and meanwhile decoding to different output size was requ
ested |
| 919 if (m_frameBufferCache.isEmpty() || hasImagePlanes()) { |
| 920 return false; |
| 921 } |
| 922 const ImageFrame& buffer = m_frameBufferCache[0]; |
| 923 // size is important here, not the decoded color - so use the current one |
| 924 // when checking size change |
| 925 if (buffer.status() != ImageFrame::FrameEmpty && !buffer.hasSize(m_decodedSi
ze, m_decodeColor)) |
| 926 return true; |
| 927 return false; |
| 928 } |
| 929 |
| 930 |
844 bool JPEGImageDecoder::decodeToYUV() | 931 bool JPEGImageDecoder::decodeToYUV() |
845 { | 932 { |
846 if (!hasImagePlanes()) | 933 if (!hasImagePlanes()) |
847 return false; | 934 return false; |
848 PlatformInstrumentation::willDecodeImage("JPEG"); | 935 PlatformInstrumentation::willDecodeImage("JPEG"); |
849 decode(false); | 936 decode(false); |
850 PlatformInstrumentation::didDecodeImage(); | 937 PlatformInstrumentation::didDecodeImage(); |
851 return !failed(); | 938 return !failed(); |
852 } | 939 } |
853 | 940 |
854 void JPEGImageDecoder::setImagePlanes(PassOwnPtr<ImagePlanes> imagePlanes) | 941 void JPEGImageDecoder::setImagePlanes(PassOwnPtr<ImagePlanes> imagePlanes) |
855 { | 942 { |
856 m_imagePlanes = imagePlanes; | 943 m_imagePlanes = imagePlanes; |
857 } | 944 } |
858 | 945 |
859 template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame
::PixelData* pixel, JSAMPARRAY samples, int column) | 946 template <J_COLOR_SPACE colorSpace, class T> void setPixel(ImageFrame& buffer, T
* pixel, JSAMPARRAY samples, int column) |
860 { | 947 { |
861 ASSERT_NOT_REACHED(); | 948 ASSERT_NOT_REACHED(); |
862 } | 949 } |
863 | 950 |
864 template <> void setPixel<JCS_RGB>(ImageFrame& buffer, ImageFrame::PixelData* pi
xel, JSAMPARRAY samples, int column) | 951 template <> void setPixel<JCS_RGB, ImageFrame::PixelData>(ImageFrame& buffer, Im
ageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
865 { | 952 { |
866 JSAMPLE* jsample = *samples + column * 3; | 953 JSAMPLE* jsample = *samples + column * 3; |
867 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); | 954 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); |
868 } | 955 } |
869 | 956 |
870 template <> void setPixel<JCS_CMYK>(ImageFrame& buffer, ImageFrame::PixelData* p
ixel, JSAMPARRAY samples, int column) | 957 template <> void setPixel<JCS_CMYK, ImageFrame::PixelData>(ImageFrame& buffer, I
mageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
871 { | 958 { |
872 JSAMPLE* jsample = *samples + column * 4; | 959 JSAMPLE* jsample = *samples + column * 4; |
873 | 960 |
874 // Source is 'Inverted CMYK', output is RGB. | 961 // Source is 'Inverted CMYK', output is RGB. |
875 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 | 962 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 |
876 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb | 963 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb |
877 // From CMYK to CMY: | 964 // From CMYK to CMY: |
878 // X = X * (1 - K ) + K [for X = C, M, or Y] | 965 // X = X * (1 - K ) + K [for X = C, M, or Y] |
879 // Thus, from Inverted CMYK to CMY is: | 966 // Thus, from Inverted CMYK to CMY is: |
880 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK | 967 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK |
881 // From CMY (0..1) to RGB (0..1): | 968 // From CMY (0..1) to RGB (0..1): |
882 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] | 969 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] |
883 unsigned k = jsample[3]; | 970 unsigned k = jsample[3]; |
884 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample
[2] * k / 255, 255); | 971 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample
[2] * k / 255, 255); |
885 } | 972 } |
886 | 973 |
887 template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima
geFrame& buffer) | 974 template <> void setPixel<JCS_RGB, ImageFrame::PixelData16>(ImageFrame& buffer,
ImageFrame::PixelData16* pixel, JSAMPARRAY samples, int column) |
| 975 { |
| 976 JSAMPLE* jsample = *samples + column * 3; |
| 977 buffer.setRGB565(pixel, jsample[0], jsample[1], jsample[2]); |
| 978 } |
| 979 |
| 980 template <> void setPixel<JCS_CMYK, ImageFrame::PixelData16>(ImageFrame& buffer,
ImageFrame::PixelData16* pixel, JSAMPARRAY samples, int column) |
| 981 { |
| 982 JSAMPLE* jsample = *samples + column * 4; |
| 983 |
| 984 // Source is 'Inverted CMYK', output is RGB. |
| 985 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 |
| 986 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb |
| 987 // From CMYK to CMY: |
| 988 // X = X * (1 - K ) + K [for X = C, M, or Y] |
| 989 // Thus, from Inverted CMYK to CMY is: |
| 990 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK |
| 991 // From CMY (0..1) to RGB (0..1): |
| 992 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] |
| 993 unsigned k = jsample[3]; |
| 994 buffer.setRGB565(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample[
2] * k / 255); |
| 995 } |
| 996 |
| 997 template <J_COLOR_SPACE colorSpace, class T> bool outputRows(JPEGImageReader* re
ader, ImageFrame& buffer) |
888 { | 998 { |
889 JSAMPARRAY samples = reader->samples(); | 999 JSAMPARRAY samples = reader->samples(); |
890 jpeg_decompress_struct* info = reader->info(); | 1000 jpeg_decompress_struct* info = reader->info(); |
891 int width = info->output_width; | 1001 int width = info->output_width; |
892 | 1002 |
893 while (info->output_scanline < info->output_height) { | 1003 while (info->output_scanline < info->output_height) { |
894 // jpeg_read_scanlines will increase the scanline counter, so we | 1004 // jpeg_read_scanlines will increase the scanline counter, so we |
895 // save the scanline before calling it. | 1005 // save the scanline before calling it. |
896 int y = info->output_scanline; | 1006 int y = info->output_scanline; |
897 // Request one scanline: returns 0 or 1 scanlines. | 1007 // Request one scanline: returns 0 or 1 scanlines. |
898 if (jpeg_read_scanlines(info, samples, 1) != 1) | 1008 if (jpeg_read_scanlines(info, samples, 1) != 1) |
899 return false; | 1009 return false; |
900 #if USE(QCMSLIB) | 1010 #if USE(QCMSLIB) |
901 if (reader->colorTransform() && colorSpace == JCS_RGB) | 1011 if (reader->colorTransform() && colorSpace == JCS_RGB) |
902 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi
dth); | 1012 qcms_transform_data(reader->colorTransform(), *samples, *samples, wi
dth); |
903 #endif | 1013 #endif |
904 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); | 1014 T* pixel = buffer.getAddrT<T>(0, y); |
905 for (int x = 0; x < width; ++pixel, ++x) | 1015 for (int x = 0; x < width; ++pixel, ++x) |
906 setPixel<colorSpace>(buffer, pixel, samples, x); | 1016 setPixel<colorSpace, T>(buffer, pixel, samples, x); |
907 } | 1017 } |
908 | 1018 |
909 buffer.setPixelsChanged(true); | 1019 buffer.setPixelsChanged(true); |
910 return true; | 1020 return true; |
911 } | 1021 } |
912 | 1022 |
913 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) | 1023 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) |
914 { | 1024 { |
915 JSAMPARRAY samples = reader->samples(); | 1025 JSAMPARRAY samples = reader->samples(); |
916 jpeg_decompress_struct* info = reader->info(); | 1026 jpeg_decompress_struct* info = reader->info(); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 return false; | 1108 return false; |
999 | 1109 |
1000 jpeg_decompress_struct* info = m_reader->info(); | 1110 jpeg_decompress_struct* info = m_reader->info(); |
1001 | 1111 |
1002 // Initialize the framebuffer if needed. | 1112 // Initialize the framebuffer if needed. |
1003 ImageFrame& buffer = m_frameBufferCache[0]; | 1113 ImageFrame& buffer = m_frameBufferCache[0]; |
1004 if (buffer.status() == ImageFrame::FrameEmpty) { | 1114 if (buffer.status() == ImageFrame::FrameEmpty) { |
1005 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width
())); | 1115 ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width
())); |
1006 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig
ht())); | 1116 ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.heig
ht())); |
1007 | 1117 |
1008 if (!buffer.setSize(info->output_width, info->output_height)) | 1118 if (!buffer.setSize(info->output_width, info->output_height, decodeToRGB
565Enabled() |
| 1119 ? ImageFrame::RGB565 : ImageFrame::RGBA8888)) |
1009 return setFailed(); | 1120 return setFailed(); |
1010 buffer.setStatus(ImageFrame::FramePartial); | 1121 buffer.setStatus(ImageFrame::FramePartial); |
1011 // The buffer is transparent outside the decoded area while the image is | 1122 // The buffer is transparent outside the decoded area while the image is |
1012 // loading. The image will be marked fully opaque in complete(). | 1123 // loading. The image will be marked fully opaque in complete(). |
1013 buffer.setHasAlpha(true); | 1124 // For RGB565 this would just fail, having bitmap opaque during decoding |
| 1125 // but, since RGB565 is used only for fully loaded content, this is not
a problem |
| 1126 if (!decodeToRGB565Enabled()) |
| 1127 buffer.setHasAlpha(true); |
1014 | 1128 |
1015 // For JPEGs, the frame always fills the entire image. | 1129 // For JPEGs, the frame always fills the entire image. |
1016 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); | 1130 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); |
1017 } | 1131 } |
1018 | 1132 |
1019 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 1133 #if defined(TURBO_JPEG_RGB_SWIZZLE) |
1020 if (turboSwizzled(info->out_color_space)) { | 1134 if (turboSwizzled(info->out_color_space)) { |
1021 while (info->output_scanline < info->output_height) { | 1135 while (info->output_scanline < info->output_height) { |
1022 unsigned char* row = reinterpret_cast_ptr<unsigned char*>(buffer.get
Addr(0, info->output_scanline)); | 1136 unsigned char* row = decodeToRGB565Enabled() |
1023 if (jpeg_read_scanlines(info, &row, 1) != 1) | 1137 ? reinterpret_cast_ptr<unsigned char*>(buffer.getAddrT<ImageFram
e::PixelData16>(0, info->output_scanline)) |
| 1138 : reinterpret_cast_ptr<unsigned char*>(buffer.getAddr(0, info->o
utput_scanline)); |
| 1139 if (jpeg_read_scanlines(info, &row, 1) != 1) { |
1024 return false; | 1140 return false; |
| 1141 } |
1025 #if USE(QCMSLIB) | 1142 #if USE(QCMSLIB) |
1026 if (qcms_transform* transform = m_reader->colorTransform()) | 1143 if (qcms_transform* transform = m_reader->colorTransform()) |
1027 qcms_transform_data_type(transform, row, row, info->output_width
, rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX); | 1144 qcms_transform_data_type(transform, row, row, info->output_width
, rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX); |
1028 #endif | 1145 #endif |
1029 } | 1146 } |
1030 buffer.setPixelsChanged(true); | 1147 buffer.setPixelsChanged(true); |
1031 return true; | 1148 return true; |
1032 } | 1149 } |
1033 #endif | 1150 #endif |
1034 | 1151 |
1035 switch (info->out_color_space) { | 1152 switch (info->out_color_space) { |
1036 case JCS_RGB: | 1153 case JCS_RGB: |
1037 return outputRows<JCS_RGB>(m_reader.get(), buffer); | 1154 if (decodeToRGB565Enabled()) |
| 1155 return outputRows<JCS_RGB, ImageFrame::PixelData16>(m_reader.get(),
buffer); |
| 1156 return outputRows<JCS_RGB, ImageFrame::PixelData>(m_reader.get(), buffer
); |
1038 case JCS_CMYK: | 1157 case JCS_CMYK: |
1039 return outputRows<JCS_CMYK>(m_reader.get(), buffer); | 1158 if (decodeToRGB565Enabled()) |
| 1159 return outputRows<JCS_CMYK, ImageFrame::PixelData16>(m_reader.get(),
buffer); |
| 1160 return outputRows<JCS_CMYK, ImageFrame::PixelData>(m_reader.get(), buffe
r); |
1040 default: | 1161 default: |
1041 ASSERT_NOT_REACHED(); | 1162 ASSERT_NOT_REACHED(); |
1042 } | 1163 } |
1043 | 1164 |
1044 return setFailed(); | 1165 return setFailed(); |
1045 } | 1166 } |
1046 | 1167 |
1047 void JPEGImageDecoder::complete() | 1168 void JPEGImageDecoder::complete() |
1048 { | 1169 { |
1049 if (m_frameBufferCache.isEmpty()) | 1170 if (m_frameBufferCache.isEmpty()) |
(...skipping 26 matching lines...) Expand all Loading... |
1076 // has failed. | 1197 // has failed. |
1077 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1198 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
1078 setFailed(); | 1199 setFailed(); |
1079 | 1200 |
1080 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1201 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
1081 if (isComplete(this, onlySize) || failed()) | 1202 if (isComplete(this, onlySize) || failed()) |
1082 m_reader.clear(); | 1203 m_reader.clear(); |
1083 } | 1204 } |
1084 | 1205 |
1085 } | 1206 } |
OLD | NEW |