aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2016-07-28 17:11:18 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-28 17:11:18 -0700
commit39979d8c6b97889f600a212cfc9b063360f3de2f (patch)
tree3a63566b6e7643335fda8c60451b922c73bac92e
parentecf3dbe8f2987a08b21be1aff61b7fbfbb69640a (diff)
Revert of Add color space xform support to SkJpegCodec (includes F16!) (patchset #9 id:260001 of https://codereview.chromium.org/2174493002/ )
Reason for revert: Breaking MSAN Original issue's description: > Add color space xform support to SkJpegCodec (includes F16!) > > Also changes SkColorXform to support: > RGBA->RGBA > RGBA->BGRA > > Instead of: > RGBA->SkPMColor > > TBR=reed@google.com > BUG=skia: > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2174493002 > CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot > > Committed: https://skia.googlesource.com/skia/+/73d55332e2846dd05e9efdaa2f017bcc3872884b TBR=mtklein@google.com,reed@google.com,herb@google.com,brianosman@google.com # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Review-Url: https://codereview.chromium.org/2195523002
-rw-r--r--bench/CodecBench.cpp4
-rw-r--r--bench/ColorCodecBench.cpp63
-rw-r--r--dm/DM.cpp3
-rw-r--r--dm/DMSrcSink.cpp93
-rw-r--r--include/codec/SkCodec.h6
-rw-r--r--src/codec/SkJpegCodec.cpp268
-rw-r--r--src/codec/SkJpegCodec.h37
-rw-r--r--src/core/SkColorSpaceXform.cpp43
-rw-r--r--src/core/SkColorSpaceXform.h7
-rw-r--r--src/core/SkOpts.cpp3
-rw-r--r--src/core/SkOpts.h11
-rw-r--r--src/opts/SkColorXform_opts.h95
-rw-r--r--src/opts/SkOpts_sse41.cpp11
-rw-r--r--tests/ColorSpaceXformTest.cpp10
-rw-r--r--tools/viewer/ImageSlide.cpp22
15 files changed, 265 insertions, 411 deletions
diff --git a/bench/CodecBench.cpp b/bench/CodecBench.cpp
index 9bd404db55..fc52edfb07 100644
--- a/bench/CodecBench.cpp
+++ b/bench/CodecBench.cpp
@@ -42,9 +42,7 @@ bool CodecBench::isSuitableFor(Backend backend) {
void CodecBench::onDelayedSetup() {
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fData));
- fInfo = codec->getInfo().makeColorType(fColorType)
- .makeAlphaType(fAlphaType)
- .makeColorSpace(nullptr);
+ fInfo = codec->getInfo().makeColorType(fColorType).makeAlphaType(fAlphaType);
fPixelStorage.reset(fInfo.getSafeSize(fInfo.minRowBytes()));
}
diff --git a/bench/ColorCodecBench.cpp b/bench/ColorCodecBench.cpp
index ac1c2bc4c0..e17d597abb 100644
--- a/bench/ColorCodecBench.cpp
+++ b/bench/ColorCodecBench.cpp
@@ -41,13 +41,32 @@ bool ColorCodecBench::isSuitableFor(Backend backend) {
void ColorCodecBench::decodeAndXform() {
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded.get()));
- SkASSERT(codec);
-
#ifdef SK_DEBUG
- SkCodec::Result result =
+ const SkCodec::Result result =
#endif
- codec->getPixels(fDstInfo, fDst.get(), fDstInfo.minRowBytes());
+ codec->startScanlineDecode(fSrcInfo);
SkASSERT(SkCodec::kSuccess == result);
+
+ sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getInfo().colorSpace());
+ if (!srcSpace) {
+ srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+ }
+ std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, fDstSpace);
+ SkASSERT(xform);
+
+ void* dst = fDst.get();
+ for (int y = 0; y < fSrcInfo.height(); y++) {
+#ifdef SK_DEBUG
+ const int rows =
+#endif
+ codec->getScanlines(fSrc.get(), 1, 0);
+ SkASSERT(1 == rows);
+
+ FLAGS_half ?
+ xform->applyToF16((uint64_t*) dst, (uint32_t*) fSrc.get(), fSrcInfo.width()) :
+ xform->applyTo8888((SkPMColor*) dst, (uint32_t*) fSrc.get(), fSrcInfo.width());
+ dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes());
+ }
}
#if defined(SK_TEST_QCMS)
@@ -102,7 +121,7 @@ void ColorCodecBench::xformOnly() {
// Transform in place
FLAGS_half ?
xform->applyToF16((uint64_t*) dst, (uint32_t*) src, fSrcInfo.width()) :
- xform->applyToRGBA((SkPMColor*) dst, (uint32_t*) src, fSrcInfo.width());
+ xform->applyTo8888((SkPMColor*) dst, (uint32_t*) src, fSrcInfo.width());
dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes());
src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes());
}
@@ -138,12 +157,28 @@ void ColorCodecBench::xformOnlyQCMS() {
void ColorCodecBench::onDelayedSetup() {
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded.get()));
+ fSrcInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType);
+
+ fDstInfo = fSrcInfo;
+ if (FLAGS_half) {
+ fDstInfo = fDstInfo.makeColorType(kRGBA_F16_SkColorType);
+ }
+ fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes()));
+
+ if (FLAGS_xform_only) {
+ fSrc.reset(fSrcInfo.getSafeSize(fSrcInfo.minRowBytes()));
+ codec->getPixels(fSrcInfo, fSrc.get(), fSrcInfo.minRowBytes());
+ } else {
+ // Set-up a row buffer to decode into before transforming to dst.
+ fSrc.reset(fSrcInfo.minRowBytes());
+ }
+
fSrcData = codec->getICCData();
sk_sp<SkData> dstData = SkData::MakeFromFileName(
GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str());
SkASSERT(dstData);
- fDstSpace = nullptr;
+
#if defined(SK_TEST_QCMS)
if (FLAGS_qcms) {
fDstSpaceQCMS.reset(FLAGS_srgb ?
@@ -161,22 +196,6 @@ void ColorCodecBench::onDelayedSetup() {
SkColorSpace::NewICC(dstData->data(), dstData->size());
SkASSERT(fDstSpace);
}
-
- fSrcInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType);
-
- fDstInfo = fSrcInfo.makeColorSpace(fDstSpace);
- if (FLAGS_half) {
- fDstInfo = fDstInfo.makeColorType(kRGBA_F16_SkColorType);
- }
- fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes()));
-
- if (FLAGS_xform_only) {
- fSrc.reset(fSrcInfo.getSafeSize(fSrcInfo.minRowBytes()));
- codec->getPixels(fSrcInfo, fSrc.get(), fSrcInfo.minRowBytes());
- } else if (FLAGS_qcms) {
- // Set-up a row buffer to decode into before transforming to dst.
- fSrc.reset(fSrcInfo.minRowBytes());
- }
}
void ColorCodecBench::onDraw(int n, SkCanvas*) {
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 772cfe054d..7a1e5959c8 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -777,8 +777,7 @@ static bool gather_srcs() {
push_src("image", "color_codec_sRGB_kF16", src);
#if defined(SK_TEST_QCMS)
- src = new ColorCodecSrc(colorImage, ColorCodecSrc::kQCMS_HPZR30w_Mode,
- kRGBA_8888_SkColorType);
+ src = new ColorCodecSrc(colorImage, ColorCodecSrc::kQCMS_HPZR30w_Mode, kN32_SkColorType);
push_src("image", "color_codec_QCMS_HPZR30w", src);
#endif
}
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index c03a8c4c98..f3f5f78b57 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -867,46 +867,75 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
}
- // Load the dst ICC profile. This particular dst is fairly similar to Adobe RGB.
- sk_sp<SkData> dstData = SkData::MakeFromFileName(
- GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str());
- if (!dstData) {
- return "Cannot read monitor profile. Is the resource path set correctly?";
- }
-
- sk_sp<SkColorSpace> dstSpace = nullptr;
- if (kDst_sRGB_Mode == fMode) {
- dstSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
- } else if (kDst_HPZR30w_Mode == fMode) {
- dstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size());
- }
-
- SkImageInfo decodeInfo = codec->getInfo().makeColorType(fColorType).makeColorSpace(dstSpace);
- SkImageInfo bitmapInfo = decodeInfo;
- if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
- kBGRA_8888_SkColorType == decodeInfo.colorType())
- {
- bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
- }
-
+ SkImageInfo info = codec->getInfo().makeColorType(fColorType);
SkBitmap bitmap;
- if (!bitmap.tryAllocPixels(bitmapInfo)) {
+ if (!bitmap.tryAllocPixels(info)) {
return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
- bitmapInfo.width(), bitmapInfo.height());
+ info.width(), info.height());
+ }
+
+ SkImageInfo decodeInfo = info;
+ size_t srcRowBytes = sizeof(SkPMColor) * info.width();
+ SkAutoMalloc src(srcRowBytes * info.height());
+ void* srcPixels = src.get();
+ if (kBaseline_Mode == fMode) {
+ srcPixels = bitmap.getPixels();
+ } else {
+ decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType);
}
- size_t rowBytes = bitmap.rowBytes();
- SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), rowBytes);
+ SkCodec::Result r = codec->getPixels(decodeInfo, srcPixels, srcRowBytes);
if (SkCodec::kSuccess != r) {
return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r);
}
+ // Load the dst ICC profile. This particular dst is fairly similar to Adobe RGB.
+ sk_sp<SkData> dstData = SkData::MakeFromFileName(
+ GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str());
+ if (!dstData) {
+ return "Cannot read monitor profile. Is the resource path set correctly?";
+ }
+
switch (fMode) {
case kBaseline_Mode:
+ canvas->drawBitmap(bitmap, 0, 0);
+ break;
case kDst_sRGB_Mode:
- case kDst_HPZR30w_Mode:
+ case kDst_HPZR30w_Mode: {
+ sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getInfo().colorSpace());
+ sk_sp<SkColorSpace> dstSpace = (kDst_sRGB_Mode == fMode) ?
+ SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) :
+ SkColorSpace::NewICC(dstData->data(), dstData->size());
+ SkASSERT(dstSpace);
+
+ std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, dstSpace);
+ if (!xform) {
+ return "Unimplemented color conversion.";
+ }
+
+ if (kN32_SkColorType == fColorType) {
+ uint32_t* srcRow = (uint32_t*) srcPixels;
+ uint32_t* dstRow = (uint32_t*) bitmap.getPixels();
+ for (int y = 0; y < info.height(); y++) {
+ xform->applyTo8888(dstRow, srcRow, info.width());
+ srcRow = SkTAddOffset<uint32_t>(srcRow, srcRowBytes);
+ dstRow = SkTAddOffset<uint32_t>(dstRow, bitmap.rowBytes());
+ }
+ } else {
+ SkASSERT(kRGBA_F16_SkColorType == fColorType);
+
+ uint32_t* srcRow = (uint32_t*) srcPixels;
+ uint64_t* dstRow = (uint64_t*) bitmap.getPixels();
+ for (int y = 0; y < info.height(); y++) {
+ xform->applyToF16(dstRow, srcRow, info.width());
+ srcRow = SkTAddOffset<uint32_t>(srcRow, srcRowBytes);
+ dstRow = SkTAddOffset<uint64_t>(dstRow, bitmap.rowBytes());
+ }
+ }
+
canvas->drawBitmap(bitmap, 0, 0);
break;
+ }
#if defined(SK_TEST_QCMS)
case kQCMS_HPZR30w_Mode: {
sk_sp<SkData> srcData = codec->getICCData();
@@ -938,10 +967,12 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
#endif
// Perform color correction.
- uint32_t* row = (uint32_t*) bitmap.getPixels();
- for (int y = 0; y < decodeInfo.height(); y++) {
- qcms_transform_data_type(transform, row, row, decodeInfo.width(), outType);
- row = SkTAddOffset<uint32_t>(row, rowBytes);
+ uint32_t* srcRow = (uint32_t*) srcPixels;
+ uint32_t* dstRow = (uint32_t*) bitmap.getPixels();
+ for (int y = 0; y < info.height(); y++) {
+ qcms_transform_data_type(transform, srcRow, dstRow, info.width(), outType);
+ srcRow = SkTAddOffset<uint32_t>(srcRow, srcRowBytes);
+ dstRow = SkTAddOffset<uint32_t>(dstRow, bitmap.rowBytes());
}
canvas->drawBitmap(bitmap, 0, 0);
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index c5dc66a474..5c84e07c70 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -286,12 +286,6 @@ public:
* to scale. If the generator cannot perform this scale,
* it will return kInvalidScale.
*
- * If the info contains a non-null SkColorSpace, the codec
- * will perform the appropriate color space transformation.
- * If the caller passes in the same color space that was
- * reported by the codec, the color space transformation is
- * a no-op.
- *
* If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
* SkPMColor values in ctable. On success the generator must copy N colors into that storage,
* (where N is the logical number of table entries) and set ctableCount to N.
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index 6160aa8e47..a81c759ff0 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -196,7 +196,7 @@ bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
// libjpeg errors will be caught and reported here
if (setjmp(decoderMgr->getJmpBuf())) {
- return decoderMgr->returnFalse("ReadHeader");
+ return decoderMgr->returnFalse("setjmp");
}
// Initialize the decompress info and the source manager
@@ -212,7 +212,7 @@ bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
// Read the jpeg header
if (JPEG_HEADER_OK != jpeg_read_header(decoderMgr->dinfo(), true)) {
- return decoderMgr->returnFalse("ReadHeader");
+ return decoderMgr->returnFalse("read_header");
}
if (codecOut) {
@@ -268,8 +268,7 @@ SkJpegCodec::SkJpegCodec(int width, int height, const SkEncodedInfo& info, SkStr
: INHERITED(width, height, info, stream, std::move(colorSpace), origin)
, fDecoderMgr(decoderMgr)
, fReadyState(decoderMgr->dinfo()->global_state)
- , fSwizzleSrcRow(nullptr)
- , fColorXformSrcRow(nullptr)
+ , fSrcRow(nullptr)
, fSwizzlerSubset(SkIRect::MakeEmpty())
, fICCData(std::move(iccData))
{}
@@ -342,16 +341,14 @@ SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
bool SkJpegCodec::onRewind() {
JpegDecoderMgr* decoderMgr = nullptr;
if (!ReadHeader(this->stream(), nullptr, &decoderMgr)) {
- return fDecoderMgr->returnFalse("onRewind");
+ return fDecoderMgr->returnFalse("could not rewind");
}
SkASSERT(nullptr != decoderMgr);
fDecoderMgr.reset(decoderMgr);
fSwizzler.reset(nullptr);
- fSwizzleSrcRow = nullptr;
- fColorXformSrcRow = nullptr;
+ fSrcRow = nullptr;
fStorage.reset();
- fColorXform.reset(nullptr);
return true;
}
@@ -361,23 +358,22 @@ bool SkJpegCodec::onRewind() {
* image has been implemented
* Sets the output color space
*/
-bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dstInfo, bool needsColorXform) {
- if (kUnknown_SkAlphaType == dstInfo.alphaType()) {
+bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
+ if (kUnknown_SkAlphaType == dst.alphaType()) {
return false;
}
- if (kOpaque_SkAlphaType != dstInfo.alphaType()) {
+ if (kOpaque_SkAlphaType != dst.alphaType()) {
SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
"- it is being decoded as non-opaque, which will draw slower\n");
}
- // Check if we will decode to CMYK. libjpeg-turbo does not convert CMYK to RGBA, so
- // we must do it ourselves.
- J_COLOR_SPACE encodedColorType = fDecoderMgr->dinfo()->jpeg_color_space;
- bool isCMYK = (JCS_CMYK == encodedColorType || JCS_YCCK == encodedColorType);
+ // Check if we will decode to CMYK because a conversion to RGBA is not supported
+ J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space;
+ bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace;
// Check for valid color types and set the output color space
- switch (dstInfo.colorType()) {
+ switch (dst.colorType()) {
case kRGBA_8888_SkColorType:
if (isCMYK) {
fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
@@ -388,19 +384,11 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dstInfo, bool needsColo
case kBGRA_8888_SkColorType:
if (isCMYK) {
fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
- } else if (needsColorXform) {
- // Our color transformation code requires RGBA order inputs, but it'll swizzle
- // to BGRA for us.
- fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
} else {
fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
}
return true;
case kRGB_565_SkColorType:
- if (needsColorXform) {
- return false;
- }
-
if (isCMYK) {
fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
} else {
@@ -413,19 +401,12 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dstInfo, bool needsColo
}
return true;
case kGray_8_SkColorType:
- if (needsColorXform || JCS_GRAYSCALE != encodedColorType) {
- return false;
- }
-
- fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
- return true;
- case kRGBA_F16_SkColorType:
- SkASSERT(needsColorXform);
-
if (isCMYK) {
- fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
+ return false;
} else {
- fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
+ // We will enable decodes to gray even if the image is color because this is
+ // much faster than decoding to color and then converting
+ fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
}
return true;
default:
@@ -439,7 +420,7 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dstInfo, bool needsColo
*/
bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
if (setjmp(fDecoderMgr->getJmpBuf())) {
- return fDecoderMgr->returnFalse("onDimensionsSupported");
+ return fDecoderMgr->returnFalse("onDimensionsSupported/setjmp");
}
const unsigned int dstWidth = size.width();
@@ -474,83 +455,6 @@ bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
return true;
}
-static bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
- // FIXME (msarett):
- // Do a better check for color space equality.
- return (kRGBA_F16_SkColorType == dstInfo.colorType()) ||
- (dstInfo.colorSpace() && (dstInfo.colorSpace() != srcInfo.colorSpace()));
-}
-
-int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count) {
- // Set the jump location for libjpeg-turbo errors
- if (setjmp(fDecoderMgr->getJmpBuf())) {
- return 0;
- }
-
- // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case,
- // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer.
- // We can never swizzle "in place" because the swizzler may perform sampling and/or
- // subsetting.
- // When fColorXformSrcRow is non-null, it means that we need to color xform and that
- // we cannot color xform "in place" (many times we can, but not when the dst is F16).
- // In this case, we will color xform from fColorXformSrc into the dst.
- JSAMPLE* decodeDst = (JSAMPLE*) dst;
- uint32_t* swizzleDst = (uint32_t*) dst;
- size_t decodeDstRowBytes = rowBytes;
- size_t swizzleDstRowBytes = rowBytes;
- if (fSwizzleSrcRow && fColorXformSrcRow) {
- decodeDst = (JSAMPLE*) fSwizzleSrcRow;
- swizzleDst = fColorXformSrcRow;
- decodeDstRowBytes = 0;
- swizzleDstRowBytes = 0;
- } else if (fColorXformSrcRow) {
- decodeDst = (JSAMPLE*) fColorXformSrcRow;
- swizzleDst = fColorXformSrcRow;
- decodeDstRowBytes = 0;
- swizzleDstRowBytes = 0;
- } else if (fSwizzleSrcRow) {
- decodeDst = (JSAMPLE*) fSwizzleSrcRow;
- decodeDstRowBytes = 0;
- }
-
- for (int y = 0; y < count; y++) {
- uint32_t lines = jpeg_read_scanlines(fDecoderMgr->dinfo(), &decodeDst, 1);
- sk_msan_mark_initialized(decodeDst, decodeDst + rowBytes, "skbug.com/4550");
- if (0 == lines) {
- return y;
- }
-
- if (fSwizzler) {
- fSwizzler->swizzle(swizzleDst, decodeDst);
- }
-
- if (fColorXform) {
- int width = dstInfo.width();
- switch (dstInfo.colorType()) {
- case kRGBA_8888_SkColorType:
- fColorXform->applyToRGBA((uint32_t*) dst, swizzleDst, width);
- break;
- case kBGRA_8888_SkColorType:
- fColorXform->applyToBGRA((uint32_t*) dst, swizzleDst, width);
- break;
- case kRGBA_F16_SkColorType:
- fColorXform->applyToF16((uint64_t*) dst, swizzleDst, width);
- break;
- default:
- SkASSERT(false);
- break;
- }
-
- dst = SkTAddOffset<void>(dst, rowBytes);
- }
-
- decodeDst = SkTAddOffset<JSAMPLE>(decodeDst, decodeDstRowBytes);
- swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
- }
-
- return count;
-}
-
/*
* Performs the jpeg decode
*/
@@ -572,15 +476,11 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
}
// Check if we can decode to the requested destination and set the output color space
- bool needsColorXform = needs_color_xform(dstInfo, this->getInfo());
- if (!this->setOutputColorSpace(dstInfo, needsColorXform)) {
- return fDecoderMgr->returnFailure("setOutputColorSpace", kInvalidConversion);
- }
-
- if (!this->initializeColorXform(dstInfo, needsColorXform)) {
- return fDecoderMgr->returnFailure("initializeColorXform", kInvalidParameters);
+ if (!this->setOutputColorSpace(dstInfo)) {
+ return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion);
}
+ // Now, given valid output dimensions, we can start the decompress
if (!jpeg_start_decompress(dinfo)) {
return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
}
@@ -594,37 +494,39 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
this->initializeSwizzler(dstInfo, options);
}
- this->allocateStorage(dstInfo);
+ // Perform the decode a single row at a time
+ uint32_t dstHeight = dstInfo.height();
- int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height());
- if (rows < dstInfo.height()) {
- *rowsDecoded = rows;
- return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
+ JSAMPLE* dstRow;
+ if (fSwizzler) {
+ // write data to storage row, then sample using swizzler
+ dstRow = fSrcRow;
+ } else {
+ // write data directly to dst
+ dstRow = (JSAMPLE*) dst;
}
- return kSuccess;
-}
+ for (uint32_t y = 0; y < dstHeight; y++) {
+ // Read rows of the image
+ uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1);
+ sk_msan_mark_initialized(dstRow, dstRow + dstRowBytes, "skbug.com/4550");
-void SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) {
- size_t swizzleBytes = 0;
- if (fSwizzler) {
- swizzleBytes = get_row_bytes(fDecoderMgr->dinfo());
- SkASSERT(!fColorXform || SkIsAlign4(swizzleBytes));
- }
+ // If we cannot read enough rows, assume the input is incomplete
+ if (lines != 1) {
+ *rowsDecoded = y;
+ return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
+ }
- size_t xformBytes = 0;
- if (kRGBA_F16_SkColorType == dstInfo.colorType()) {
- SkASSERT(fColorXform);
- xformBytes = dstInfo.width() * sizeof(SkColorSpaceXform::RGBA32);
+ if (fSwizzler) {
+ // use swizzler to sample row
+ fSwizzler->swizzle(dst, dstRow);
+ dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
+ } else {
+ dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
+ }
}
- size_t totalBytes = swizzleBytes + xformBytes;
- if (totalBytes > 0) {
- fStorage.reset(totalBytes);
- fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
- fColorXformSrcRow = (xformBytes > 0) ?
- SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
- }
+ return kSuccess;
}
void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
@@ -641,9 +543,9 @@ void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options&
break;
case JCS_CMYK:
preSwizzled = false;
- swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Color,
- swizzlerInfo.alpha(),
- swizzlerInfo.bitsPerComponent());
+ swizzlerInfo = SkEncodedInfo::Make(
+ SkEncodedInfo::kInvertedCMYK_Color, swizzlerInfo.alpha(),
+ swizzlerInfo.bitsPerComponent());
break;
default:
break;
@@ -661,28 +563,17 @@ void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options&
fSwizzler.reset(SkSwizzler::CreateSwizzler(swizzlerInfo, nullptr, dstInfo, swizzlerOptions,
nullptr, preSwizzled));
SkASSERT(fSwizzler);
-}
-
-bool SkJpegCodec::initializeColorXform(const SkImageInfo& dstInfo, bool needsColorXform) {
- if (needsColorXform) {
- fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpace()),
- sk_ref_sp(dstInfo.colorSpace()));
- if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) {
- return false;
- }
- }
-
- return true;
+ fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
+ fSrcRow = fStorage.get();
}
SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
if (!createIfNecessary || fSwizzler) {
- SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
+ SkASSERT(!fSwizzler || (fSrcRow && fStorage.get() == fSrcRow));
return fSwizzler;
}
this->initializeSwizzler(this->dstInfo(), this->options());
- this->allocateStorage(this->dstInfo());
return fSwizzler;
}
@@ -695,15 +586,11 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
}
// Check if we can decode to the requested destination and set the output color space
- bool needsColorXform = needs_color_xform(dstInfo, this->getInfo());
- if (!this->setOutputColorSpace(dstInfo, needsColorXform)) {
+ if (!this->setOutputColorSpace(dstInfo)) {
return kInvalidConversion;
}
- if (!this->initializeColorXform(dstInfo, needsColorXform)) {
- return fDecoderMgr->returnFailure("initializeColorXform", kInvalidParameters);
- }
-
+ // Now, given valid output dimensions, we can start the decompress
if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
SkCodecPrintf("start decompress failed\n");
return kInvalidInput;
@@ -764,37 +651,62 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
}
#endif
- this->allocateStorage(dstInfo);
-
return kSuccess;
}
int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
- int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count);
- if (rows < count) {
- // This allows us to skip calling jpeg_finish_decompress().
- fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
+ // Set the jump location for libjpeg errors
+ if (setjmp(fDecoderMgr->getJmpBuf())) {
+ return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
+ }
+ // Read rows one at a time
+ JSAMPLE* dstRow;
+ size_t srcRowBytes = get_row_bytes(fDecoderMgr->dinfo());
+ if (fSwizzler) {
+ // write data to storage row, then sample using swizzler
+ dstRow = fSrcRow;
+ } else {
+ // write data directly to dst
+ SkASSERT(count == 1 || dstRowBytes >= srcRowBytes);
+ dstRow = (JSAMPLE*) dst;
}
- return rows;
+ for (int y = 0; y < count; y++) {
+ // Read row of the image
+ uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow, 1);
+ sk_msan_mark_initialized(dstRow, dstRow + srcRowBytes, "skbug.com/4550");
+ if (rowsDecoded != 1) {
+ fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
+ return y;
+ }
+
+ if (fSwizzler) {
+ // use swizzler to sample row
+ fSwizzler->swizzle(dst, dstRow);
+ dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
+ } else {
+ dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
+ }
+ }
+ return count;
}
bool SkJpegCodec::onSkipScanlines(int count) {
// Set the jump location for libjpeg errors
if (setjmp(fDecoderMgr->getJmpBuf())) {
- return fDecoderMgr->returnFalse("onSkipScanlines");
+ return fDecoderMgr->returnFalse("setjmp");
}
#ifdef TURBO_HAS_SKIP
return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
#else
- if (!fSwizzleSrcRow) {
+ if (!fSrcRow) {
fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
- fSwizzleSrcRow = fStorage.get();
+ fSrcRow = fStorage.get();
}
for (int y = 0; y < count; y++) {
- if (1 != jpeg_read_scanlines(fDecoderMgr->dinfo(), &fSwizzleSrcRow, 1)) {
+ if (1 != jpeg_read_scanlines(fDecoderMgr->dinfo(), &fSrcRow, 1)) {
return false;
}
}
diff --git a/src/codec/SkJpegCodec.h b/src/codec/SkJpegCodec.h
index 7eb5100a8f..7aa275ce4e 100644
--- a/src/codec/SkJpegCodec.h
+++ b/src/codec/SkJpegCodec.h
@@ -10,7 +10,6 @@
#include "SkCodec.h"
#include "SkColorSpace.h"
-#include "SkColorSpaceXform.h"
#include "SkImageInfo.h"
#include "SkSwizzler.h"
#include "SkStream.h"
@@ -100,46 +99,34 @@ private:
/*
* Checks if the conversion between the input image and the requested output
- * image has been implemented.
- *
- * Sets the output color space.
+ * image has been implemented
+ * Sets the output color space
*/
- bool setOutputColorSpace(const SkImageInfo& dst, bool needsColorXform);
+ bool setOutputColorSpace(const SkImageInfo& dst);
+ // scanline decoding
void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options);
- bool initializeColorXform(const SkImageInfo& dstInfo, bool needsColorXform);
- void allocateStorage(const SkImageInfo& dstInfo);
- int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count);
-
- /*
- * Scanline decoding.
- */
SkSampler* getSampler(bool createIfNecessary) override;
Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options,
SkPMColor ctable[], int* ctableCount) override;
int onGetScanlines(void* dst, int count, size_t rowBytes) override;
bool onSkipScanlines(int count) override;
- SkAutoTDelete<JpegDecoderMgr> fDecoderMgr;
-
+ SkAutoTDelete<JpegDecoderMgr> fDecoderMgr;
// We will save the state of the decompress struct after reading the header.
// This allows us to safely call onGetScaledDimensions() at any time.
- const int fReadyState;
-
-
- SkAutoTMalloc<uint8_t> fStorage;
- uint8_t* fSwizzleSrcRow;
- uint32_t* fColorXformSrcRow;
+ const int fReadyState;
+ // scanline decoding
+ SkAutoTMalloc<uint8_t> fStorage; // Only used if sampling is needed
+ uint8_t* fSrcRow; // Only used if sampling is needed
// libjpeg-turbo provides some subsetting. In the case that libjpeg-turbo
// cannot take the exact the subset that we need, we will use the swizzler
// to further subset the output from libjpeg-turbo.
- SkIRect fSwizzlerSubset;
-
- SkAutoTDelete<SkSwizzler> fSwizzler;
- std::unique_ptr<SkColorSpaceXform> fColorXform;
+ SkIRect fSwizzlerSubset;
+ SkAutoTDelete<SkSwizzler> fSwizzler;
- sk_sp<SkData> fICCData;
+ sk_sp<SkData> fICCData;
typedef SkCodec INHERITED;
};
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
index 4fbfa6cd9e..924f24f6fc 100644
--- a/src/core/SkColorSpaceXform.cpp
+++ b/src/core/SkColorSpaceXform.cpp
@@ -629,7 +629,7 @@ SkColorSpaceXform_Base<Dst>::SkColorSpaceXform_Base(const sk_sp<SkColorSpace>& s
template <>
void SkColorSpaceXform_Base<SkColorSpace::kSRGB_GammaNamed>
-::applyToRGBA(RGBA32* dst, const RGBA32* src, int len) const
+::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
{
if (fColorLUT) {
handle_color_lut(dst, src, len, fColorLUT.get());
@@ -641,7 +641,7 @@ void SkColorSpaceXform_Base<SkColorSpace::kSRGB_GammaNamed>
template <>
void SkColorSpaceXform_Base<SkColorSpace::k2Dot2Curve_GammaNamed>
-::applyToRGBA(RGBA32* dst, const RGBA32* src, int len) const
+::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
{
if (fColorLUT) {
handle_color_lut(dst, src, len, fColorLUT.get());
@@ -653,7 +653,7 @@ void SkColorSpaceXform_Base<SkColorSpace::k2Dot2Curve_GammaNamed>
template <>
void SkColorSpaceXform_Base<SkColorSpace::kNonStandard_GammaNamed>
-::applyToRGBA(RGBA32* dst, const RGBA32* src, int len) const
+::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
{
if (fColorLUT) {
handle_color_lut(dst, src, len, fColorLUT.get());
@@ -663,43 +663,6 @@ void SkColorSpaceXform_Base<SkColorSpace::kNonStandard_GammaNamed>
SkOpts::color_xform_RGB1_to_table(dst, src, len, fSrcGammaTables, fSrcToDst, fDstGammaTables);
}
-template <>
-void SkColorSpaceXform_Base<SkColorSpace::kSRGB_GammaNamed>
-::applyToBGRA(BGRA32* dst, const RGBA32* src, int len) const
-{
- if (fColorLUT) {
- handle_color_lut(dst, src, len, fColorLUT.get());
- src = dst;
- }
-
- SkOpts::color_xform_RGB1_to_srgb_swaprb(dst, src, len, fSrcGammaTables, fSrcToDst);
-}
-
-template <>
-void SkColorSpaceXform_Base<SkColorSpace::k2Dot2Curve_GammaNamed>
-::applyToBGRA(BGRA32* dst, const RGBA32* src, int len) const
-{
- if (fColorLUT) {
- handle_color_lut(dst, src, len, fColorLUT.get());
- src = dst;
- }
-
- SkOpts::color_xform_RGB1_to_2dot2_swaprb(dst, src, len, fSrcGammaTables, fSrcToDst);
-}
-
-template <>
-void SkColorSpaceXform_Base<SkColorSpace::kNonStandard_GammaNamed>
-::applyToBGRA(BGRA32* dst, const RGBA32* src, int len) const
-{
- if (fColorLUT) {
- handle_color_lut(dst, src, len, fColorLUT.get());
- src = dst;
- }
-
- SkOpts::color_xform_RGB1_to_table_swaprb(dst, src, len, fSrcGammaTables, fSrcToDst,
- fDstGammaTables);
-}
-
template <SkColorSpace::GammaNamed T>
void SkColorSpaceXform_Base<T>
::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const
diff --git a/src/core/SkColorSpaceXform.h b/src/core/SkColorSpaceXform.h
index 2696b8582a..0a5b35c489 100644
--- a/src/core/SkColorSpaceXform.h
+++ b/src/core/SkColorSpaceXform.h
@@ -15,7 +15,6 @@ class SkColorSpaceXform : SkNoncopyable {
public:
typedef uint32_t RGBA32;
- typedef uint32_t BGRA32;
typedef uint64_t RGBAF16;
/**
@@ -33,8 +32,7 @@ public:
* The src is stored as RGBA (8888) and is treated as opaque.
* TODO (msarett): Support non-opaque srcs.
*/
- virtual void applyToRGBA(RGBA32* dst, const RGBA32* src, int len) const = 0;
- virtual void applyToBGRA(BGRA32* dst, const RGBA32* src, int len) const = 0;
+ virtual void applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const = 0;
virtual void applyToF16(RGBAF16* dst, const RGBA32* src, int len) const = 0;
virtual ~SkColorSpaceXform() {}
@@ -44,8 +42,7 @@ template <SkColorSpace::GammaNamed Dst>
class SkColorSpaceXform_Base : public SkColorSpaceXform {
public:
- void applyToRGBA(RGBA32* dst, const RGBA32* src, int len) const override;
- void applyToBGRA(BGRA32* dst, const RGBA32* src, int len) const override;
+ void applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const override;
void applyToF16(RGBAF16* dst, const RGBA32* src, int len) const override;
static constexpr int kDstGammaTableSize = 1024;
diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp
index 9ba7bc7178..c577bf9603 100644
--- a/src/core/SkOpts.cpp
+++ b/src/core/SkOpts.cpp
@@ -76,9 +76,6 @@ namespace SkOpts {
DEFINE_DEFAULT(color_xform_RGB1_to_srgb);
DEFINE_DEFAULT(color_xform_RGB1_to_table);
DEFINE_DEFAULT(color_xform_RGB1_to_linear);
- DEFINE_DEFAULT(color_xform_RGB1_to_2dot2_swaprb);
- DEFINE_DEFAULT(color_xform_RGB1_to_srgb_swaprb);
- DEFINE_DEFAULT(color_xform_RGB1_to_table_swaprb);
#undef DEFINE_DEFAULT
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
index 87489ee94e..fc424e1473 100644
--- a/src/core/SkOpts.h
+++ b/src/core/SkOpts.h
@@ -80,16 +80,7 @@ namespace SkOpts {
extern void (*color_xform_RGB1_to_linear)(uint64_t* dst, const uint32_t* src, int len,
const float* const srcTables[3],
const float srcToDstMatrix[16]);
- extern void (*color_xform_RGB1_to_2dot2_swaprb) (uint32_t* dst, const uint32_t* src, int len,
- const float* const srcTables[3],
- const float srcToDstMatrix[16]);
- extern void (*color_xform_RGB1_to_srgb_swaprb)(uint32_t* dst, const uint32_t* src, int len,
- const float* const srcTables[3],
- const float srcToDstMatrix[16]);
- extern void (*color_xform_RGB1_to_table_swaprb)(uint32_t* dst, const uint32_t* src, int len,
- const float* const srcTables[3],
- const float srcToDstMatrix[16],
- const uint8_t* const dstTables[3]);
+
}
#endif//SkOpts_DEFINED
diff --git a/src/opts/SkColorXform_opts.h b/src/opts/SkColorXform_opts.h
index b3da55c1fd..b5b7f81bbf 100644
--- a/src/opts/SkColorXform_opts.h
+++ b/src/opts/SkColorXform_opts.h
@@ -41,19 +41,10 @@ enum DstGamma {
kLinear_DstGamma,
};
-template <DstGamma kDstGamma, bool kSwapRB>
+template <DstGamma kDstGamma>
static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
const float* const srcTables[3], const float matrix[16],
const uint8_t* const dstTables[3]) {
- int kRShift = 0;
- int kGShift = 8;
- int kBShift = 16;
- int kAShift = 24;
- if (kSwapRB) {
- kBShift = 0;
- kRShift = 16;
- }
-
Sk4f rXgXbX = Sk4f::Load(matrix + 0),
rYgYbY = Sk4f::Load(matrix + 4),
rZgZbZ = Sk4f::Load(matrix + 8),
@@ -86,8 +77,7 @@ static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
dstBlues = rXgXbX[2]*reds + rYgYbY[2]*greens + rZgZbZ[2]*blues + rTgTbT[2];
};
- auto store_4 = [&dstReds, &dstGreens, &dstBlues, &dst, &dstTables, kRShift, kGShift,
- kBShift, kAShift] {
+ auto store_4 = [&dstReds, &dstGreens, &dstBlues, &dst, &dstTables] {
if (kSRGB_DstGamma == kDstGamma || k2Dot2_DstGamma == kDstGamma) {
Sk4f (*linear_to_curve)(const Sk4f&) = (kSRGB_DstGamma == kDstGamma) ?
sk_linear_to_srgb_needs_trunc : linear_to_2dot2;
@@ -102,10 +92,10 @@ static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
dstGreens = sk_clamp_0_255(dstGreens);
dstBlues = sk_clamp_0_255(dstBlues);
- auto rgba = (float_to_int(dstReds) << kRShift)
- | (float_to_int(dstGreens) << kGShift)
- | (float_to_int(dstBlues) << kBShift)
- | (Sk4i{0xFF} << kAShift);
+ auto rgba = (float_to_int(dstReds) << SK_R32_SHIFT)
+ | (float_to_int(dstGreens) << SK_G32_SHIFT)
+ | (float_to_int(dstBlues) << SK_B32_SHIFT)
+ | (Sk4i{0xFF} << SK_A32_SHIFT);
rgba.store((uint32_t*) dst);
dst = SkTAddOffset<void>(dst, 4 * sizeof(uint32_t));
@@ -119,22 +109,22 @@ static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
Sk4i indicesBlues = Sk4f_round(scaledBlues);
uint32_t* dst32 = (uint32_t*) dst;
- dst32[0] = dstTables[0][indicesReds [0]] << kRShift
- | dstTables[1][indicesGreens[0]] << kGShift
- | dstTables[2][indicesBlues [0]] << kBShift
- | 0xFF << kAShift;
- dst32[1] = dstTables[0][indicesReds [1]] << kRShift
- | dstTables[1][indicesGreens[1]] << kGShift
- | dstTables[2][indicesBlues [1]] << kBShift
- | 0xFF << kAShift;
- dst32[2] = dstTables[0][indicesReds [2]] << kRShift
- | dstTables[1][indicesGreens[2]] << kGShift
- | dstTables[2][indicesBlues [2]] << kBShift
- | 0xFF << kAShift;
- dst32[3] = dstTables[0][indicesReds [3]] << kRShift
- | dstTables[1][indicesGreens[3]] << kGShift
- | dstTables[2][indicesBlues [3]] << kBShift
- | 0xFF << kAShift;
+ dst32[0] = dstTables[0][indicesReds [0]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[0]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [0]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+ dst32[1] = dstTables[0][indicesReds [1]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[1]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [1]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+ dst32[2] = dstTables[0][indicesReds [2]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[2]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [2]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+ dst32[3] = dstTables[0][indicesReds [3]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[3]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [3]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
dst = SkTAddOffset<void>(dst, 4 * sizeof(uint32_t));
} else {
@@ -177,21 +167,17 @@ static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
uint32_t rgba;
SkNx_cast<uint8_t>(float_to_int(dstPixel)).store(&rgba);
rgba |= 0xFF000000;
- if (kSwapRB) {
- *((uint32_t*) dst) = SkSwizzle_RB(rgba);
- } else {
- *((uint32_t*) dst) = rgba;
- }
+ *((uint32_t*) dst) = SkSwizzle_RGBA_to_PMColor(rgba);
dst = SkTAddOffset<void>(dst, sizeof(uint32_t));
} else if (kTable_DstGamma == kDstGamma) {
Sk4f scaledPixel = Sk4f::Min(Sk4f::Max(1023.0f * dstPixel, 0.0f), 1023.0f);
Sk4i indices = Sk4f_round(scaledPixel);
- *((uint32_t*) dst) = dstTables[0][indices[0]] << kRShift
- | dstTables[1][indices[1]] << kGShift
- | dstTables[2][indices[2]] << kBShift
- | 0xFF << kAShift;
+ *((uint32_t*) dst) = dstTables[0][indices[0]] << SK_R32_SHIFT
+ | dstTables[1][indices[1]] << SK_G32_SHIFT
+ | dstTables[2][indices[2]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
dst = SkTAddOffset<void>(dst, sizeof(uint32_t));
} else {
@@ -209,42 +195,23 @@ static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
static void color_xform_RGB1_to_2dot2(uint32_t* dst, const uint32_t* src, int len,
const float* const srcTables[3], const float matrix[16]) {
- color_xform_RGB1<k2Dot2_DstGamma, false>(dst, src, len, srcTables, matrix, nullptr);
+ color_xform_RGB1<k2Dot2_DstGamma>(dst, src, len, srcTables, matrix, nullptr);
}
static void color_xform_RGB1_to_srgb(uint32_t* dst, const uint32_t* src, int len,
const float* const srcTables[3], const float matrix[16]) {
- color_xform_RGB1<kSRGB_DstGamma, false>(dst, src, len, srcTables, matrix, nullptr);
+ color_xform_RGB1<kSRGB_DstGamma>(dst, src, len, srcTables, matrix, nullptr);
}
static void color_xform_RGB1_to_table(uint32_t* dst, const uint32_t* src, int len,
const float* const srcTables[3], const float matrix[16],
const uint8_t* const dstTables[3]) {
- color_xform_RGB1<kTable_DstGamma, false>(dst, src, len, srcTables, matrix, dstTables);
+ color_xform_RGB1<kTable_DstGamma>(dst, src, len, srcTables, matrix, dstTables);
}
static void color_xform_RGB1_to_linear(uint64_t* dst, const uint32_t* src, int len,
const float* const srcTables[3], const float matrix[16]) {
- color_xform_RGB1<kLinear_DstGamma, false>(dst, src, len, srcTables, matrix, nullptr);
-}
-
-static void color_xform_RGB1_to_2dot2_swaprb(uint32_t* dst, const uint32_t* src, int len,
- const float* const srcTables[3],
- const float matrix[16]) {
- color_xform_RGB1<k2Dot2_DstGamma, true>(dst, src, len, srcTables, matrix, nullptr);
-}
-
-static void color_xform_RGB1_to_srgb_swaprb(uint32_t* dst, const uint32_t* src, int len,
- const float* const srcTables[3],
- const float matrix[16]) {
- color_xform_RGB1<kSRGB_DstGamma, true>(dst, src, len, srcTables, matrix, nullptr);
-}
-
-static void color_xform_RGB1_to_table_swaprb(uint32_t* dst, const uint32_t* src, int len,
- const float* const srcTables[3],
- const float matrix[16],
- const uint8_t* const dstTables[3]) {
- color_xform_RGB1<kTable_DstGamma, true>(dst, src, len, srcTables, matrix, dstTables);
+ color_xform_RGB1<kLinear_DstGamma>(dst, src, len, srcTables, matrix, nullptr);
}
} // namespace SK_OPTS_NS
diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp
index e70cedeb31..e1e024d948 100644
--- a/src/opts/SkOpts_sse41.cpp
+++ b/src/opts/SkOpts_sse41.cpp
@@ -21,12 +21,9 @@ namespace SkOpts {
srcover_srgb_srgb = sse41::srcover_srgb_srgb;
blit_row_s32a_opaque = sse41::blit_row_s32a_opaque;
- color_xform_RGB1_to_2dot2 = sse41::color_xform_RGB1_to_2dot2;
- color_xform_RGB1_to_srgb = sse41::color_xform_RGB1_to_srgb;
- color_xform_RGB1_to_table = sse41::color_xform_RGB1_to_table;
- color_xform_RGB1_to_linear = sse41::color_xform_RGB1_to_linear;
- color_xform_RGB1_to_2dot2_swaprb = sse41::color_xform_RGB1_to_2dot2_swaprb;
- color_xform_RGB1_to_srgb_swaprb = sse41::color_xform_RGB1_to_srgb_swaprb;
- color_xform_RGB1_to_table_swaprb = sse41::color_xform_RGB1_to_table_swaprb;
+ color_xform_RGB1_to_2dot2 = sse41::color_xform_RGB1_to_2dot2;
+ color_xform_RGB1_to_srgb = sse41::color_xform_RGB1_to_srgb;
+ color_xform_RGB1_to_table = sse41::color_xform_RGB1_to_table;
+ color_xform_RGB1_to_linear = sse41::color_xform_RGB1_to_linear;
}
}
diff --git a/tests/ColorSpaceXformTest.cpp b/tests/ColorSpaceXformTest.cpp
index 1e75ee6853..23b08ce8ae 100644
--- a/tests/ColorSpaceXformTest.cpp
+++ b/tests/ColorSpaceXformTest.cpp
@@ -37,19 +37,19 @@ static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& ga
// Create and perform an identity xform.
std::unique_ptr<SkColorSpaceXform> xform = ColorSpaceXformTest::CreateIdentityXform(gammas);
- xform->applyToRGBA(dstPixels, srcPixels, width);
+ xform->applyTo8888(dstPixels, srcPixels, width);
// Since the src->dst matrix is the identity, and the gamma curves match,
// the pixels should be unchanged.
for (int i = 0; i < width; i++) {
REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 0) & 0xFF),
- ((dstPixels[i] >> 0) & 0xFF)));
+ SkGetPackedR32(dstPixels[i])));
REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 8) & 0xFF),
- ((dstPixels[i] >> 8) & 0xFF)));
+ SkGetPackedG32(dstPixels[i])));
REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 16) & 0xFF),
- ((dstPixels[i] >> 16) & 0xFF)));
+ SkGetPackedB32(dstPixels[i])));
REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF),
- ((dstPixels[i] >> 24) & 0xFF)));
+ SkGetPackedA32(dstPixels[i])));
}
}
diff --git a/tools/viewer/ImageSlide.cpp b/tools/viewer/ImageSlide.cpp
index 7dcee5d5ac..b0471547bc 100644
--- a/tools/viewer/ImageSlide.cpp
+++ b/tools/viewer/ImageSlide.cpp
@@ -37,18 +37,20 @@ void ImageSlide::draw(SkCanvas* canvas) {
void ImageSlide::load(SkScalar, SkScalar) {
sk_sp<SkData> encoded = SkData::MakeFromFileName(fPath.c_str());
+ fImage = SkImage::MakeFromEncoded(encoded);
+ fImage->asLegacyBitmap(&fOriginalBitmap, SkImage::kRO_LegacyBitmapMode);
+
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded.get()));
- if (!codec) {
- return;
+ sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getInfo().colorSpace());
+ sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named);
+ std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, dstSpace);
+ fOriginalBitmap.deepCopyTo(&fXformedBitmap);
+ uint32_t* row = (uint32_t*) fXformedBitmap.getPixels();
+ for (int y = 0; y < fXformedBitmap.height(); y++) {
+ xform->applyTo8888(row, row, fXformedBitmap.width());
+ row = SkTAddOffset<uint32_t>(row, fXformedBitmap.rowBytes());
}
-
- fOriginalBitmap.allocPixels(codec->getInfo());
- codec->getPixels(codec->getInfo(), fOriginalBitmap.getPixels(), fOriginalBitmap.rowBytes());
-
- SkImageInfo xformedInfo = codec->getInfo().makeColorSpace(
- SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named));
- fXformedBitmap.allocPixels(xformedInfo);
- codec->getPixels(xformedInfo, fXformedBitmap.getPixels(), fXformedBitmap.rowBytes());
+ fXformedBitmap.notifyPixelsChanged(); // This is needed for the deepCopy
}
void ImageSlide::unload() {