aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-04-03 11:42:52 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-04-03 16:21:31 +0000
commit5b1dba845169c9459fb79070940098ccb59535a8 (patch)
treea1ae76ed5301088cb2a9d5d946725dbdd3872c1c /src
parent887cdf112809727c51890ba8b98b3ddce22249f0 (diff)
Support parametric transfer functions in SkImage_Raster::onMakeColorSpace()
BUG=skia:6456 Change-Id: Ib94bba9db669562a9b2b64fff56ebe40a2bc0096 Reviewed-on: https://skia-review.googlesource.com/11122 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src')
-rw-r--r--src/image/SkImage_Raster.cpp48
1 files changed, 45 insertions, 3 deletions
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 547bdbf5ad..e6905aa5ce 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -9,12 +9,15 @@
#include "SkBitmap.h"
#include "SkBitmapProcShader.h"
#include "SkCanvas.h"
+#include "SkColorSpaceXform_Base.h"
+#include "SkColorSpaceXformPriv.h"
#include "SkColorTable.h"
#include "SkData.h"
#include "SkImagePriv.h"
#include "SkPixelRef.h"
#include "SkSurface.h"
#include "SkTLazy.h"
+#include "SkUnPreMultiplyPriv.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
@@ -350,6 +353,47 @@ bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) c
return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
}
+///////////////////////////////////////////////////////////////////////////////
+
+static inline void do_color_xform_non_linear_blending(SkBitmap* dst, const SkPixmap& src) {
+ SkDEBUGCODE(SkColorSpaceTransferFn fn;);
+ SkASSERT(dst->colorSpace()->isNumericalTransferFn(&fn) &&
+ src.colorSpace()->isNumericalTransferFn(&fn));
+
+ void* dstPixels = dst->getPixels();
+ const void* srcPixels = src.addr();
+ size_t dstRowBytes = dst->rowBytes();
+ size_t srcRowBytes = src.rowBytes();
+ if (kN32_SkColorType != src.colorType()) {
+ SkAssertResult(src.readPixels(src.info().makeColorType(kN32_SkColorType), dstPixels,
+ dstRowBytes, 0, 0));
+
+ srcPixels = dstPixels;
+ srcRowBytes = dstRowBytes;
+ }
+
+ std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform_Base::New(
+ src.colorSpace(), dst->colorSpace(), SkTransferFunctionBehavior::kIgnore);
+
+ void* dstRow = dstPixels;
+ const void* srcRow = srcPixels;
+ for (int y = 0; y < dst->height(); y++) {
+ // This function assumes non-linear blending. Which means that we must start by
+ // unpremultiplying in the gamma encoded space.
+ const void* tmpRow = srcRow;
+ if (kPremul_SkAlphaType == src.alphaType()) {
+ SkUnpremultiplyRow<false>((uint32_t*) dstRow, (const uint32_t*) srcRow, dst->width());
+ tmpRow = dstRow;
+ }
+
+ SkColorSpaceXform::ColorFormat fmt = select_xform_format(kN32_SkColorType);
+ SkAssertResult(xform->apply(fmt, dstRow, fmt, tmpRow, dst->width(), dst->alphaType()));
+
+ dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
+ srcRow = SkTAddOffset<const void>(srcRow, srcRowBytes);
+ }
+}
+
sk_sp<SkImage> SkImage_Raster::onMakeColorSpace(sk_sp<SkColorSpace> target) const {
// Force the color type of the new image to be kN32_SkColorType.
// (1) This means we lose precision on F16 images. This is necessary while this function is
@@ -374,9 +418,7 @@ sk_sp<SkImage> SkImage_Raster::onMakeColorSpace(sk_sp<SkColorSpace> target) cons
src.setColorSpace(SkColorSpace::MakeSRGB());
}
- // 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.
- SkAssertResult(dst.writePixels(src, 0, 0, SkTransferFunctionBehavior::kIgnore));
+ do_color_xform_non_linear_blending(&dst, src);
dst.setImmutable();
return SkImage::MakeFromBitmap(dst);
}