Index: third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp |
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp |
index a77a3f4bff35338403be10a21d71786f4ac15189..083a5499e6d90909e0eb54ee0520639c856c81c6 100644 |
--- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp |
+++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp |
@@ -65,7 +65,7 @@ inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_RGBA; } |
#else // Output little-endian BGRA pixels. |
inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_EXT_BGRA; } |
#endif |
-inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_EXT_RGBA || colorSpace == JCS_EXT_BGRA; } |
+inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { return colorSpace == JCS_EXT_RGBA || colorSpace == JCS_EXT_BGRA || colorSpace == JCS_RGB565; } |
inline bool colorSpaceHasAlpha(J_COLOR_SPACE colorSpace) { return turboSwizzled(colorSpace); } |
#else |
inline J_COLOR_SPACE rgbOutputColorSpace() { return JCS_RGB; } |
@@ -472,6 +472,23 @@ public: |
default: |
return m_decoder->setFailed(); |
} |
+ if (m_decoder->decodeToRGB565Enabled()) { |
+ if (m_info.out_color_space == rgbOutputColorSpace()) { |
+ // the rest would need to be converted manually on write |
+#if defined (JCS_ALPHA_EXTENSIONS) |
+ m_info.out_color_space = JCS_RGB565; |
+#else |
+ m_info.out_color_space = JCS_RGB; |
scroggo_chromium
2015/10/19 20:41:36
Isn't that the same as rgbOutputColorSpace when JC
aleksandar.stojiljkovic
2015/10/20 09:51:12
Correct, not needed to set to same.
|
+#endif |
+#if USE(QCMSLIB) |
+ // if there is colorprofile, use JCS_RGB as QCMS is not supporting RGB565 |
+ // conversion, RGB->RGB565 happens in outputRows<>() |
+ if (!m_decoder->ignoresGammaAndColorProfile()) |
+ m_info.out_color_space = JCS_RGB; |
+#endif |
+ } |
+ } |
+ // fell through |
scroggo_chromium
2015/10/19 20:41:36
nit: Other places in this file say "FALL THROUGH".
aleksandar.stojiljkovic
2015/10/20 09:51:12
Done.
|
m_state = JPEG_START_DECOMPRESS; |
@@ -588,6 +605,7 @@ public: |
case JPEG_DECOMPRESS_PROGRESSIVE: |
if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { |
+ |
scroggo_chromium
2015/10/19 20:41:36
Why the extra line here?
|
int status = 0; |
do { |
decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_mgr*>(m_info.err); |
@@ -780,6 +798,7 @@ void term_source(j_decompress_ptr jd) |
JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption colorOptions, size_t maxDecodedBytes) |
: ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) |
, m_hasColorProfile(false) |
+ , m_decodeToRGB565(false) |
{ |
} |
@@ -841,6 +860,30 @@ bool JPEGImageDecoder::canDecodeToYUV() |
return isSizeAvailable() && m_reader->info()->out_color_space == JCS_YCbCr; |
} |
+bool JPEGImageDecoder::canDecodeToRGB565() |
+{ |
+ // Calling isSizeAvailable() ensures the reader is created and the output |
scroggo_chromium
2015/10/19 20:41:36
I do not follow how this comment applies.
aleksandar.stojiljkovic
2015/10/20 09:51:12
Didn't do cleanup after copy paste.
Also decoding
|
+ // color space is set. |
+#if defined(JCS_ALPHA_EXTENSIONS) |
+ return true; |
+#else |
+ return false; |
+#endif |
+} |
+ |
+bool JPEGImageDecoder::setDecodeRGB565Enabled(const bool enable) |
+{ |
+#if defined(JCS_ALPHA_EXTENSIONS) |
+ m_decodeToRGB565 = enable; |
scroggo_chromium
2015/10/19 20:41:36
Should m_decodeToRGB565 only be defined if JCS_ALP
aleksandar.stojiljkovic
2015/10/20 09:51:12
Done.
|
+ return true; |
+#else |
+ if (!enable) |
scroggo_chromium
2015/10/19 20:41:36
Can this just be:
return !enable
and then drop
aleksandar.stojiljkovic
2015/10/20 09:51:12
Done.
|
+ return true; |
+#endif |
+ return false; |
+} |
+ |
+ |
bool JPEGImageDecoder::decodeToYUV() |
{ |
if (!hasImagePlanes()) |
@@ -856,18 +899,18 @@ void JPEGImageDecoder::setImagePlanes(PassOwnPtr<ImagePlanes> imagePlanes) |
m_imagePlanes = imagePlanes; |
} |
-template <J_COLOR_SPACE colorSpace> void setPixel(ImageFrame& buffer, ImageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
+template <J_COLOR_SPACE colorSpace, class T> void setPixel(ImageFrame& buffer, T* pixel, JSAMPARRAY samples, int column) |
{ |
ASSERT_NOT_REACHED(); |
} |
-template <> void setPixel<JCS_RGB>(ImageFrame& buffer, ImageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
+template <> void setPixel<JCS_RGB, ImageFrame::PixelData>(ImageFrame& buffer, ImageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
{ |
JSAMPLE* jsample = *samples + column * 3; |
buffer.setRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); |
} |
-template <> void setPixel<JCS_CMYK>(ImageFrame& buffer, ImageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
+template <> void setPixel<JCS_CMYK, ImageFrame::PixelData>(ImageFrame& buffer, ImageFrame::PixelData* pixel, JSAMPARRAY samples, int column) |
{ |
JSAMPLE* jsample = *samples + column * 4; |
@@ -884,7 +927,30 @@ template <> void setPixel<JCS_CMYK>(ImageFrame& buffer, ImageFrame::PixelData* p |
buffer.setRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 255); |
} |
-template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, ImageFrame& buffer) |
+template <> void setPixel<JCS_RGB, ImageFrame::PixelData16>(ImageFrame& buffer, ImageFrame::PixelData16* pixel, JSAMPARRAY samples, int column) |
+{ |
+ JSAMPLE* jsample = *samples + column * 3; |
+ buffer.setRGB565(pixel, jsample[0], jsample[1], jsample[2]); |
+} |
+ |
+template <> void setPixel<JCS_CMYK, ImageFrame::PixelData16>(ImageFrame& buffer, ImageFrame::PixelData16* pixel, JSAMPARRAY samples, int column) |
+{ |
+ JSAMPLE* jsample = *samples + column * 4; |
+ |
+ // Source is 'Inverted CMYK', output is RGB. |
+ // See: http://www.easyrgb.com/math.php?MATH=M12#text12 |
+ // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb |
+ // From CMYK to CMY: |
+ // X = X * (1 - K ) + K [for X = C, M, or Y] |
+ // Thus, from Inverted CMYK to CMY is: |
+ // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK |
+ // From CMY (0..1) to RGB (0..1): |
+ // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] |
+ unsigned k = jsample[3]; |
+ buffer.setRGB565(pixel, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255); |
+} |
+ |
+template <J_COLOR_SPACE colorSpace, class T> bool outputRows(JPEGImageReader* reader, ImageFrame& buffer) |
{ |
JSAMPARRAY samples = reader->samples(); |
jpeg_decompress_struct* info = reader->info(); |
@@ -901,9 +967,9 @@ template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, Ima |
if (reader->colorTransform() && colorSpace == JCS_RGB) |
qcms_transform_data(reader->colorTransform(), *samples, *samples, width); |
#endif |
- ImageFrame::PixelData* pixel = buffer.getAddr(0, y); |
+ T* pixel = buffer.getAddrT<T>(0, y); |
for (int x = 0; x < width; ++pixel, ++x) |
- setPixel<colorSpace>(buffer, pixel, samples, x); |
+ setPixel<colorSpace, T>(buffer, pixel, samples, x); |
} |
buffer.setPixelsChanged(true); |
@@ -1005,11 +1071,13 @@ bool JPEGImageDecoder::outputScanlines() |
ASSERT(info->output_width == static_cast<JDIMENSION>(m_decodedSize.width())); |
ASSERT(info->output_height == static_cast<JDIMENSION>(m_decodedSize.height())); |
- if (!buffer.setSize(info->output_width, info->output_height)) |
+ if (!buffer.setSize(info->output_width, info->output_height, decodeToRGB565Enabled() |
+ ? ImageFrame::RGB565 : ImageFrame::RGBA8888)) |
return setFailed(); |
buffer.setStatus(ImageFrame::FramePartial); |
// The buffer is transparent outside the decoded area while the image is |
// loading. The image will be marked fully opaque in complete(). |
+ // for RGB565 this would just fail, having bitmap opaque during decoding |
scroggo_chromium
2015/10/19 20:41:36
So doesn't this need to say something like if (!56
aleksandar.stojiljkovic
2015/10/20 09:51:12
Done.
|
buffer.setHasAlpha(true); |
// For JPEGs, the frame always fills the entire image. |
@@ -1019,9 +1087,12 @@ bool JPEGImageDecoder::outputScanlines() |
#if defined(TURBO_JPEG_RGB_SWIZZLE) |
if (turboSwizzled(info->out_color_space)) { |
while (info->output_scanline < info->output_height) { |
- unsigned char* row = reinterpret_cast_ptr<unsigned char*>(buffer.getAddr(0, info->output_scanline)); |
- if (jpeg_read_scanlines(info, &row, 1) != 1) |
+ unsigned char* row = decodeToRGB565Enabled() |
+ ? reinterpret_cast_ptr<unsigned char*>(buffer.getAddrT<ImageFrame::PixelData16>(0, info->output_scanline)) |
+ : reinterpret_cast_ptr<unsigned char*>(buffer.getAddr(0, info->output_scanline)); |
+ if (jpeg_read_scanlines(info, &row, 1) != 1) { |
return false; |
+ } |
#if USE(QCMSLIB) |
if (qcms_transform* transform = m_reader->colorTransform()) |
qcms_transform_data_type(transform, row, row, info->output_width, rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX); |
@@ -1034,9 +1105,13 @@ bool JPEGImageDecoder::outputScanlines() |
switch (info->out_color_space) { |
case JCS_RGB: |
- return outputRows<JCS_RGB>(m_reader.get(), buffer); |
+ if (decodeToRGB565Enabled()) |
+ return outputRows<JCS_RGB, ImageFrame::PixelData16>(m_reader.get(), buffer); |
+ return outputRows<JCS_RGB, ImageFrame::PixelData>(m_reader.get(), buffer); |
case JCS_CMYK: |
- return outputRows<JCS_CMYK>(m_reader.get(), buffer); |
+ if (decodeToRGB565Enabled()) |
+ return outputRows<JCS_CMYK, ImageFrame::PixelData16>(m_reader.get(), buffer); |
+ return outputRows<JCS_CMYK, ImageFrame::PixelData>(m_reader.get(), buffer); |
default: |
ASSERT_NOT_REACHED(); |
} |