aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@google.com>2015-10-23 08:39:58 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-23 08:39:58 -0700
commitb7f1251775390cdcf58197fd904d7676b9508128 (patch)
tree9db226d8ae7298ccad12f309900bc0e892e9697e /src
parent450ee8f26d39f975cf6af37a27de658ae5a9fa10 (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.cpp145
-rw-r--r--src/codec/SkSwizzler.cpp95
-rw-r--r--src/codec/SkSwizzler.h2
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);