static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) { SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor); SkAssertResult(primaries.toXYZD50(&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); }
// Returns a colorSpace object that represents any color space information in // the encoded data. If the encoded data contains no color space, this will // return NULL. sk_sp<SkColorSpace> read_color_space(png_structp png_ptr, png_infop info_ptr) { #if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6) // First check for an ICC profile png_bytep profile; png_uint_32 length; // The below variables are unused, however, we need to pass them in anyway or // png_get_iCCP() will return nothing. // Could knowing the |name| of the profile ever be interesting? Maybe for debugging? png_charp name; // The |compression| is uninteresting since: // (1) libpng has already decompressed the profile for us. // (2) "deflate" is the only mode of decompression that libpng supports. int compression; if (PNG_INFO_iCCP == png_get_iCCP(png_ptr, info_ptr, &name, &compression, &profile, &length)) { return SkColorSpace::NewICC(profile, length); } // Second, check for sRGB. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) { // sRGB chunks also store a rendering intent: Absolute, Relative, // Perceptual, and Saturation. // FIXME (msarett): Extract this information from the sRGB chunk once // we are able to handle this information in // SkColorSpace. return SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); } // Next, check for chromaticities. png_fixed_point toXYZFixed[9]; float toXYZ[9]; png_fixed_point whitePointFixed[2]; float whitePoint[2]; png_fixed_point gamma; float gammas[3]; if (png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &toXYZFixed[0], &toXYZFixed[1], &toXYZFixed[2], &toXYZFixed[3], &toXYZFixed[4], &toXYZFixed[5], &toXYZFixed[6], &toXYZFixed[7], &toXYZFixed[8]) && png_get_cHRM_fixed(png_ptr, info_ptr, &whitePointFixed[0], &whitePointFixed[1], nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)) { for (int i = 0; i < 9; i++) { toXYZ[i] = png_fixed_point_to_float(toXYZFixed[i]); } whitePoint[0] = png_fixed_point_to_float(whitePointFixed[0]); whitePoint[1] = png_fixed_point_to_float(whitePointFixed[1]); SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor); if (!convert_to_D50(&toXYZD50, toXYZ, whitePoint)) { toXYZD50.set3x3RowMajorf(gSRGB_toXYZD50); } if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { float value = png_inverted_fixed_point_to_float(gamma); gammas[0] = value; gammas[1] = value; gammas[2] = value; return SkColorSpace_Base::NewRGB(gammas, toXYZD50); } // Default to sRGB gamma if the image has color space information, // but does not specify gamma. return SkColorSpace::NewRGB(SkColorSpace::kSRGB_GammaNamed, toXYZD50); } // Last, check for gamma. if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { // Set the gammas. float value = png_inverted_fixed_point_to_float(gamma); gammas[0] = value; gammas[1] = value; gammas[2] = value; // Since there is no cHRM, we will guess sRGB gamut. SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor); toXYZD50.set3x3RowMajorf(gSRGB_toXYZD50); return SkColorSpace_Base::NewRGB(gammas, toXYZD50); } #endif // LIBPNG >= 1.6 // Report that there is no color space information in the PNG. SkPngCodec is currently // implemented to guess sRGB in this case. return nullptr; }