| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include "wtf/PtrUtil.h" | 42 #include "wtf/PtrUtil.h" |
| 43 #include "wtf/Threading.h" | 43 #include "wtf/Threading.h" |
| 44 #include <memory> | 44 #include <memory> |
| 45 | 45 |
| 46 extern "C" { | 46 extern "C" { |
| 47 #include <stdio.h> // jpeglib.h needs stdio FILE. | 47 #include <stdio.h> // jpeglib.h needs stdio FILE. |
| 48 #include "jpeglib.h" | 48 #include "jpeglib.h" |
| 49 #if USE(ICCJPEG) | 49 #if USE(ICCJPEG) |
| 50 #include "iccjpeg.h" | 50 #include "iccjpeg.h" |
| 51 #endif | 51 #endif |
| 52 #if USE(QCMSLIB) | |
| 53 #include "qcms.h" | |
| 54 #endif | |
| 55 #include <setjmp.h> | 52 #include <setjmp.h> |
| 56 } | 53 } |
| 57 | 54 |
| 58 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) | 55 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) |
| 59 #error Blink assumes a little-endian target. | 56 #error Blink assumes a little-endian target. |
| 60 #endif | 57 #endif |
| 61 | 58 |
| 62 #if defined(JCS_ALPHA_EXTENSIONS) | 59 #if defined(JCS_ALPHA_EXTENSIONS) |
| 63 #define TURBO_JPEG_RGB_SWIZZLE | 60 #define TURBO_JPEG_RGB_SWIZZLE |
| 64 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android). | 61 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android). |
| 65 inline J_COLOR_SPACE rgbOutputColorSpace() { | 62 inline J_COLOR_SPACE rgbOutputColorSpace() { |
| 66 return JCS_EXT_RGBA; | 63 return JCS_EXT_RGBA; |
| 67 } | 64 } |
| 68 #else // Output little-endian BGRA pixels. | 65 #else // Output little-endian BGRA pixels. |
| 69 inline J_COLOR_SPACE rgbOutputColorSpace() { | 66 inline J_COLOR_SPACE rgbOutputColorSpace() { |
| 70 return JCS_EXT_BGRA; | 67 return JCS_EXT_BGRA; |
| 71 } | 68 } |
| 72 #endif | 69 #endif |
| 73 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { | 70 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { |
| 74 return colorSpace == JCS_EXT_RGBA || colorSpace == JCS_EXT_BGRA; | 71 return colorSpace == JCS_EXT_RGBA || colorSpace == JCS_EXT_BGRA; |
| 75 } | 72 } |
| 76 inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { | |
| 77 return turboSwizzled(colorSpace); | |
| 78 } | |
| 79 #else | 73 #else |
| 80 inline J_COLOR_SPACE rgbOutputColorSpace() { | 74 inline J_COLOR_SPACE rgbOutputColorSpace() { |
| 81 return JCS_RGB; | 75 return JCS_RGB; |
| 82 } | 76 } |
| 83 inline bool colorSpaceHasAlpha(J_COLOR_SPACE) { | |
| 84 return false; | |
| 85 } | |
| 86 #endif | 77 #endif |
| 87 | 78 |
| 88 namespace { | 79 namespace { |
| 89 | 80 |
| 90 const int exifMarker = JPEG_APP0 + 1; | 81 const int exifMarker = JPEG_APP0 + 1; |
| 91 | 82 |
| 92 // JPEG only supports a denominator of 8. | 83 // JPEG only supports a denominator of 8. |
| 93 const unsigned scaleDenominator = 8; | 84 const unsigned scaleDenominator = 8; |
| 94 | 85 |
| 95 } // namespace | 86 } // namespace |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 m_src.pub.fill_input_buffer = fill_input_buffer; | 299 m_src.pub.fill_input_buffer = fill_input_buffer; |
| 309 m_src.pub.skip_input_data = skip_input_data; | 300 m_src.pub.skip_input_data = skip_input_data; |
| 310 m_src.pub.resync_to_restart = jpeg_resync_to_restart; | 301 m_src.pub.resync_to_restart = jpeg_resync_to_restart; |
| 311 m_src.pub.term_source = term_source; | 302 m_src.pub.term_source = term_source; |
| 312 m_src.reader = this; | 303 m_src.reader = this; |
| 313 | 304 |
| 314 #if USE(ICCJPEG) | 305 #if USE(ICCJPEG) |
| 315 // Retain ICC color profile markers for color management. | 306 // Retain ICC color profile markers for color management. |
| 316 setup_read_icc_profile(&m_info); | 307 setup_read_icc_profile(&m_info); |
| 317 #endif | 308 #endif |
| 309 |
| 318 // Keep APP1 blocks, for obtaining exif data. | 310 // Keep APP1 blocks, for obtaining exif data. |
| 319 jpeg_save_markers(&m_info, exifMarker, 0xFFFF); | 311 jpeg_save_markers(&m_info, exifMarker, 0xFFFF); |
| 320 } | 312 } |
| 321 | 313 |
| 322 ~JPEGImageReader() { jpeg_destroy_decompress(&m_info); } | 314 ~JPEGImageReader() { jpeg_destroy_decompress(&m_info); } |
| 323 | 315 |
| 324 void skipBytes(long numBytes) { | 316 void skipBytes(long numBytes) { |
| 325 if (numBytes <= 0) | 317 if (numBytes <= 0) |
| 326 return; | 318 return; |
| 327 | 319 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height); | 446 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height); |
| 455 | 447 |
| 456 m_decoder->setOrientation(readImageOrientation(info())); | 448 m_decoder->setOrientation(readImageOrientation(info())); |
| 457 | 449 |
| 458 // Allow color management of the decoded RGBA pixels if possible. | 450 // Allow color management of the decoded RGBA pixels if possible. |
| 459 if (!m_decoder->ignoresGammaAndColorProfile()) { | 451 if (!m_decoder->ignoresGammaAndColorProfile()) { |
| 460 #if USE(ICCJPEG) | 452 #if USE(ICCJPEG) |
| 461 JOCTET* profile = nullptr; | 453 JOCTET* profile = nullptr; |
| 462 unsigned profileLength = 0; | 454 unsigned profileLength = 0; |
| 463 if (read_icc_profile(info(), &profile, &profileLength)) { | 455 if (read_icc_profile(info(), &profile, &profileLength)) { |
| 464 decoder()->setColorProfileAndComputeTransform( | 456 decoder()->setColorSpaceAndComputeTransform( |
| 465 reinterpret_cast<char*>(profile), profileLength, | 457 reinterpret_cast<char*>(profile), profileLength, |
| 466 colorSpaceHasAlpha(info()->out_color_space), | |
| 467 false /* useSRGB */); | 458 false /* useSRGB */); |
| 468 free(profile); | 459 free(profile); |
| 469 } | 460 } |
| 470 #endif // USE(ICCJPEG) | 461 #endif // USE(ICCJPEG) |
| 471 #if USE(QCMSLIB) | 462 #if USE(SKCOLORXFORM) |
| 472 if (decoder()->colorTransform()) { | 463 if (decoder()->colorTransform()) { |
| 473 overrideColorSpace = JCS_UNKNOWN; | 464 overrideColorSpace = JCS_UNKNOWN; |
| 474 #if defined(TURBO_JPEG_RGB_SWIZZLE) | |
| 475 // Input RGBA data to qcms. Note: restored to BGRA on output. | |
| 476 if (m_info.out_color_space == JCS_EXT_BGRA) | |
| 477 m_info.out_color_space = JCS_EXT_RGBA; | |
| 478 #endif // defined(TURBO_JPEG_RGB_SWIZZLE) | |
| 479 } | 465 } |
| 480 #endif // USE(QCMSLIB) | 466 #endif // USE(SKCOLORXFORM) |
| 481 } | 467 } |
| 482 if (overrideColorSpace == JCS_YCbCr) { | 468 if (overrideColorSpace == JCS_YCbCr) { |
| 483 m_info.out_color_space = JCS_YCbCr; | 469 m_info.out_color_space = JCS_YCbCr; |
| 484 m_info.raw_data_out = TRUE; | 470 m_info.raw_data_out = TRUE; |
| 485 m_uvSize = computeYUVSize( | 471 m_uvSize = computeYUVSize( |
| 486 &m_info, | 472 &m_info, |
| 487 1); // U size and V size have to be the same if we got here | 473 1); // U size and V size have to be the same if we got here |
| 488 } | 474 } |
| 489 | 475 |
| 490 // Don't allocate a giant and superfluous memory buffer when the | 476 // Don't allocate a giant and superfluous memory buffer when the |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 } | 793 } |
| 808 | 794 |
| 809 template <J_COLOR_SPACE colorSpace> | 795 template <J_COLOR_SPACE colorSpace> |
| 810 void setPixel(ImageFrame& buffer, | 796 void setPixel(ImageFrame& buffer, |
| 811 ImageFrame::PixelData* pixel, | 797 ImageFrame::PixelData* pixel, |
| 812 JSAMPARRAY samples, | 798 JSAMPARRAY samples, |
| 813 int column) { | 799 int column) { |
| 814 ASSERT_NOT_REACHED(); | 800 ASSERT_NOT_REACHED(); |
| 815 } | 801 } |
| 816 | 802 |
| 803 // Used only for debugging with libjpeg (instead of libjpeg-turbo). |
| 817 template <> | 804 template <> |
| 818 void setPixel<JCS_RGB>(ImageFrame& buffer, | 805 void setPixel<JCS_RGB>(ImageFrame& buffer, |
| 819 ImageFrame::PixelData* pixel, | 806 ImageFrame::PixelData* pixel, |
| 820 JSAMPARRAY samples, | 807 JSAMPARRAY samples, |
| 821 int column) { | 808 int column) { |
| 822 JSAMPLE* jsample = *samples + column * 3; | 809 JSAMPLE* jsample = *samples + column * 3; |
| 823 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); | 810 buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); |
| 824 } | 811 } |
| 825 | 812 |
| 826 template <> | 813 template <> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 837 // X = X * (1 - K ) + K [for X = C, M, or Y] | 824 // X = X * (1 - K ) + K [for X = C, M, or Y] |
| 838 // Thus, from Inverted CMYK to CMY is: | 825 // Thus, from Inverted CMYK to CMY is: |
| 839 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK | 826 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK |
| 840 // From CMY (0..1) to RGB (0..1): | 827 // From CMY (0..1) to RGB (0..1): |
| 841 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] | 828 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] |
| 842 unsigned k = jsample[3]; | 829 unsigned k = jsample[3]; |
| 843 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, | 830 buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, |
| 844 jsample[2] * k / 255, 255); | 831 jsample[2] * k / 255, 255); |
| 845 } | 832 } |
| 846 | 833 |
| 834 // Used only for JCS_CMYK and JCS_RGB output. Note that JCS_RGB is used only |
| 835 // for debugging with libjpeg (instead of libjpeg-turbo). |
| 847 template <J_COLOR_SPACE colorSpace> | 836 template <J_COLOR_SPACE colorSpace> |
| 848 bool outputRows(JPEGImageReader* reader, ImageFrame& buffer) { | 837 bool outputRows(JPEGImageReader* reader, ImageFrame& buffer) { |
| 849 JSAMPARRAY samples = reader->samples(); | 838 JSAMPARRAY samples = reader->samples(); |
| 850 jpeg_decompress_struct* info = reader->info(); | 839 jpeg_decompress_struct* info = reader->info(); |
| 851 int width = info->output_width; | 840 int width = info->output_width; |
| 852 | 841 |
| 853 while (info->output_scanline < info->output_height) { | 842 while (info->output_scanline < info->output_height) { |
| 854 // jpeg_read_scanlines will increase the scanline counter, so we | 843 // jpeg_read_scanlines will increase the scanline counter, so we |
| 855 // save the scanline before calling it. | 844 // save the scanline before calling it. |
| 856 int y = info->output_scanline; | 845 int y = info->output_scanline; |
| 857 // Request one scanline: returns 0 or 1 scanlines. | 846 // Request one scanline: returns 0 or 1 scanlines. |
| 858 if (jpeg_read_scanlines(info, samples, 1) != 1) | 847 if (jpeg_read_scanlines(info, samples, 1) != 1) |
| 859 return false; | 848 return false; |
| 860 #if USE(QCMSLIB) | 849 |
| 861 if (reader->decoder()->colorTransform() && colorSpace == JCS_RGB) | |
| 862 qcms_transform_data(reader->decoder()->colorTransform(), *samples, | |
| 863 *samples, width); | |
| 864 #endif | |
| 865 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); | 850 ImageFrame::PixelData* pixel = buffer.getAddr(0, y); |
| 866 for (int x = 0; x < width; ++pixel, ++x) | 851 for (int x = 0; x < width; ++pixel, ++x) |
| 867 setPixel<colorSpace>(buffer, pixel, samples, x); | 852 setPixel<colorSpace>(buffer, pixel, samples, x); |
| 853 |
| 854 #if USE(SKCOLORXFORM) |
| 855 SkColorSpaceXform* xform = reader->decoder()->colorTransform(); |
| 856 if (JCS_RGB == colorSpace && xform) { |
| 857 ImageFrame::PixelData* row = buffer.getAddr(0, y); |
| 858 xform->apply(xformColorFormat(), row, xformColorFormat(), row, width, |
| 859 kOpaque_SkAlphaType); |
| 860 } |
| 861 #endif |
| 868 } | 862 } |
| 869 | 863 |
| 870 buffer.setPixelsChanged(true); | 864 buffer.setPixelsChanged(true); |
| 871 return true; | 865 return true; |
| 872 } | 866 } |
| 873 | 867 |
| 874 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) { | 868 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) { |
| 875 JSAMPARRAY samples = reader->samples(); | 869 JSAMPARRAY samples = reader->samples(); |
| 876 jpeg_decompress_struct* info = reader->info(); | 870 jpeg_decompress_struct* info = reader->info(); |
| 877 | 871 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); | 952 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); |
| 959 } | 953 } |
| 960 | 954 |
| 961 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 955 #if defined(TURBO_JPEG_RGB_SWIZZLE) |
| 962 if (turboSwizzled(info->out_color_space)) { | 956 if (turboSwizzled(info->out_color_space)) { |
| 963 while (info->output_scanline < info->output_height) { | 957 while (info->output_scanline < info->output_height) { |
| 964 unsigned char* row = reinterpret_cast_ptr<unsigned char*>( | 958 unsigned char* row = reinterpret_cast_ptr<unsigned char*>( |
| 965 buffer.getAddr(0, info->output_scanline)); | 959 buffer.getAddr(0, info->output_scanline)); |
| 966 if (jpeg_read_scanlines(info, &row, 1) != 1) | 960 if (jpeg_read_scanlines(info, &row, 1) != 1) |
| 967 return false; | 961 return false; |
| 968 #if USE(QCMSLIB) | 962 |
| 969 if (qcms_transform* transform = colorTransform()) | 963 #if USE(SKCOLORXFORM) |
| 970 qcms_transform_data_type(transform, row, row, info->output_width, | 964 SkColorSpaceXform* xform = colorTransform(); |
| 971 rgbOutputColorSpace() == JCS_EXT_BGRA | 965 if (xform) { |
| 972 ? QCMS_OUTPUT_BGRX | 966 xform->apply(xformColorFormat(), row, xformColorFormat(), row, |
| 973 : QCMS_OUTPUT_RGBX); | 967 info->output_width, kOpaque_SkAlphaType); |
| 968 } |
| 974 #endif | 969 #endif |
| 975 } | 970 } |
| 976 buffer.setPixelsChanged(true); | 971 buffer.setPixelsChanged(true); |
| 977 return true; | 972 return true; |
| 978 } | 973 } |
| 979 #endif | 974 #endif |
| 980 | 975 |
| 981 switch (info->out_color_space) { | 976 switch (info->out_color_space) { |
| 982 case JCS_RGB: | 977 case JCS_RGB: |
| 983 return outputRows<JCS_RGB>(m_reader.get(), buffer); | 978 return outputRows<JCS_RGB>(m_reader.get(), buffer); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 // has failed. | 1013 // has failed. |
| 1019 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1014 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
| 1020 setFailed(); | 1015 setFailed(); |
| 1021 | 1016 |
| 1022 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1017 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
| 1023 if (isComplete(this, onlySize) || failed()) | 1018 if (isComplete(this, onlySize) || failed()) |
| 1024 m_reader.reset(); | 1019 m_reader.reset(); |
| 1025 } | 1020 } |
| 1026 | 1021 |
| 1027 } // namespace blink | 1022 } // namespace blink |
| OLD | NEW |