diff options
author | msarett <msarett@google.com> | 2016-07-28 17:11:18 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-07-28 17:11:18 -0700 |
commit | 39979d8c6b97889f600a212cfc9b063360f3de2f (patch) | |
tree | 3a63566b6e7643335fda8c60451b922c73bac92e | |
parent | ecf3dbe8f2987a08b21be1aff61b7fbfbb69640a (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.cpp | 4 | ||||
-rw-r--r-- | bench/ColorCodecBench.cpp | 63 | ||||
-rw-r--r-- | dm/DM.cpp | 3 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 93 | ||||
-rw-r--r-- | include/codec/SkCodec.h | 6 | ||||
-rw-r--r-- | src/codec/SkJpegCodec.cpp | 268 | ||||
-rw-r--r-- | src/codec/SkJpegCodec.h | 37 | ||||
-rw-r--r-- | src/core/SkColorSpaceXform.cpp | 43 | ||||
-rw-r--r-- | src/core/SkColorSpaceXform.h | 7 | ||||
-rw-r--r-- | src/core/SkOpts.cpp | 3 | ||||
-rw-r--r-- | src/core/SkOpts.h | 11 | ||||
-rw-r--r-- | src/opts/SkColorXform_opts.h | 95 | ||||
-rw-r--r-- | src/opts/SkOpts_sse41.cpp | 11 | ||||
-rw-r--r-- | tests/ColorSpaceXformTest.cpp | 10 | ||||
-rw-r--r-- | tools/viewer/ImageSlide.cpp | 22 |
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*) { @@ -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() { |