diff options
author | Derek Sollenberger <djsollen@google.com> | 2013-04-18 16:01:40 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-04-18 16:01:40 +0000 |
commit | fa3c026835b4e2fa13f21d56d3299922fca6815f (patch) | |
tree | a055e577f184ea18dd60502238c3bfabe54b909d | |
parent | e2dc2d7f2acec9dc1e1d577a14b3f6e8efd3be71 (diff) | |
parent | 88a3a9a8c5f4e37888216b6332f971cea924d821 (diff) | |
download | skia-fa3c026835b4e2fa13f21d56d3299922fca6815f.tar.gz |
Merge "Add support for CMYK jpeg images." into jb-mr2-devandroid-4.3_r3.1android-4.3_r3android-4.3_r2.3android-4.3_r2.2android-4.3_r2.1android-4.3_r2android-4.3_r1.1android-4.3_r1android-4.3_r0.9.1android-4.3_r0.9android-4.3.1_r1jb-mr2.0.0-releasejb-mr2.0-releasejb-mr2-releasejb-mr2-dev
-rw-r--r-- | src/images/SkImageDecoder_libjpeg.cpp | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp index 2f72c2d72b..81344b3e44 100644 --- a/src/images/SkImageDecoder_libjpeg.cpp +++ b/src/images/SkImageDecoder_libjpeg.cpp @@ -189,6 +189,29 @@ static bool return_false(const jpeg_decompress_struct& cinfo, return false; // must always return false } +// Convert a scanline of CMYK samples to RGBX in place. Note that this +// method moves the "scanline" pointer in its processing +static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { + // At this point we've received CMYK pixels from libjpeg. We + // perform a crude conversion to RGB (based on the formulae + // from easyrgb.com): + // CMYK -> CMY + // C = ( C * (1 - K) + K ) // for each CMY component + // CMY -> RGB + // R = ( 1 - C ) * 255 // for each RGB component + // Unfortunately we are seeing inverted CMYK so all the original terms + // are 1-. This yields: + // CMYK -> CMY + // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K + // The conversion from CMY->RGB remains the same + for (unsigned int x = 0; x < width; ++x, scanline += 4) { + scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); + scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); + scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); + scanline[3] = 255; + } +} + bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { #ifdef TIME_DECODE AutoTimeMillis atm("JPEG Decode"); @@ -249,7 +272,14 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { cinfo.do_block_smoothing = 0; /* default format is RGB */ - cinfo.out_color_space = JCS_RGB; + if (cinfo.jpeg_color_space == JCS_CMYK) { + // libjpeg cannot convert from CMYK to RGB - here we set up + // so libjpeg will give us CMYK samples back and we will + // later manually convert them to RGB + cinfo.out_color_space = JCS_CMYK; + } else { + cinfo.out_color_space = JCS_RGB; + } SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false); // only these make sense for jpegs @@ -261,9 +291,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { #ifdef ANDROID_RGB cinfo.dither_mode = JDITHER_NONE; - if (config == SkBitmap::kARGB_8888_Config) { + if (SkBitmap::kARGB_8888_Config == config && JCS_CMYK != cinfo.out_color_space) { cinfo.out_color_space = JCS_RGBA_8888; - } else if (config == SkBitmap::kRGB_565_Config) { + } else if (SkBitmap::kRGB_565_Config == config && JCS_CMYK != cinfo.out_color_space) { cinfo.out_color_space = JCS_RGB_565; if (this->getDitherImage()) { cinfo.dither_mode = JDITHER_ORDERED; @@ -368,7 +398,10 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { // check for supported formats SkScaledBitmapSampler::SrcConfig sc; - if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { + if (JCS_CMYK == cinfo.out_color_space) { + // In this case we will manually convert the CMYK values to RGB + sc = SkScaledBitmapSampler::kRGBX; + } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { sc = SkScaledBitmapSampler::kRGB; #ifdef ANDROID_RGB } else if (JCS_RGBA_8888 == cinfo.out_color_space) { @@ -416,6 +449,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { return return_false(cinfo, *bm, "sampler.begin"); } + // The CMYK work-around relies on 4 components per pixel here uint8_t* srcRow = (uint8_t*)srcStorage.reset(cinfo.output_width * 4); // Possibly skip initial rows [sampler.srcY0] @@ -433,7 +467,11 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { if (this->shouldCancelDecode()) { return return_false(cinfo, *bm, "shouldCancelDecode"); } - + + if (JCS_CMYK == cinfo.out_color_space) { + convert_CMYK_to_RGB(srcRow, cinfo.output_width); + } + sampler.next(srcRow); if (bm->height() - 1 == y) { // we're done |