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>
This commit is contained in:
parent
3f405985be
commit
2ae3a2ec29
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user