diff --git a/include/core/SkImageGenerator.h b/include/core/SkImageGenerator.h index 6263dee574..8624359e1a 100644 --- a/include/core/SkImageGenerator.h +++ b/include/core/SkImageGenerator.h @@ -177,6 +177,23 @@ protected: return false; } + struct Options { + Options() + : fColorTable(nullptr) + , fColorTableCount(nullptr) + , fBehavior(SkTransferFunctionBehavior::kRespect) + {} + + SkPMColor* fColorTable; + int* fColorTableCount; + SkTransferFunctionBehavior fBehavior; + }; + bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options* opts); + virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, + const Options& opts) { + return this->onGetPixels(info, pixels, rowBytes, opts.fColorTable, opts.fColorTableCount); + } + #if SK_SUPPORT_GPU virtual sk_sp onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&); @@ -186,6 +203,8 @@ private: const SkImageInfo fInfo; const uint32_t fUniqueID; + friend class SkImageCacherator; + // This is our default impl, which may be different on different platforms. // It is called from NewFromEncoded() after it has checked for any runtime factory. // The SkData will never be NULL, as that will have been checked by NewFromEncoded. diff --git a/src/codec/SkCodecImageGenerator.cpp b/src/codec/SkCodecImageGenerator.cpp index 56ca21eb76..6467033371 100644 --- a/src/codec/SkCodecImageGenerator.cpp +++ b/src/codec/SkCodecImageGenerator.cpp @@ -37,8 +37,19 @@ SkData* SkCodecImageGenerator::onRefEncodedData(GrContext* ctx) { bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount) { - SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, nullptr, ctable, - ctableCount); + Options opts; + opts.fColorTable = ctable; + opts.fColorTableCount = ctableCount; + opts.fBehavior = SkTransferFunctionBehavior::kRespect; + return this->onGetPixels(info, pixels, rowBytes, opts); +} + +bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, + const Options& opts) { + SkCodec::Options codecOpts; + codecOpts.fPremulBehavior = opts.fBehavior; + SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, &codecOpts, opts.fColorTable, + opts.fColorTableCount); switch (result) { case SkCodec::kSuccess: case SkCodec::kIncompleteInput: diff --git a/src/codec/SkCodecImageGenerator.h b/src/codec/SkCodecImageGenerator.h index 727a747ec2..a435205fa9 100644 --- a/src/codec/SkCodecImageGenerator.h +++ b/src/codec/SkCodecImageGenerator.h @@ -24,7 +24,9 @@ protected: SkData* onRefEncodedData(GrContext* ctx) override; bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], - int* ctableCount) override; + int* ctableCount) override; + bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts) + override; bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const override; diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index 4929c6b94c..1a37f3b217 100644 --- a/src/core/SkImageCacherator.cpp +++ b/src/core/SkImageCacherator.cpp @@ -166,14 +166,18 @@ bool SkImageCacherator::generateBitmap(SkBitmap* bitmap, const SkImageInfo& deco } bool SkImageCacherator::directGeneratePixels(const SkImageInfo& info, void* pixels, size_t rb, - int srcX, int srcY) { + int srcX, int srcY, + SkTransferFunctionBehavior behavior) { ScopedGenerator generator(fSharedGenerator); const SkImageInfo& genInfo = generator->getInfo(); // Currently generators do not natively handle subsets, so check that first. if (srcX || srcY || genInfo.width() != info.width() || genInfo.height() != info.height()) { return false; } - return generator->getPixels(info, pixels, rb); + + SkImageGenerator::Options opts; + opts.fBehavior = behavior; + return generator->getPixels(info, pixels, rb, &opts); } ////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h index e75aab7a93..233b7db13e 100644 --- a/src/core/SkImageCacherator.h +++ b/src/core/SkImageCacherator.h @@ -88,7 +88,7 @@ public: bool lockAsBitmapOnlyIfAlreadyCached(SkBitmap*, CachedFormat); // Call the underlying generator directly bool directGeneratePixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, - int srcX, int srcY); + int srcX, int srcY, SkTransferFunctionBehavior behavior); private: // Ref-counted tuple(SkImageGenerator, SkMutex) which allows sharing of one generator diff --git a/src/core/SkImageGenerator.cpp b/src/core/SkImageGenerator.cpp index 18a6ce2669..2f209ca99c 100644 --- a/src/core/SkImageGenerator.cpp +++ b/src/core/SkImageGenerator.cpp @@ -45,6 +45,15 @@ bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t r return success; } +bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, + const Options* opts) { + Options defaultOpts; + if (!opts) { + opts = &defaultOpts; + } + return this->onGetPixels(info, pixels, rowBytes, *opts); +} + bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { SkASSERT(kIndex_8_SkColorType != info.colorType()); if (kIndex_8_SkColorType == info.colorType()) { diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp index 15977b9218..51fb281c26 100644 --- a/src/image/SkImage_Generator.cpp +++ b/src/image/SkImage_Generator.cpp @@ -60,7 +60,8 @@ bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels // Try passing the caller's buffer directly down to the generator. If this fails we // may still succeed in the general case, as the generator may prefer some other // config, which we could then convert via SkBitmap::readPixels. - if (fCache.directGeneratePixels(dstInfo, dstPixels, dstRB, srcX, srcY)) { + if (fCache.directGeneratePixels(dstInfo, dstPixels, dstRB, srcX, srcY, + SkTransferFunctionBehavior::kRespect)) { return true; } // else fall through @@ -112,7 +113,10 @@ sk_sp SkImage_Generator::onMakeColorSpace(sk_sp target) c } dst.allocPixels(dstInfo); - if (!fCache.directGeneratePixels(dstInfo, dst.getPixels(), dst.rowBytes(), 0, 0)) { + // Use kIgnore for transfer function behavior. This is used by the SkColorSpaceXformCanvas, + // which wants to pre-xform the inputs but ignore the transfer function on blends. + if (!fCache.directGeneratePixels(dstInfo, dst.getPixels(), dst.rowBytes(), 0, 0, + SkTransferFunctionBehavior::kIgnore)) { return nullptr; }