Add SkColorSpaceTransferFn to SkColorSpace
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3178 Change-Id: I354342d4469cee0e25a7b0d189e925e431da623c Reviewed-on: https://skia-review.googlesource.com/3178 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Matt Sarett <msarett@google.com>
This commit is contained in:
parent
3eb71216d2
commit
df44fc5f2b
@ -29,6 +29,27 @@ struct SK_API SkColorSpacePrimaries {
|
||||
bool toXYZD50(SkMatrix44* toXYZD50) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains the coefficients for a common transfer function equation, specified as
|
||||
* a transformation from a curved space to linear.
|
||||
*
|
||||
* LinearVal = E*InputVal + F , for 0.0f <= InputVal < D
|
||||
* LinearVal = (A*InputVal + B)^G + C, for D <= InputVal <= 1.0f
|
||||
*
|
||||
* Function is undefined if InputVal is not in [ 0.0f, 1.0f ].
|
||||
* Resulting LinearVals must be in [ 0.0f, 1.0f ].
|
||||
* Function must be positive and increasing.
|
||||
*/
|
||||
struct SK_API SkColorSpaceTransferFn {
|
||||
float fG;
|
||||
float fA;
|
||||
float fB;
|
||||
float fC;
|
||||
float fD;
|
||||
float fE;
|
||||
float fF;
|
||||
};
|
||||
|
||||
class SK_API SkColorSpace : public SkRefCnt {
|
||||
public:
|
||||
|
||||
@ -68,10 +89,12 @@ public:
|
||||
/**
|
||||
* Create an SkColorSpace from a transfer function and a color gamut.
|
||||
*
|
||||
* Transfer function is specified as linear or sRGB.
|
||||
* Transfer function can be specified as a render target or as the coefficients to an equation.
|
||||
* Gamut is specified using the matrix transformation to XYZ D50.
|
||||
*/
|
||||
static sk_sp<SkColorSpace> NewRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
|
||||
static sk_sp<SkColorSpace> NewRGB(const SkColorSpaceTransferFn& coeffs,
|
||||
const SkMatrix44& toXYZD50);
|
||||
|
||||
/**
|
||||
* Create a common, named SkColorSpace.
|
||||
|
@ -11,10 +11,6 @@
|
||||
#include "SkOnce.h"
|
||||
#include "SkPoint3.h"
|
||||
|
||||
static inline bool is_zero_to_one(float v) {
|
||||
return (0.0f <= v) && (v <= 1.0f);
|
||||
}
|
||||
|
||||
bool SkColorSpacePrimaries::toXYZD50(SkMatrix44* toXYZ_D50) const {
|
||||
if (!is_zero_to_one(fRX) || !is_zero_to_one(fRY) ||
|
||||
!is_zero_to_one(fGX) || !is_zero_to_one(fGY) ||
|
||||
@ -211,6 +207,37 @@ sk_sp<SkColorSpace> SkColorSpace::NewRGB(RenderTargetGamma gamma, const SkMatrix
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkColorSpaceTransferFn& coeffs,
|
||||
const SkMatrix44& toXYZD50) {
|
||||
if (!is_valid_transfer_fn(coeffs)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (is_almost_srgb(coeffs)) {
|
||||
return SkColorSpace::NewRGB(kSRGB_RenderTargetGamma, toXYZD50);
|
||||
}
|
||||
|
||||
if (is_almost_2dot2(coeffs)) {
|
||||
return SkColorSpace_Base::NewRGB(k2Dot2Curve_SkGammaNamed, toXYZD50);
|
||||
}
|
||||
|
||||
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
|
||||
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas());
|
||||
SkColorSpaceTransferFn* fn = SkTAddOffset<SkColorSpaceTransferFn>(memory, sizeof(SkGammas));
|
||||
*fn = coeffs;
|
||||
gammas->fRedType = SkGammas::Type::kParam_Type;
|
||||
gammas->fGreenType = SkGammas::Type::kParam_Type;
|
||||
gammas->fBlueType = SkGammas::Type::kParam_Type;
|
||||
|
||||
SkGammas::Data data;
|
||||
data.fParamOffset = 0;
|
||||
gammas->fRedData = data;
|
||||
gammas->fGreenData = data;
|
||||
gammas->fBlueData = data;
|
||||
return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, kNonStandard_SkGammaNamed,
|
||||
std::move(gammas), toXYZD50, nullptr));
|
||||
}
|
||||
|
||||
static SkColorSpace* gAdobeRGB;
|
||||
static SkColorSpace* gSRGB;
|
||||
static SkColorSpace* gSRGBLinear;
|
||||
@ -299,9 +326,13 @@ enum Version {
|
||||
};
|
||||
|
||||
struct ColorSpaceHeader {
|
||||
/**
|
||||
* It is only valid to set zero or one flags.
|
||||
* Setting multiple flags is invalid.
|
||||
*/
|
||||
|
||||
/**
|
||||
* If kMatrix_Flag is set, we will write 12 floats after the header.
|
||||
* Should not be set at the same time as the kICC_Flag or kFloatGamma_Flag.
|
||||
*/
|
||||
static constexpr uint8_t kMatrix_Flag = 1 << 0;
|
||||
|
||||
@ -309,7 +340,6 @@ struct ColorSpaceHeader {
|
||||
* If kICC_Flag is set, we will write an ICC profile after the header.
|
||||
* The ICC profile will be written as a uint32 size, followed immediately
|
||||
* by the data (padded to 4 bytes).
|
||||
* Should not be set at the same time as the kMatrix_Flag or kFloatGamma_Flag.
|
||||
*/
|
||||
static constexpr uint8_t kICC_Flag = 1 << 1;
|
||||
|
||||
@ -317,10 +347,16 @@ struct ColorSpaceHeader {
|
||||
* If kFloatGamma_Flag is set, we will write 15 floats after the header.
|
||||
* The first three are the gamma values, and the next twelve are the
|
||||
* matrix.
|
||||
* Should not be set at the same time as the kICC_Flag or kMatrix_Flag.
|
||||
*/
|
||||
static constexpr uint8_t kFloatGamma_Flag = 1 << 2;
|
||||
|
||||
/**
|
||||
* If kTransferFn_Flag is set, we will write 19 floats after the header.
|
||||
* The first seven represent the transfer fn, and the next twelve are the
|
||||
* matrix.
|
||||
*/
|
||||
static constexpr uint8_t kTransferFn_Flag = 1 << 3;
|
||||
|
||||
static ColorSpaceHeader Pack(Version version, uint8_t named, uint8_t gammaNamed, uint8_t flags)
|
||||
{
|
||||
ColorSpaceHeader header;
|
||||
@ -334,7 +370,7 @@ struct ColorSpaceHeader {
|
||||
SkASSERT(gammaNamed <= kNonStandard_SkGammaNamed);
|
||||
header.fGammaNamed = (uint8_t) gammaNamed;
|
||||
|
||||
SkASSERT(flags <= kFloatGamma_Flag);
|
||||
SkASSERT(flags <= kTransferFn_Flag);
|
||||
header.fFlags = flags;
|
||||
return header;
|
||||
}
|
||||
@ -388,26 +424,51 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
|
||||
return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
|
||||
}
|
||||
default:
|
||||
// Otherwise, write the gamma values and the matrix.
|
||||
if (memory) {
|
||||
*((ColorSpaceHeader*) memory) =
|
||||
ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
||||
ColorSpaceHeader::kFloatGamma_Flag);
|
||||
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
||||
const SkGammas* gammas = as_CSB(this)->gammas();
|
||||
SkASSERT(gammas);
|
||||
if (gammas->isValue(0) && gammas->isValue(1) && gammas->isValue(2)) {
|
||||
if (memory) {
|
||||
*((ColorSpaceHeader*) memory) =
|
||||
ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
||||
ColorSpaceHeader::kFloatGamma_Flag);
|
||||
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
||||
|
||||
const SkGammas* gammas = as_CSB(this)->gammas();
|
||||
SkASSERT(gammas);
|
||||
SkASSERT(SkGammas::Type::kValue_Type == gammas->fRedType &&
|
||||
SkGammas::Type::kValue_Type == gammas->fGreenType &&
|
||||
SkGammas::Type::kValue_Type == gammas->fBlueType);
|
||||
*(((float*) memory) + 0) = gammas->fRedData.fValue;
|
||||
*(((float*) memory) + 1) = gammas->fGreenData.fValue;
|
||||
*(((float*) memory) + 2) = gammas->fBlueData.fValue;
|
||||
memory = SkTAddOffset<void>(memory, 3 * sizeof(float));
|
||||
*(((float*) memory) + 0) = gammas->fRedData.fValue;
|
||||
*(((float*) memory) + 1) = gammas->fGreenData.fValue;
|
||||
*(((float*) memory) + 2) = gammas->fBlueData.fValue;
|
||||
memory = SkTAddOffset<void>(memory, 3 * sizeof(float));
|
||||
|
||||
as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
||||
as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
||||
}
|
||||
|
||||
return sizeof(ColorSpaceHeader) + 15 * sizeof(float);
|
||||
} else {
|
||||
SkASSERT(gammas->isParametric(0));
|
||||
SkASSERT(gammas->isParametric(1));
|
||||
SkASSERT(gammas->isParametric(2));
|
||||
SkASSERT(gammas->data(0) == gammas->data(1));
|
||||
SkASSERT(gammas->data(0) == gammas->data(2));
|
||||
|
||||
if (memory) {
|
||||
*((ColorSpaceHeader*) memory) =
|
||||
ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
||||
ColorSpaceHeader::kTransferFn_Flag);
|
||||
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
||||
|
||||
*(((float*) memory) + 0) = gammas->params(0).fA;
|
||||
*(((float*) memory) + 1) = gammas->params(0).fB;
|
||||
*(((float*) memory) + 2) = gammas->params(0).fC;
|
||||
*(((float*) memory) + 3) = gammas->params(0).fD;
|
||||
*(((float*) memory) + 4) = gammas->params(0).fE;
|
||||
*(((float*) memory) + 5) = gammas->params(0).fF;
|
||||
*(((float*) memory) + 6) = gammas->params(0).fG;
|
||||
memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
|
||||
|
||||
as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
||||
}
|
||||
|
||||
return sizeof(ColorSpaceHeader) + 19 * sizeof(float);
|
||||
}
|
||||
return sizeof(ColorSpaceHeader) + 15 * sizeof(float);
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,6 +562,25 @@ sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) {
|
||||
toXYZ.set3x4RowMajorf((const float*) data);
|
||||
return SkColorSpace_Base::NewRGB(gammas, toXYZ);
|
||||
}
|
||||
case ColorSpaceHeader::kTransferFn_Flag: {
|
||||
if (length < 19 * sizeof(float)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkColorSpaceTransferFn transferFn;
|
||||
transferFn.fA = *(((const float*) data) + 0);
|
||||
transferFn.fB = *(((const float*) data) + 1);
|
||||
transferFn.fC = *(((const float*) data) + 2);
|
||||
transferFn.fD = *(((const float*) data) + 3);
|
||||
transferFn.fE = *(((const float*) data) + 4);
|
||||
transferFn.fF = *(((const float*) data) + 5);
|
||||
transferFn.fG = *(((const float*) data) + 6);
|
||||
data = SkTAddOffset<const void>(data, 7 * sizeof(float));
|
||||
|
||||
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
|
||||
toXYZ.set3x4RowMajorf((const float*) data);
|
||||
return SkColorSpace::NewRGB(transferFn, toXYZ);
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -7,6 +7,80 @@
|
||||
|
||||
#define SkColorSpacePrintf(...)
|
||||
|
||||
inline bool color_space_almost_equal(float a, float b) {
|
||||
static inline bool color_space_almost_equal(float a, float b) {
|
||||
return SkTAbs(a - b) < 0.01f;
|
||||
}
|
||||
|
||||
static inline bool is_zero_to_one(float v) {
|
||||
return (0.0f <= v) && (v <= 1.0f);
|
||||
}
|
||||
|
||||
static inline bool is_valid_transfer_fn(const SkColorSpaceTransferFn& coeffs) {
|
||||
if (SkScalarIsNaN(coeffs.fA) || SkScalarIsNaN(coeffs.fB) ||
|
||||
SkScalarIsNaN(coeffs.fC) || SkScalarIsNaN(coeffs.fD) ||
|
||||
SkScalarIsNaN(coeffs.fE) || SkScalarIsNaN(coeffs.fF) ||
|
||||
SkScalarIsNaN(coeffs.fG))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_zero_to_one(coeffs.fD)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (coeffs.fD == 0.0f) {
|
||||
// Y = (aX + b)^g + c for always
|
||||
if (0.0f == coeffs.fA || 0.0f == coeffs.fG) {
|
||||
SkColorSpacePrintf("A or G is zero, constant transfer function "
|
||||
"is nonsense");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (coeffs.fD == 1.0f) {
|
||||
// Y = eX + f for always
|
||||
if (0.0f == coeffs.fE) {
|
||||
SkColorSpacePrintf("E is zero, constant transfer function is "
|
||||
"nonsense");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((0.0f == coeffs.fA || 0.0f == coeffs.fG) && 0.0f == coeffs.fE) {
|
||||
SkColorSpacePrintf("A or G, and E are zero, constant transfer function "
|
||||
"is nonsense");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (coeffs.fE < 0.0f) {
|
||||
SkColorSpacePrintf("Transfer function must be increasing");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (coeffs.fA < 0.0f || coeffs.fG < 0.0f) {
|
||||
SkColorSpacePrintf("Transfer function must be positive or increasing");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool is_almost_srgb(const SkColorSpaceTransferFn& coeffs) {
|
||||
return color_space_almost_equal(0.9479f, coeffs.fA) &&
|
||||
color_space_almost_equal(0.0521f, coeffs.fB) &&
|
||||
color_space_almost_equal(0.0000f, coeffs.fC) &&
|
||||
color_space_almost_equal(0.0405f, coeffs.fD) &&
|
||||
color_space_almost_equal(0.0774f, coeffs.fE) &&
|
||||
color_space_almost_equal(0.0000f, coeffs.fF) &&
|
||||
color_space_almost_equal(2.4000f, coeffs.fG);
|
||||
}
|
||||
|
||||
static inline bool is_almost_2dot2(const SkColorSpaceTransferFn& coeffs) {
|
||||
return color_space_almost_equal(1.0f, coeffs.fA) &&
|
||||
color_space_almost_equal(0.0f, coeffs.fB) &&
|
||||
color_space_almost_equal(0.0f, coeffs.fC) &&
|
||||
color_space_almost_equal(0.0f, coeffs.fD) &&
|
||||
color_space_almost_equal(0.0f, coeffs.fE) &&
|
||||
color_space_almost_equal(0.0f, coeffs.fF) &&
|
||||
color_space_almost_equal(2.2f, coeffs.fG);
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage,
|
||||
outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
|
||||
} else {
|
||||
SkASSERT(gammas->isParametric(i));
|
||||
const SkGammas::Params& params = gammas->params(i);
|
||||
const SkColorSpaceTransferFn& params = gammas->params(i);
|
||||
(*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG,
|
||||
params.fA, params.fB, params.fC, params.fD, params.fE,
|
||||
params.fF);
|
||||
|
@ -42,19 +42,6 @@ struct SkGammas : SkRefCnt {
|
||||
}
|
||||
};
|
||||
|
||||
// Contains the parameters for a parametric curve.
|
||||
struct Params {
|
||||
// Y = (aX + b)^g + c for X >= d
|
||||
// Y = eX + f otherwise
|
||||
float fG;
|
||||
float fA;
|
||||
float fB;
|
||||
float fC;
|
||||
float fD;
|
||||
float fE;
|
||||
float fF;
|
||||
};
|
||||
|
||||
// Contains the actual gamma curve information. Should be interpreted
|
||||
// based on the type of the gamma curve.
|
||||
union Data {
|
||||
@ -72,8 +59,9 @@ struct SkGammas : SkRefCnt {
|
||||
Table fTable;
|
||||
size_t fParamOffset;
|
||||
|
||||
const Params& params(const SkGammas* base) const {
|
||||
return *SkTAddOffset<const Params>(base, sizeof(SkGammas) + fParamOffset);
|
||||
const SkColorSpaceTransferFn& params(const SkGammas* base) const {
|
||||
return *SkTAddOffset<const SkColorSpaceTransferFn>(
|
||||
base, sizeof(SkGammas) + fParamOffset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -112,7 +100,7 @@ struct SkGammas : SkRefCnt {
|
||||
return this->data(i).fTable.table(this);
|
||||
}
|
||||
|
||||
const Params& params(int i) const {
|
||||
const SkColorSpaceTransferFn& params(int i) const {
|
||||
SkASSERT(isParametric(i));
|
||||
return this->data(i).params(this);
|
||||
}
|
||||
|
@ -274,8 +274,8 @@ static float read_big_endian_16_dot_16(const uint8_t buf[4]) {
|
||||
*
|
||||
* @return kNone_Type on failure, otherwise the type of the gamma tag.
|
||||
*/
|
||||
static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* outParams,
|
||||
size_t* outTagBytes, const uint8_t* src, size_t len) {
|
||||
static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkColorSpaceTransferFn* outParams,
|
||||
size_t* outTagBytes, const uint8_t* src, size_t len) {
|
||||
if (len < 12) {
|
||||
SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
|
||||
return SkGammas::Type::kNone_Type;
|
||||
@ -478,49 +478,6 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out
|
||||
return SkGammas::Type::kNone_Type;
|
||||
}
|
||||
|
||||
// Recognize and simplify a very common parametric representation of sRGB gamma.
|
||||
if (color_space_almost_equal(0.9479f, a) &&
|
||||
color_space_almost_equal(0.0521f, b) &&
|
||||
color_space_almost_equal(0.0000f, c) &&
|
||||
color_space_almost_equal(0.0405f, d) &&
|
||||
color_space_almost_equal(0.0774f, e) &&
|
||||
color_space_almost_equal(0.0000f, f) &&
|
||||
color_space_almost_equal(2.4000f, g)) {
|
||||
outData->fNamed = kSRGB_SkGammaNamed;
|
||||
return SkGammas::Type::kNamed_Type;
|
||||
}
|
||||
|
||||
// Fail on invalid gammas.
|
||||
if (SkScalarIsNaN(d)) {
|
||||
return SkGammas::Type::kNone_Type;
|
||||
}
|
||||
|
||||
if (d <= 0.0f) {
|
||||
// Y = (aX + b)^g + c for always
|
||||
if (0.0f == a || 0.0f == g) {
|
||||
SkColorSpacePrintf("A or G is zero, constant gamma function "
|
||||
"is nonsense");
|
||||
return SkGammas::Type::kNone_Type;
|
||||
}
|
||||
}
|
||||
|
||||
if (d >= 1.0f) {
|
||||
// Y = eX + f for always
|
||||
if (0.0f == e) {
|
||||
SkColorSpacePrintf("E is zero, constant gamma function is "
|
||||
"nonsense");
|
||||
return SkGammas::Type::kNone_Type;
|
||||
}
|
||||
}
|
||||
|
||||
if ((0.0f == a || 0.0f == g) && 0.0f == e) {
|
||||
SkColorSpacePrintf("A or G, and E are zero, constant gamma function "
|
||||
"is nonsense");
|
||||
return SkGammas::Type::kNone_Type;
|
||||
}
|
||||
|
||||
*outTagBytes = tagBytes;
|
||||
|
||||
outParams->fG = g;
|
||||
outParams->fA = a;
|
||||
outParams->fB = b;
|
||||
@ -528,6 +485,22 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out
|
||||
outParams->fD = d;
|
||||
outParams->fE = e;
|
||||
outParams->fF = f;
|
||||
|
||||
if (!is_valid_transfer_fn(*outParams)) {
|
||||
return SkGammas::Type::kNone_Type;
|
||||
}
|
||||
|
||||
if (is_almost_srgb(*outParams)) {
|
||||
outData->fNamed = kSRGB_SkGammaNamed;
|
||||
return SkGammas::Type::kNamed_Type;
|
||||
}
|
||||
|
||||
if (is_almost_2dot2(*outParams)) {
|
||||
outData->fNamed = k2Dot2Curve_SkGammaNamed;
|
||||
return SkGammas::Type::kNamed_Type;
|
||||
}
|
||||
|
||||
*outTagBytes = tagBytes;
|
||||
return SkGammas::Type::kParam_Type;
|
||||
}
|
||||
default:
|
||||
@ -547,7 +520,7 @@ static size_t gamma_alloc_size(SkGammas::Type type, const SkGammas::Data& data)
|
||||
case SkGammas::Type::kTable_Type:
|
||||
return sizeof(float) * data.fTable.fSize;
|
||||
case SkGammas::Type::kParam_Type:
|
||||
return sizeof(SkGammas::Params);
|
||||
return sizeof(SkColorSpaceTransferFn);
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return 0;
|
||||
@ -584,7 +557,7 @@ static void handle_invalid_gamma(SkGammas::Type* type, SkGammas::Data* data) {
|
||||
* @return Additional bytes of memory that are being used by this gamma curve.
|
||||
*/
|
||||
static size_t load_gammas(void* memory, size_t offset, SkGammas::Type type,
|
||||
SkGammas::Data* data, const SkGammas::Params& params,
|
||||
SkGammas::Data* data, const SkColorSpaceTransferFn& params,
|
||||
const uint8_t* src) {
|
||||
void* storage = SkTAddOffset<void>(memory, offset + sizeof(SkGammas));
|
||||
|
||||
@ -606,8 +579,8 @@ static size_t load_gammas(void* memory, size_t offset, SkGammas::Type type,
|
||||
}
|
||||
case SkGammas::Type::kParam_Type:
|
||||
data->fTable.fOffset = offset;
|
||||
memcpy(storage, ¶ms, sizeof(SkGammas::Params));
|
||||
return sizeof(SkGammas::Params);
|
||||
memcpy(storage, ¶ms, sizeof(SkColorSpaceTransferFn));
|
||||
return sizeof(SkColorSpaceTransferFn);
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return 0;
|
||||
@ -785,7 +758,7 @@ static bool load_a2b0(sk_sp<SkColorLookUpTable>* colorLUT, SkGammaNamed* gammaNa
|
||||
size_t tagLen = len - offsetToMCurves;
|
||||
|
||||
SkGammas::Data rData;
|
||||
SkGammas::Params rParams;
|
||||
SkColorSpaceTransferFn rParams;
|
||||
|
||||
// On an invalid first gamma, tagBytes remains set as zero. This causes the two
|
||||
// subsequent to be treated as identical (which is what we want).
|
||||
@ -820,17 +793,17 @@ static bool load_a2b0(sk_sp<SkColorLookUpTable>* colorLUT, SkGammaNamed* gammaNa
|
||||
const uint8_t* gTagPtr = rTagPtr + alignedTagBytes;
|
||||
tagLen = tagLen > alignedTagBytes ? tagLen - alignedTagBytes : 0;
|
||||
SkGammas::Data gData;
|
||||
SkGammas::Params gParams;
|
||||
SkColorSpaceTransferFn gParams;
|
||||
tagBytes = 0;
|
||||
SkGammas::Type gType = parse_gamma(&gData, &gParams, &tagBytes, gTagPtr,
|
||||
tagLen);
|
||||
tagLen);
|
||||
handle_invalid_gamma(&gType, &gData);
|
||||
|
||||
alignedTagBytes = SkAlign4(tagBytes);
|
||||
const uint8_t* bTagPtr = gTagPtr + alignedTagBytes;
|
||||
tagLen = tagLen > alignedTagBytes ? tagLen - alignedTagBytes : 0;
|
||||
SkGammas::Data bData;
|
||||
SkGammas::Params bParams;
|
||||
SkColorSpaceTransferFn bParams;
|
||||
SkGammas::Type bType = parse_gamma(&bData, &bParams, &tagBytes, bTagPtr,
|
||||
tagLen);
|
||||
handle_invalid_gamma(&bType, &bData);
|
||||
@ -993,7 +966,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
|
||||
if (r && g && b) {
|
||||
if (tag_equals(r, g, base) && tag_equals(g, b, base)) {
|
||||
SkGammas::Data data;
|
||||
SkGammas::Params params;
|
||||
SkColorSpaceTransferFn params;
|
||||
SkGammas::Type type =
|
||||
parse_gamma(&data, ¶ms, &tagBytes, r->addr(base), r->fLength);
|
||||
handle_invalid_gamma(&type, &data);
|
||||
@ -1019,19 +992,19 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
|
||||
}
|
||||
} else {
|
||||
SkGammas::Data rData;
|
||||
SkGammas::Params rParams;
|
||||
SkColorSpaceTransferFn rParams;
|
||||
SkGammas::Type rType =
|
||||
parse_gamma(&rData, &rParams, &tagBytes, r->addr(base), r->fLength);
|
||||
handle_invalid_gamma(&rType, &rData);
|
||||
|
||||
SkGammas::Data gData;
|
||||
SkGammas::Params gParams;
|
||||
SkColorSpaceTransferFn gParams;
|
||||
SkGammas::Type gType =
|
||||
parse_gamma(&gData, &gParams, &tagBytes, g->addr(base), g->fLength);
|
||||
handle_invalid_gamma(&gType, &gData);
|
||||
|
||||
SkGammas::Data bData;
|
||||
SkGammas::Params bParams;
|
||||
SkColorSpaceTransferFn bParams;
|
||||
SkGammas::Type bType =
|
||||
parse_gamma(&bData, &bParams, &tagBytes, b->addr(base), b->fLength);
|
||||
handle_invalid_gamma(&bType, &bData);
|
||||
|
@ -229,6 +229,16 @@ DEF_TEST(ColorSpace_Serialize, r) {
|
||||
const float gammas[] = { 1.1f, 1.2f, 1.7f, };
|
||||
SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor);
|
||||
test_serialize(r, SkColorSpace_Base::NewRGB(gammas, toXYZ).get(), false);
|
||||
|
||||
SkColorSpaceTransferFn fn;
|
||||
fn.fA = 1.0f;
|
||||
fn.fB = 0.0f;
|
||||
fn.fC = 0.0f;
|
||||
fn.fD = 0.5f;
|
||||
fn.fE = 1.0f;
|
||||
fn.fF = 0.0f;
|
||||
fn.fG = 1.0f;
|
||||
test_serialize(r, SkColorSpace::NewRGB(fn, toXYZ).get(), false);
|
||||
}
|
||||
|
||||
DEF_TEST(ColorSpace_Equals, r) {
|
||||
@ -250,6 +260,16 @@ DEF_TEST(ColorSpace_Equals, r) {
|
||||
sk_sp<SkColorSpace> rgb2 = SkColorSpace_Base::NewRGB(gammas2, toXYZ);
|
||||
sk_sp<SkColorSpace> rgb3 = SkColorSpace_Base::NewRGB(gammas1, toXYZ);
|
||||
|
||||
SkColorSpaceTransferFn fn;
|
||||
fn.fA = 1.0f;
|
||||
fn.fB = 0.0f;
|
||||
fn.fC = 0.0f;
|
||||
fn.fD = 0.5f;
|
||||
fn.fE = 1.0f;
|
||||
fn.fF = 0.0f;
|
||||
fn.fG = 1.0f;
|
||||
sk_sp<SkColorSpace> rgb4 = SkColorSpace::NewRGB(fn, toXYZ);
|
||||
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr));
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(srgb.get(), srgb.get()));
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(adobe.get(), adobe.get()));
|
||||
@ -259,6 +279,7 @@ DEF_TEST(ColorSpace_Equals, r) {
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(upperRight.get(), upperRight.get()));
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(rgb1.get(), rgb1.get()));
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(rgb1.get(), rgb3.get()));
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(rgb4.get(), rgb4.get()));
|
||||
|
||||
REPORTER_ASSERT(r, !SkColorSpace::Equals(nullptr, srgb.get()));
|
||||
REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), nullptr));
|
||||
@ -270,6 +291,7 @@ DEF_TEST(ColorSpace_Equals, r) {
|
||||
REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), upperRight.get()));
|
||||
REPORTER_ASSERT(r, !SkColorSpace::Equals(upperRight.get(), adobe.get()));
|
||||
REPORTER_ASSERT(r, !SkColorSpace::Equals(rgb1.get(), rgb2.get()));
|
||||
REPORTER_ASSERT(r, !SkColorSpace::Equals(rgb1.get(), rgb4.get()));
|
||||
}
|
||||
|
||||
DEF_TEST(ColorSpace_Primaries, r) {
|
||||
|
@ -86,12 +86,13 @@ DEF_TEST(ColorSpaceXform_TableGamma, r) {
|
||||
|
||||
DEF_TEST(ColorSpaceXform_ParametricGamma, r) {
|
||||
// Parametric gamma curves
|
||||
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkGammas::Params));
|
||||
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
|
||||
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas());
|
||||
gammas->fRedType = gammas->fGreenType = gammas->fBlueType = SkGammas::Type::kParam_Type;
|
||||
gammas->fRedData.fParamOffset = gammas->fGreenData.fParamOffset =
|
||||
gammas->fBlueData.fParamOffset = 0;
|
||||
SkGammas::Params* params = SkTAddOffset<SkGammas::Params>(memory, sizeof(SkGammas));
|
||||
SkColorSpaceTransferFn* params = SkTAddOffset<SkColorSpaceTransferFn>
|
||||
(memory, sizeof(SkGammas));
|
||||
|
||||
// Interval, switch xforms at 0.0031308f
|
||||
params->fD = 0.04045f;
|
||||
@ -129,7 +130,7 @@ DEF_TEST(ColorSpaceXform_NamedGamma, r) {
|
||||
DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) {
|
||||
constexpr size_t tableSize = 10;
|
||||
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(float) * tableSize +
|
||||
sizeof(SkGammas::Params));
|
||||
sizeof(SkColorSpaceTransferFn));
|
||||
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas());
|
||||
|
||||
float* table = SkTAddOffset<float>(memory, sizeof(SkGammas));
|
||||
@ -144,8 +145,8 @@ DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) {
|
||||
table[8] = 0.85f;
|
||||
table[9] = 1.00f;
|
||||
|
||||
SkGammas::Params* params = SkTAddOffset<SkGammas::Params>(memory, sizeof(SkGammas) +
|
||||
sizeof(float) * tableSize);
|
||||
SkColorSpaceTransferFn* params = SkTAddOffset<SkColorSpaceTransferFn>(memory,
|
||||
sizeof(SkGammas) + sizeof(float) * tableSize);
|
||||
params->fA = 1.0f / 1.055f;
|
||||
params->fB = 0.055f / 1.055f;
|
||||
params->fC = 0.0f;
|
||||
|
Loading…
Reference in New Issue
Block a user