| Index: src/codec/SkJpegCodec.cpp
|
| diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
|
| index 9975748cf4b4ce4010ea9dc79eca8cac6614fc93..6850a7782512aa0cc731982c7fb3cff61c93b0ec 100644
|
| --- a/src/codec/SkJpegCodec.cpp
|
| +++ b/src/codec/SkJpegCodec.cpp
|
| @@ -23,69 +23,6 @@ extern "C" {
|
| #include "jpeglib.h"
|
| }
|
|
|
| -/*
|
| - * Convert a row of CMYK samples to RGBA in place.
|
| - * Note that this method moves the row pointer.
|
| - * @param width the number of pixels in the row that is being converted
|
| - * CMYK is stored as four bytes per pixel
|
| - */
|
| -static void convert_CMYK_to_RGBA(uint8_t* row, uint32_t width) {
|
| - // We will implement a crude conversion from CMYK -> RGB using formulas
|
| - // from easyrgb.com.
|
| - //
|
| - // CMYK -> CMY
|
| - // C = C * (1 - K) + K
|
| - // M = M * (1 - K) + K
|
| - // Y = Y * (1 - K) + K
|
| - //
|
| - // libjpeg actually gives us inverted CMYK, so we must subtract the
|
| - // original terms from 1.
|
| - // CMYK -> CMY
|
| - // C = (1 - C) * (1 - (1 - K)) + (1 - K)
|
| - // M = (1 - M) * (1 - (1 - K)) + (1 - K)
|
| - // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
|
| - //
|
| - // Simplifying the above expression.
|
| - // CMYK -> CMY
|
| - // C = 1 - CK
|
| - // M = 1 - MK
|
| - // Y = 1 - YK
|
| - //
|
| - // CMY -> RGB
|
| - // R = (1 - C) * 255
|
| - // G = (1 - M) * 255
|
| - // B = (1 - Y) * 255
|
| - //
|
| - // Therefore the full conversion is below. This can be verified at
|
| - // www.rapidtables.com (assuming inverted CMYK).
|
| - // CMYK -> RGB
|
| - // R = C * K * 255
|
| - // G = M * K * 255
|
| - // B = Y * K * 255
|
| - //
|
| - // As a final note, we have treated the CMYK values as if they were on
|
| - // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
|
| - // We must divide each CMYK component by 255 to obtain the true conversion
|
| - // we should perform.
|
| - // CMYK -> RGB
|
| - // R = C * K / 255
|
| - // G = M * K / 255
|
| - // B = Y * K / 255
|
| - for (uint32_t x = 0; x < width; x++, row += 4) {
|
| -#if defined(SK_PMCOLOR_IS_RGBA)
|
| - row[0] = SkMulDiv255Round(row[0], row[3]);
|
| - row[1] = SkMulDiv255Round(row[1], row[3]);
|
| - row[2] = SkMulDiv255Round(row[2], row[3]);
|
| -#else
|
| - uint8_t tmp = row[0];
|
| - row[0] = SkMulDiv255Round(row[2], row[3]);
|
| - row[1] = SkMulDiv255Round(row[1], row[3]);
|
| - row[2] = SkMulDiv255Round(tmp, row[3]);
|
| -#endif
|
| - row[3] = 0xFF;
|
| - }
|
| -}
|
| -
|
| bool SkJpegCodec::IsJpeg(SkStream* stream) {
|
| static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF };
|
| char buffer[sizeof(jpegSig)];
|
| @@ -263,10 +200,7 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
|
| return true;
|
| case kRGB_565_SkColorType:
|
| if (isCMYK) {
|
| - // FIXME (msarett): We need to support 565 here. It's not hard to do, considering
|
| - // we already convert CMYK to RGBA, I just need to do it. I think it might be
|
| - // best to do this in SkSwizzler and also move convert_CMYK_to_RGBA into SkSwizzler.
|
| - return false;
|
| + fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
|
| } else {
|
| #if defined(GOOGLE3)
|
| return false;
|
| @@ -365,9 +299,22 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| // If it's not, we want to know because it means our strategy is not optimal.
|
| SkASSERT(1 == dinfo->rec_outbuf_height);
|
|
|
| + if (JCS_CMYK == dinfo->out_color_space) {
|
| + this->initializeSwizzler(dstInfo, options);
|
| + }
|
| +
|
| // Perform the decode a single row at a time
|
| uint32_t dstHeight = dstInfo.height();
|
| - JSAMPLE* dstRow = (JSAMPLE*) dst;
|
| +
|
| + JSAMPLE* dstRow;
|
| + if (fSwizzler) {
|
| + // write data to storage row, then sample using swizzler
|
| + dstRow = fSrcRow;
|
| + } else {
|
| + // write data directly to dst
|
| + dstRow = (JSAMPLE*) dst;
|
| + }
|
| +
|
| for (uint32_t y = 0; y < dstHeight; y++) {
|
| // Read rows of the image
|
| uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1);
|
| @@ -379,13 +326,13 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
|
| }
|
|
|
| - // Convert to RGBA if necessary
|
| - if (JCS_CMYK == dinfo->out_color_space) {
|
| - convert_CMYK_to_RGBA(dstRow, dstInfo.width());
|
| + if (fSwizzler) {
|
| + // use swizzler to sample row
|
| + fSwizzler->swizzle(dst, dstRow);
|
| + dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
|
| + } else {
|
| + dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
|
| }
|
| -
|
| - // Move to the next row
|
| - dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
|
| }
|
|
|
| return kSuccess;
|
| @@ -393,26 +340,30 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
|
|
|
| void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
|
| SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown;
|
| - switch (dstInfo.colorType()) {
|
| - case kGray_8_SkColorType:
|
| - srcConfig = SkSwizzler::kGray;
|
| - break;
|
| - case kRGBA_8888_SkColorType:
|
| - srcConfig = SkSwizzler::kRGBX;
|
| - break;
|
| - case kBGRA_8888_SkColorType:
|
| - srcConfig = SkSwizzler::kBGRX;
|
| - break;
|
| - case kRGB_565_SkColorType:
|
| - srcConfig = SkSwizzler::kRGB_565;
|
| - break;
|
| - default:
|
| - // This function should only be called if the colorType is supported by jpeg
|
| + if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
|
| + srcConfig = SkSwizzler::kCMYK;
|
| + } else {
|
| + switch (dstInfo.colorType()) {
|
| + case kGray_8_SkColorType:
|
| + srcConfig = SkSwizzler::kGray;
|
| + break;
|
| + case kRGBA_8888_SkColorType:
|
| + srcConfig = SkSwizzler::kRGBX;
|
| + break;
|
| + case kBGRA_8888_SkColorType:
|
| + srcConfig = SkSwizzler::kBGRX;
|
| + break;
|
| + case kRGB_565_SkColorType:
|
| + srcConfig = SkSwizzler::kRGB_565;
|
| + break;
|
| + default:
|
| + // This function should only be called if the colorType is supported by jpeg
|
| #if defined(GOOGLE3)
|
| - SK_CRASH();
|
| + SK_CRASH();
|
| #else
|
| - SkASSERT(false);
|
| + SkASSERT(false);
|
| #endif
|
| + }
|
| }
|
|
|
| fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, options));
|
| @@ -454,8 +405,9 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
|
| return kInvalidInput;
|
| }
|
|
|
| - // We will need a swizzler if we are performing a subset decode
|
| - if (options.fSubset) {
|
| + // We will need a swizzler if we are performing a subset decode or
|
| + // converting from CMYK.
|
| + if (options.fSubset || JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
|
| this->initializeSwizzler(dstInfo, options);
|
| }
|
|
|
| @@ -485,12 +437,7 @@ int SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
|
| return y;
|
| }
|
|
|
| - // Convert to RGBA if necessary
|
| - if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
|
| - convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width);
|
| - }
|
| -
|
| - if(fSwizzler) {
|
| + if (fSwizzler) {
|
| // use swizzler to sample row
|
| fSwizzler->swizzle(dst, dstRow);
|
| dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
|
|
|