diff options
author | scroggo <scroggo@google.com> | 2015-10-23 08:39:58 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-23 08:39:58 -0700 |
commit | b7f1251775390cdcf58197fd904d7676b9508128 (patch) | |
tree | 9db226d8ae7298ccad12f309900bc0e892e9697e /src | |
parent | 450ee8f26d39f975cf6af37a27de658ae5a9fa10 (diff) |
Revert of Use SkSwizzler to convert from CMYK (patchset #4 id:60001 of https://codereview.chromium.org/1411083009/ )
Reason for revert:
Breaking ASAN. See http://build.chromium.org/p/client.skia/builders/Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-ASAN/builds/2879
Original issue's description:
> Use SkSwizzler to convert from CMYK
>
> Move convert_CMYK_to_RGBA into two functions in SkSwizzler: one for 565
> and one for 8888.
>
> For simplicity, when converting to 8888, we no longer convert in place.
>
> BUG=skia:4476
>
> Committed: https://skia.googlesource.com/skia/+/450ee8f26d39f975cf6af37a27de658ae5a9fa10
TBR=msarett@google.com,scroggo@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:4476
Review URL: https://codereview.chromium.org/1411193006
Diffstat (limited to 'src')
-rw-r--r-- | src/codec/SkJpegCodec.cpp | 145 | ||||
-rw-r--r-- | src/codec/SkSwizzler.cpp | 95 | ||||
-rw-r--r-- | src/codec/SkSwizzler.h | 2 |
3 files changed, 99 insertions, 143 deletions
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp index 6850a77825..9975748cf4 100644 --- a/src/codec/SkJpegCodec.cpp +++ b/src/codec/SkJpegCodec.cpp @@ -23,6 +23,69 @@ 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)]; @@ -200,7 +263,10 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) { return true; case kRGB_565_SkColorType: if (isCMYK) { - fDecoderMgr->dinfo()->out_color_space = JCS_CMYK; + // 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; } else { #if defined(GOOGLE3) return false; @@ -299,22 +365,9 @@ 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; - if (fSwizzler) { - // write data to storage row, then sample using swizzler - dstRow = fSrcRow; - } else { - // write data directly to dst - dstRow = (JSAMPLE*) dst; - } - + JSAMPLE* 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); @@ -326,13 +379,13 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput); } - if (fSwizzler) { - // use swizzler to sample row - fSwizzler->swizzle(dst, dstRow); - dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes); - } else { - dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); + // Convert to RGBA if necessary + if (JCS_CMYK == dinfo->out_color_space) { + convert_CMYK_to_RGBA(dstRow, dstInfo.width()); } + + // Move to the next row + dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); } return kSuccess; @@ -340,30 +393,26 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) { SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown; - 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 + 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)); @@ -405,9 +454,8 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, return kInvalidInput; } - // 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) { + // We will need a swizzler if we are performing a subset decode + if (options.fSubset) { this->initializeSwizzler(dstInfo, options); } @@ -437,7 +485,12 @@ int SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { return y; } - if (fSwizzler) { + // Convert to RGBA if necessary + if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { + convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width); + } + + if(fSwizzler) { // use swizzler to sample row fSwizzler->swizzle(dst, dstRow); dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp index 915aded177..4eea8799c5 100644 --- a/src/codec/SkSwizzler.cpp +++ b/src/codec/SkSwizzler.cpp @@ -480,89 +480,6 @@ static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( return COMPUTE_RESULT_ALPHA; } -// kCMYK -// -// CMYK is stored as four bytes per pixel. -// -// 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 -static SkSwizzler::ResultAlpha swizzle_cmyk_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { - - src += offset; - SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < dstWidth; x++) { - const uint8_t r = SkMulDiv255Round(src[0], src[3]); - const uint8_t g = SkMulDiv255Round(src[1], src[3]); - const uint8_t b = SkMulDiv255Round(src[2], src[3]); - - dst[x] = SkPackARGB32NoCheck(0xFF, r, g, b); - src += deltaSrc; - } - - // CMYK is always opaque - return SkSwizzler::kOpaque_ResultAlpha; -} - -static SkSwizzler::ResultAlpha swizzle_cmyk_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { - - src += offset; - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < dstWidth; x++) { - const uint8_t r = SkMulDiv255Round(src[0], src[3]); - const uint8_t g = SkMulDiv255Round(src[1], src[3]); - const uint8_t b = SkMulDiv255Round(src[2], src[3]); - - dst[x] = SkPack888ToRGB16(r, g, b); - src += deltaSrc; - } - - // CMYK is always opaque - return SkSwizzler::kOpaque_ResultAlpha; -} - /** FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes. This would be fine for drawing normally, but not for drawing with transfer modes. Being @@ -755,18 +672,6 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, default: break; } - case kCMYK: - switch (dstInfo.colorType()) { - case kN32_SkColorType: - proc = &swizzle_cmyk_to_n32; - break; - case kRGB_565_SkColorType: - proc = &swizzle_cmyk_to_565; - break; - default: - break; - } - break; default: break; } diff --git a/src/codec/SkSwizzler.h b/src/codec/SkSwizzler.h index 691dc77aa6..fd205880f8 100644 --- a/src/codec/SkSwizzler.h +++ b/src/codec/SkSwizzler.h @@ -33,7 +33,6 @@ public: kRGBA, kBGRA, kRGB_565, - kCMYK, }; /* @@ -98,7 +97,6 @@ public: case kRGBA: case kBGRX: case kBGRA: - case kCMYK: return 32; default: SkASSERT(false); |