Support numerical transfer functions in readPixels()
authorMatt Sarett <msarett@google.com>
Tue, 2 May 2017 20:19:51 +0000 (16:19 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Tue, 2 May 2017 21:05:51 +0000 (21:05 +0000)
Let's do this because:
(1) We can.
(2) Android and Chrome have asked for it.
(3) It will simplify the implementation of SkImage::makeColorSpace().

Bug: skia:
Change-Id: Ia3c322b8a58c79ad67cdebe744e0623bd59dcffd
Reviewed-on: https://skia-review.googlesource.com/15148
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>

gm/readpixels.cpp
src/core/SkConvertPixels.cpp
src/core/SkImageInfoPriv.h

index f757a49..69d22bb 100644 (file)
@@ -91,10 +91,12 @@ static sk_sp<SkImage> make_picture_image() {
                                     SkColorSpace::MakeSRGB());
 }
 
-static sk_sp<SkColorSpace> make_srgb_transfer_fn(const SkColorSpacePrimaries& primaries) {
+static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
     SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
     SkAssertResult(primaries.toXYZD50(&toXYZD50));
-    return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, toXYZD50);
+    SkColorSpaceTransferFn fn;
+    fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 1.8f;
+    return SkColorSpace::MakeRGB(fn, toXYZD50);
 }
 
 static sk_sp<SkColorSpace> make_wide_gamut() {
@@ -108,7 +110,7 @@ static sk_sp<SkColorSpace> make_wide_gamut() {
     primaries.fBY = 0.0001f;
     primaries.fWX = 0.34567f;
     primaries.fWY = 0.35850f;
-    return make_srgb_transfer_fn(primaries);
+    return make_parametric_transfer_fn(primaries);
 }
 
 static sk_sp<SkColorSpace> make_small_gamut() {
@@ -121,7 +123,7 @@ static sk_sp<SkColorSpace> make_small_gamut() {
     primaries.fBY = 0.16f;
     primaries.fWX = 0.3127f;
     primaries.fWY = 0.3290f;
-    return make_srgb_transfer_fn(primaries);
+    return make_parametric_transfer_fn(primaries);
 }
 
 static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
index b919f5d..67e8a28 100644 (file)
@@ -310,6 +310,12 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
 
     if (isColorAware && srcInfo.gammaCloseToSRGB()) {
         pipeline.append_from_srgb(srcInfo.alphaType());
+    } else if (isColorAware && !srcInfo.colorSpace()->gammaIsLinear()) {
+        SkColorSpaceTransferFn fn;
+        SkAssertResult(srcInfo.colorSpace()->isNumericalTransferFn(&fn));
+        pipeline.append(SkRasterPipeline::parametric_r, &fn);
+        pipeline.append(SkRasterPipeline::parametric_g, &fn);
+        pipeline.append(SkRasterPipeline::parametric_b, &fn);
     }
 
     float matrix[12];
@@ -331,6 +337,13 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
 
     if (isColorAware && dstInfo.gammaCloseToSRGB()) {
         pipeline.append(SkRasterPipeline::to_srgb);
+    } else if (isColorAware && !dstInfo.colorSpace()->gammaIsLinear()) {
+        SkColorSpaceTransferFn fn;
+        SkAssertResult(dstInfo.colorSpace()->isNumericalTransferFn(&fn));
+        fn = fn.invert();
+        pipeline.append(SkRasterPipeline::parametric_r, &fn);
+        pipeline.append(SkRasterPipeline::parametric_g, &fn);
+        pipeline.append(SkRasterPipeline::parametric_b, &fn);
     }
 
     if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat &&
index a0c1b34..42e80ca 100644 (file)
@@ -94,7 +94,7 @@ static inline bool SkImageInfoIsValidRenderingCS(const SkImageInfo& info) {
  *      conversion is not well-defined.
  */
 static inline bool SkImageInfoValidConversion(const SkImageInfo& dst, const SkImageInfo& src) {
-    if (!SkImageInfoIsValidRenderingCS(dst) || !SkImageInfoIsValidRenderingCS(src)) {
+    if (!SkImageInfoIsValidAllowNumericalCS(dst) || !SkImageInfoIsValidAllowNumericalCS(src)) {
         return false;
     }