diff options
author | Matt Sarett <msarett@google.com> | 2017-06-06 10:11:34 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-06 14:34:03 +0000 |
commit | 3928ff8e0b617c3a00eee1963bc31ce5470fba6d (patch) | |
tree | 98bbe9e51b3316c175a8b1ffe1063877ca84eb55 /src | |
parent | 1608a1dd17187aeeada376e710ecfafb1e229af2 (diff) |
Create an SkColorSpaceXform image generator
This should be immediately useful in the Skia-Android
rendering pipeline.
Possible future uses include creating a "renderable"
SkImage from a bitmap with a funny color space.
Inspired by:
https://skia-review.googlesource.com/c/13981/
Bug: b/62347704
Change-Id: I388c7af1fc43834b8ad22022d0caf3ac90b734c8
Reviewed-on: https://skia-review.googlesource.com/18598
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBitmap.cpp | 4 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformImageGenerator.cpp | 96 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformImageGenerator.h | 40 | ||||
-rw-r--r-- | src/core/SkPixmap.cpp | 6 |
4 files changed, 141 insertions, 5 deletions
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 72cac7cc9c..e88fa5ec57 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -512,12 +512,12 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { /////////////////////////////////////////////////////////////////////////////// bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB, - int x, int y) const { + int x, int y, SkTransferFunctionBehavior behavior) const { SkPixmap src; if (!this->peekPixels(&src)) { return false; } - return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y); + return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y, behavior); } bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const { diff --git a/src/core/SkColorSpaceXformImageGenerator.cpp b/src/core/SkColorSpaceXformImageGenerator.cpp new file mode 100644 index 0000000000..d9bec78035 --- /dev/null +++ b/src/core/SkColorSpaceXformImageGenerator.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkColorSpaceXformImageGenerator.h" + +std::unique_ptr<SkImageGenerator> SkColorSpaceXformImageGenerator::Make( + const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode mode) { + if (!dst) { + return nullptr; + } + + const SkBitmap* srcPtr = &src; + SkBitmap copy; + if (kAlways_SkCopyPixelsMode == mode || + (kNever_SkCopyPixelsMode != mode && !src.isImmutable())) { + if (!copy.tryAllocPixels(src.info())) { + return nullptr; + } + + SkAssertResult(src.readPixels(copy.info(), copy.getPixels(), copy.rowBytes(), 0, 0)); + copy.setImmutable(); + srcPtr = © + } + + + return std::unique_ptr<SkImageGenerator>( + new SkColorSpaceXformImageGenerator(*srcPtr, std::move(dst))); +} + +SkColorSpaceXformImageGenerator::SkColorSpaceXformImageGenerator(const SkBitmap& src, + sk_sp<SkColorSpace> dst) + : INHERITED(src.info().makeColorSpace(dst), kNeedNewImageUniqueID) + , fSrc(src) + , fDst(dst) +{} + +bool SkColorSpaceXformImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, + size_t rowBytes, const Options& opts) { + SkImageInfo dstInfo = info; + if (!info.colorSpace()) { + dstInfo = dstInfo.makeColorSpace(fDst); + } + return fSrc.readPixels(dstInfo, pixels, rowBytes, 0, 0, opts.fBehavior); +} + +#if SK_SUPPORT_GPU + +#include "GrClip.h" +#include "GrContext.h" +#include "GrPaint.h" +#include "GrRenderTargetContext.h" +#include "GrTextureProxy.h" +#include "SkGr.h" +#include "effects/GrNonlinearColorSpaceXformEffect.h" + +sk_sp<GrTextureProxy> SkColorSpaceXformImageGenerator::onGenerateTexture(GrContext* ctx, + const SkImageInfo& info, + const SkIPoint& origin) { + // FIXME: + // This always operates as if SkTranferFunctionBehavior is kIgnore. Should we add + // options so that caller can also request kRespect? + + SkASSERT(ctx); + + sk_sp<GrTextureProxy> proxy = + GrUploadBitmapToTextureProxy(ctx->resourceProvider(), fSrc, nullptr); + + sk_sp<SkColorSpace> srcSpace = + fSrc.colorSpace() ? sk_ref_sp(fSrc.colorSpace()) : SkColorSpace::MakeSRGB(); + auto xform = GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), fDst.get()); + if (!xform) { + return nullptr; + } + + sk_sp<GrRenderTargetContext> renderTargetContext = ctx->makeDeferredRenderTargetContext( + SkBackingFit::kExact, fSrc.width(), fSrc.height(), kRGBA_8888_GrPixelConfig, nullptr); + if (!renderTargetContext) { + return nullptr; + } + + GrPaint paint; + paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.addColorTextureProcessor(ctx->resourceProvider(), proxy, nullptr, + SkMatrix::MakeTrans(origin.fX, origin.fY)); + paint.addColorFragmentProcessor(std::move(xform)); + + const SkRect rect = SkRect::MakeWH(info.width(), info.height()); + renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect); + return sk_ref_sp(renderTargetContext->asTextureProxy()); +} + +#endif diff --git a/src/core/SkColorSpaceXformImageGenerator.h b/src/core/SkColorSpaceXformImageGenerator.h new file mode 100644 index 0000000000..29bf85bff9 --- /dev/null +++ b/src/core/SkColorSpaceXformImageGenerator.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkColorSpaceXformImageGenerator_DEFINED +#define SkColorSpaceXformImageGenerator_DEFINED + +#include "SkImageGenerator.h" +#include "SkImagePriv.h" + +class SkColorSpaceXformImageGenerator : public SkImageGenerator { +public: + + static std::unique_ptr<SkImageGenerator> Make( + const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode); + +protected: + bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, + const Options& opts) override; + +#if SK_SUPPORT_GPU + sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, + const SkIPoint&) override; +#endif + +private: + SkBitmap fSrc; + sk_sp<SkColorSpace> fDst; + + SkColorSpaceXformImageGenerator(const SkBitmap& src, sk_sp<SkColorSpace> dst); + + friend class SkImageGenerator; + + typedef SkImageGenerator INHERITED; +}; + +#endif // SkColorSpaceXformImageGenerator_DEFINED diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index 02090b77c6..6425b29f92 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -74,8 +74,8 @@ bool SkPixmap::extractSubset(SkPixmap* result, const SkIRect& subset) const { return true; } -bool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, int x, int y) -const { +bool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, int x, int y, + SkTransferFunctionBehavior behavior) const { if (!SkImageInfoValidConversion(dstInfo, fInfo)) { return false; } @@ -88,7 +88,7 @@ const { const void* srcPixels = this->addr(rec.fX, rec.fY); const SkImageInfo srcInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height()); SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels, this->rowBytes(), - this->ctable(), SkTransferFunctionBehavior::kRespect); + this->ctable(), behavior); return true; } |