aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-02-15 08:48:02 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-15 14:35:48 +0000
commit2ae3a2ec299b9b529496bbd06b8276263c8df9b0 (patch)
treeb32e8e4361468a7337cce07477759aa1d204d74d
parent3f405985be5c84a8b4b3e38f24091656aa699b5c (diff)
Suggest P3 for wide gamut images in SkAndroidCodec
This will prevent us from clipping the gamut to sRGB. BUG=skia: Change-Id: Ifc34369d96aa9dd92ae2af72aac1cfa17fdc4b94 Reviewed-on: https://skia-review.googlesource.com/8025 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Leon Scroggins <scroggo@google.com>
-rw-r--r--include/codec/SkAndroidCodec.h3
-rw-r--r--src/codec/SkAndroidCodec.cpp48
2 files changed, 48 insertions, 3 deletions
diff --git a/include/codec/SkAndroidCodec.h b/include/codec/SkAndroidCodec.h
index e30a2aa0b3..8e9ad4e2d3 100644
--- a/include/codec/SkAndroidCodec.h
+++ b/include/codec/SkAndroidCodec.h
@@ -79,9 +79,6 @@ public:
* @param outputColorType Color type that the client will decode to
*
* Returns the appropriate color space to decode to.
- *
- * For now, this just returns a default. This could be updated to take
- * requests for wide gamut modes or specific output spaces.
*/
sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType);
diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp
index 5fc7bfc585..c1f12fa591 100644
--- a/src/codec/SkAndroidCodec.cpp
+++ b/src/codec/SkAndroidCodec.cpp
@@ -17,6 +17,49 @@ static bool is_valid_sample_size(int sampleSize) {
return sampleSize > 0;
}
+/**
+ * Loads the gamut as a set of three points (triangle).
+ */
+static void load_gamut(SkPoint rgb[], const SkMatrix44& xyz) {
+ // rx = rX / (rX + rY + rZ)
+ // ry = rY / (rX + rY + rZ)
+ // gx, gy, bx, and gy are calulcated similarly.
+ float rSum = xyz.get(0, 0) + xyz.get(1, 0) + xyz.get(2, 0);
+ float gSum = xyz.get(0, 1) + xyz.get(1, 1) + xyz.get(2, 1);
+ float bSum = xyz.get(0, 2) + xyz.get(1, 2) + xyz.get(2, 2);
+ rgb[0].fX = xyz.get(0, 0) / rSum;
+ rgb[0].fY = xyz.get(1, 0) / rSum;
+ rgb[1].fX = xyz.get(0, 1) / gSum;
+ rgb[1].fY = xyz.get(1, 1) / gSum;
+ rgb[2].fX = xyz.get(0, 2) / bSum;
+ rgb[2].fY = xyz.get(1, 2) / bSum;
+}
+
+/**
+ * Calculates the area of the triangular gamut.
+ */
+static float calculate_area(SkPoint abc[]) {
+ SkPoint a = abc[0];
+ SkPoint b = abc[1];
+ SkPoint c = abc[2];
+ return 0.5f * SkTAbs(a.fX*b.fY + b.fX*c.fY - a.fX*c.fY - c.fX*b.fY - b.fX*a.fY);
+}
+
+static const float kSRGB_D50_GamutArea = 0.084f;
+
+static bool is_wide_gamut(const SkColorSpace* colorSpace) {
+ // Determine if the source image has a gamut that is wider than sRGB. If so, we
+ // will use P3 as the output color space to avoid clipping the gamut.
+ const SkMatrix44* toXYZD50 = as_CSB(colorSpace)->toXYZD50();
+ if (toXYZD50) {
+ SkPoint rgb[3];
+ load_gamut(rgb, *toXYZD50);
+ return calculate_area(rgb) > kSRGB_D50_GamutArea;
+ }
+
+ return false;
+}
+
SkAndroidCodec::SkAndroidCodec(SkCodec* codec)
: fInfo(codec->getInfo())
, fCodec(codec)
@@ -131,6 +174,11 @@ sk_sp<SkColorSpace> SkAndroidCodec::computeOutputColorSpace(SkColorType outputCo
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
case kIndex_8_SkColorType:
+ if (is_wide_gamut(fCodec->getInfo().colorSpace())) {
+ return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
+ }
+
return SkColorSpace::MakeSRGB();
case kRGBA_F16_SkColorType:
return SkColorSpace::MakeSRGBLinear();