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