sk_sp<SkColorSpace> SkColorSpace::NewRGB(float gammaVals[3], const SkMatrix44& toXYZD50) { sk_sp<SkGammas> gammas = nullptr; // Check if we really have sRGB or Adobe RGB if (color_space_almost_equal(2.2f, gammaVals[0]) && color_space_almost_equal(2.2f, gammaVals[1]) && color_space_almost_equal(2.2f, gammaVals[2])) { gStandardGammasOnce([] { gStandardGammas = new SkGammas(2.2f, 2.2f, 2.2f); }); gammas = sk_ref_sp(gStandardGammas); if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) { return SkColorSpace::NewNamed(kSRGB_Named); } else if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) { return SkColorSpace::NewNamed(kAdobeRGB_Named); } } if (!gammas) { gammas = sk_sp<SkGammas>(new SkGammas(gammaVals[0], gammaVals[1], gammaVals[2])); } return sk_sp<SkColorSpace>(new SkColorSpace(gammas, toXYZD50, kUnknown_Named)); }
bool valid() const { return_if_false(fSize >= kICCHeaderSize, "Size is too small"); uint8_t majorVersion = fVersion >> 24; return_if_false(majorVersion <= 4, "Unsupported version"); // These are the three basic classes of profiles that we might expect to see embedded // in images. Four additional classes exist, but they generally are used as a convenient // way for CMMs to store calculated transforms. const uint32_t kDisplay_Profile = SkSetFourByteTag('m', 'n', 't', 'r'); const uint32_t kInput_Profile = SkSetFourByteTag('s', 'c', 'n', 'r'); const uint32_t kOutput_Profile = SkSetFourByteTag('p', 'r', 't', 'r'); return_if_false(fProfileClass == kDisplay_Profile || fProfileClass == kInput_Profile || fProfileClass == kOutput_Profile, "Unsupported profile"); // TODO (msarett): // All the profiles we've tested so far use RGB as the input color space. return_if_false(fInputColorSpace == kRGB_ColorSpace, "Unsupported color space"); // TODO (msarett): // All the profiles we've tested so far use XYZ as the profile connection space. const uint32_t kXYZ_PCSSpace = SkSetFourByteTag('X', 'Y', 'Z', ' '); return_if_false(fPCS == kXYZ_PCSSpace, "Unsupported PCS space"); return_if_false(fSignature == SkSetFourByteTag('a', 'c', 's', 'p'), "Bad signature"); // TODO (msarett): // Should we treat different rendering intents differently? // Valid rendering intents include kPerceptual (0), kRelative (1), // kSaturation (2), and kAbsolute (3). return_if_false(fRenderingIntent <= 3, "Bad rendering intent"); return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0]), 0.96420f) && color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1]), 1.00000f) && color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2]), 0.82491f), "Illuminant must be D50"); return_if_false(fTagCount <= 100, "Too many tags"); return true; }
static bool xyz_almost_equal(const skcms_Matrix3x3& mA, const skcms_Matrix3x3& mB) { for (int r = 0; r < 3; ++r) { for (int c = 0; c < 3; ++c) { if (!color_space_almost_equal(mA.vals[r][c], mB.vals[r][c])) { return false; } } } return true; }
/** * Checks if our toXYZ matrix is a close match to a known color gamut. * * @param toXYZD50 transformation matrix deduced from profile data * @param standard 3x3 canonical transformation matrix */ static bool xyz_almost_equal(const SkMatrix44& toXYZD50, const float* standard) { return color_space_almost_equal(toXYZD50.getFloat(0, 0), standard[0]) && color_space_almost_equal(toXYZD50.getFloat(0, 1), standard[1]) && color_space_almost_equal(toXYZD50.getFloat(0, 2), standard[2]) && color_space_almost_equal(toXYZD50.getFloat(1, 0), standard[3]) && color_space_almost_equal(toXYZD50.getFloat(1, 1), standard[4]) && color_space_almost_equal(toXYZD50.getFloat(1, 2), standard[5]) && color_space_almost_equal(toXYZD50.getFloat(2, 0), standard[6]) && color_space_almost_equal(toXYZD50.getFloat(2, 1), standard[7]) && color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); }