Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7ba1d64

Browse files
brianosmanSkia Commit-Bot
authored andcommitted
Revert "Remove old ICC parser, A2B SkColorSpace, SkGammas, etc..."
This reverts commit 8ae7c90. Reason for revert: Chrome roll Original change's description: > Remove old ICC parser, A2B SkColorSpace, SkGammas, etc... > > Docs-Preview: https://skia.org/?cl=148807 > Change-Id: I2d77f6543e390c4948d57242a518af77443f0165 > Reviewed-on: https://skia-review.googlesource.com/148807 > Commit-Queue: Mike Klein <mtklein@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> TBR=mtklein@google.com,brianosman@google.com,reed@google.com Change-Id: I5821591b22e395327ec0cd29ec18569bf7f61859 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/150142 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
1 parent 5223243 commit 7ba1d64

File tree

12 files changed

+2151
-102
lines changed

12 files changed

+2151
-102
lines changed

gn/core.gni

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ skia_core_sources = [
7575
"$_src/core/SkColorMatrixFilterRowMajor255.cpp",
7676
"$_src/core/SkColorMatrixFilterRowMajor255.h",
7777
"$_src/core/SkColorSpace.cpp",
78+
"$_src/core/SkColorSpace_A2B.cpp",
79+
"$_src/core/SkColorSpace_A2B.h",
7880
"$_src/core/SkColorSpace_XYZ.cpp",
7981
"$_src/core/SkColorSpace_XYZ.h",
82+
"$_src/core/SkColorSpace_ICC.cpp",
8083
"$_src/core/SkColorSpaceXform.cpp",
8184
"$_src/core/SkColorSpaceXformCanvas.cpp",
8285
"$_src/core/SkColorSpaceXformSteps.cpp",

include/core/SkColorSpace.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ class SK_API SkColorSpace : public SkRefCnt {
126126

127127
static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);
128128

129+
/**
130+
* Create an SkColorSpace from an ICC profile.
131+
*/
132+
static sk_sp<SkColorSpace> MakeICC(const void*, size_t);
133+
129134
/**
130135
* Create an SkColorSpace from a parsed (skcms) ICC profile.
131136
*/
@@ -136,6 +141,16 @@ class SK_API SkColorSpace : public SkRefCnt {
136141
*/
137142
void toProfile(skcms_ICCProfile*) const;
138143

144+
/**
145+
* Types of colorspaces.
146+
*/
147+
enum Type {
148+
kRGB_Type,
149+
kCMYK_Type,
150+
kGray_Type,
151+
};
152+
Type type() const;
153+
139154
SkGammaNamed gammaNamed() const;
140155

141156
/**
@@ -250,6 +265,9 @@ class SK_API SkColorSpace : public SkRefCnt {
250265
virtual bool onGammaCloseToSRGB() const = 0;
251266
virtual bool onGammaIsLinear() const = 0;
252267
virtual bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const = 0;
268+
virtual bool onIsCMYK() const { return false; }
269+
270+
virtual const SkData* onProfileData() const { return nullptr; }
253271

254272
using INHERITED = SkRefCnt;
255273
};

site/user/sample/color.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ to make color spaces.
8080

8181
// Choose a common gamut and a common transfer function
8282
sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma, Gamut);
83+
84+
// Create a color space from an ICC profile
85+
sk_sp<SkColorSpace> MakeICC();
8386

8487
Starting with **sources** (the things that you draw), there are a number of ways to make sure
8588
that they are tagged with a color space.

src/core/SkColorSpace.cpp

Lines changed: 120 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include "SkColorSpace_XYZ.h"
1010
#include "SkColorSpacePriv.h"
1111
#include "SkPoint3.h"
12-
#include "SkTemplates.h"
1312
#include <new>
1413

1514
bool SkColorSpacePrimaries::toXYZD50(SkMatrix44* toXYZ_D50) const {
@@ -128,7 +127,7 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(SkGammaNamed gammaNamed, const SkMatri
128127
break;
129128
}
130129

131-
return sk_sp<SkColorSpace>(new SkColorSpace_XYZ(gammaNamed, nullptr, toXYZD50));
130+
return sk_sp<SkColorSpace>(new SkColorSpace_XYZ(gammaNamed, toXYZD50));
132131
}
133132

134133
sk_sp<SkColorSpace> SkColorSpace::MakeRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50) {
@@ -160,7 +159,18 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const SkColorSpaceTransferFn& coeffs,
160159
return SkColorSpace::MakeRGB(kLinear_SkGammaNamed, toXYZD50);
161160
}
162161

163-
return sk_sp<SkColorSpace>(new SkColorSpace_XYZ(kNonStandard_SkGammaNamed, &coeffs, toXYZD50));
162+
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
163+
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas(3));
164+
SkColorSpaceTransferFn* fn = SkTAddOffset<SkColorSpaceTransferFn>(memory, sizeof(SkGammas));
165+
*fn = coeffs;
166+
SkGammas::Data data;
167+
data.fParamOffset = 0;
168+
for (int channel = 0; channel < 3; ++channel) {
169+
gammas->fType[channel] = SkGammas::Type::kParam_Type;
170+
gammas->fData[channel] = data;
171+
}
172+
return sk_sp<SkColorSpace>(new SkColorSpace_XYZ(kNonStandard_SkGammaNamed,
173+
std::move(gammas), toXYZD50, nullptr));
164174
}
165175

166176
sk_sp<SkColorSpace> SkColorSpace::MakeRGB(RenderTargetGamma gamma, Gamut gamut) {
@@ -179,7 +189,7 @@ static SkColorSpace* singleton_colorspace(SkGammaNamed gamma, const float to_xyz
179189
SkMatrix44 m44(SkMatrix44::kUninitialized_Constructor);
180190
m44.set3x3RowMajorf(to_xyz);
181191
(void)m44.getType(); // Force typemask to be computed to avoid races.
182-
return new SkColorSpace_XYZ(gamma, nullptr, m44);
192+
return new SkColorSpace_XYZ(gamma, m44);
183193
}
184194

185195
SkColorSpace* sk_srgb_singleton() {
@@ -201,6 +211,14 @@ sk_sp<SkColorSpace> SkColorSpace::MakeSRGBLinear() {
201211

202212
///////////////////////////////////////////////////////////////////////////////////////////////////
203213

214+
SkColorSpace::Type SkColorSpace::type() const {
215+
const SkMatrix44* m = this->toXYZD50();
216+
if (m) {
217+
return m->isScale() ? kGray_Type : kRGB_Type;
218+
}
219+
return this->onIsCMYK() ? kCMYK_Type : kRGB_Type;
220+
}
221+
204222
SkGammaNamed SkColorSpace::gammaNamed() const {
205223
return this->onGammaNamed();
206224
}
@@ -271,7 +289,6 @@ struct ColorSpaceHeader {
271289
* If kICC_Flag is set, we will write an ICC profile after the header.
272290
* The ICC profile will be written as a uint32 size, followed immediately
273291
* by the data (padded to 4 bytes).
274-
* DEPRECATED / UNUSED
275292
*/
276293
static constexpr uint8_t kICC_Flag = 1 << 1;
277294

@@ -307,61 +324,87 @@ struct ColorSpaceHeader {
307324
};
308325

309326
size_t SkColorSpace::writeToMemory(void* memory) const {
310-
// If we have a named profile, only write the enum.
311-
const SkGammaNamed gammaNamed = this->gammaNamed();
312-
if (this == sk_srgb_singleton()) {
313-
if (memory) {
314-
*((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
315-
k0_Version, kSRGB_NamedColorSpace, gammaNamed, 0);
316-
}
317-
return sizeof(ColorSpaceHeader);
318-
} else if (this == sk_srgb_linear_singleton()) {
319-
if (memory) {
320-
*((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
321-
k0_Version, kSRGBLinear_NamedColorSpace, gammaNamed, 0);
322-
}
323-
return sizeof(ColorSpaceHeader);
324-
}
325-
326-
// If we have a named gamma, write the enum and the matrix.
327-
switch (gammaNamed) {
328-
case kSRGB_SkGammaNamed:
329-
case k2Dot2Curve_SkGammaNamed:
330-
case kLinear_SkGammaNamed: {
327+
// Start by trying the serialization fast path. If we haven't saved ICC profile data,
328+
// we must have a profile that we can serialize easily.
329+
if (!this->onProfileData()) {
330+
// Profile data is mandatory for A2B0 color spaces, so we must be XYZ.
331+
SkASSERT(this->toXYZD50());
332+
// If we have a named profile, only write the enum.
333+
const SkGammaNamed gammaNamed = this->gammaNamed();
334+
if (this == sk_srgb_singleton()) {
331335
if (memory) {
332-
*((ColorSpaceHeader*) memory) =
333-
ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
334-
ColorSpaceHeader::kMatrix_Flag);
335-
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
336-
this->toXYZD50()->as3x4RowMajorf((float*) memory);
336+
*((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
337+
k0_Version, kSRGB_NamedColorSpace, gammaNamed, 0);
337338
}
338-
return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
339-
}
340-
default: {
341-
SkColorSpaceTransferFn transferFn;
342-
SkAssertResult(this->isNumericalTransferFn(&transferFn));
343-
339+
return sizeof(ColorSpaceHeader);
340+
} else if (this == sk_srgb_linear_singleton()) {
344341
if (memory) {
345-
*((ColorSpaceHeader*) memory) =
346-
ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
347-
ColorSpaceHeader::kTransferFn_Flag);
348-
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
349-
350-
*(((float*) memory) + 0) = transferFn.fA;
351-
*(((float*) memory) + 1) = transferFn.fB;
352-
*(((float*) memory) + 2) = transferFn.fC;
353-
*(((float*) memory) + 3) = transferFn.fD;
354-
*(((float*) memory) + 4) = transferFn.fE;
355-
*(((float*) memory) + 5) = transferFn.fF;
356-
*(((float*) memory) + 6) = transferFn.fG;
357-
memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
358-
359-
this->toXYZD50()->as3x4RowMajorf((float*) memory);
342+
*((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
343+
k0_Version, kSRGBLinear_NamedColorSpace, gammaNamed, 0);
360344
}
345+
return sizeof(ColorSpaceHeader);
346+
}
361347

362-
return sizeof(ColorSpaceHeader) + 19 * sizeof(float);
348+
// If we have a named gamma, write the enum and the matrix.
349+
switch (gammaNamed) {
350+
case kSRGB_SkGammaNamed:
351+
case k2Dot2Curve_SkGammaNamed:
352+
case kLinear_SkGammaNamed: {
353+
if (memory) {
354+
*((ColorSpaceHeader*) memory) =
355+
ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
356+
ColorSpaceHeader::kMatrix_Flag);
357+
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
358+
this->toXYZD50()->as3x4RowMajorf((float*) memory);
359+
}
360+
return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
361+
}
362+
default: {
363+
SkColorSpaceTransferFn transferFn;
364+
SkAssertResult(this->isNumericalTransferFn(&transferFn));
365+
366+
if (memory) {
367+
*((ColorSpaceHeader*) memory) =
368+
ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
369+
ColorSpaceHeader::kTransferFn_Flag);
370+
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
371+
372+
*(((float*) memory) + 0) = transferFn.fA;
373+
*(((float*) memory) + 1) = transferFn.fB;
374+
*(((float*) memory) + 2) = transferFn.fC;
375+
*(((float*) memory) + 3) = transferFn.fD;
376+
*(((float*) memory) + 4) = transferFn.fE;
377+
*(((float*) memory) + 5) = transferFn.fF;
378+
*(((float*) memory) + 6) = transferFn.fG;
379+
memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
380+
381+
this->toXYZD50()->as3x4RowMajorf((float*) memory);
382+
}
383+
384+
return sizeof(ColorSpaceHeader) + 19 * sizeof(float);
385+
}
363386
}
364387
}
388+
389+
// Otherwise, serialize the ICC data.
390+
size_t profileSize = this->onProfileData()->size();
391+
if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) {
392+
return 0;
393+
}
394+
395+
if (memory) {
396+
*((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(k0_Version, 0,
397+
kNonStandard_SkGammaNamed,
398+
ColorSpaceHeader::kICC_Flag);
399+
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
400+
401+
*((uint32_t*) memory) = (uint32_t) SkAlign4(profileSize);
402+
memory = SkTAddOffset<void>(memory, sizeof(uint32_t));
403+
404+
memcpy(memory, this->onProfileData()->data(), profileSize);
405+
memset(SkTAddOffset<void>(memory, profileSize), 0, SkAlign4(profileSize) - profileSize);
406+
}
407+
return sizeof(ColorSpaceHeader) + sizeof(uint32_t) + SkAlign4(profileSize);
365408
}
366409

367410
sk_sp<SkData> SkColorSpace::serialize() const {
@@ -412,8 +455,18 @@ sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) {
412455

413456
switch (header.fFlags) {
414457
case ColorSpaceHeader::kICC_Flag: {
415-
// Deprecated and unsupported code path
416-
return nullptr;
458+
if (length < sizeof(uint32_t)) {
459+
return nullptr;
460+
}
461+
462+
uint32_t profileSize = *((uint32_t*) data);
463+
data = SkTAddOffset<const void>(data, sizeof(uint32_t));
464+
length -= sizeof(uint32_t);
465+
if (length < profileSize) {
466+
return nullptr;
467+
}
468+
469+
return MakeICC(data, profileSize);
417470
}
418471
case ColorSpaceHeader::kTransferFn_Flag: {
419472
if (length < 19 * sizeof(float)) {
@@ -448,6 +501,18 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
448501
return false;
449502
}
450503

504+
const SkData* srcData = src->onProfileData();
505+
const SkData* dstData = dst->onProfileData();
506+
if (srcData || dstData) {
507+
if (srcData && dstData) {
508+
return srcData->size() == dstData->size() &&
509+
0 == memcmp(srcData->data(), dstData->data(), srcData->size());
510+
}
511+
512+
return false;
513+
}
514+
515+
// Profiles are mandatory for A2B0 color spaces, so these must be XYZ
451516
if (src->gammaNamed() != dst->gammaNamed()) {
452517
return false;
453518
}
@@ -463,7 +528,6 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
463528
return false;
464529
default:
465530
// It is unlikely that we will reach this case.
466-
// TODO: Simplify this case now that color spaces have one representation.
467531
sk_sp<SkData> serializedSrcData = src->serialize();
468532
sk_sp<SkData> serializedDstData = dst->serialize();
469533
return serializedSrcData->size() == serializedDstData->size() &&

src/core/SkColorSpacePriv.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,43 @@ static inline bool is_almost_linear(const SkColorSpaceTransferFn& coeffs) {
188188
return linearExp || linearFn;
189189
}
190190

191+
static inline bool is_just_gamma(const SkColorSpaceTransferFn& coeffs) {
192+
return transfer_fn_almost_equal(coeffs.fA, 1.0f)
193+
&& transfer_fn_almost_equal(coeffs.fB, 0.0f)
194+
&& transfer_fn_almost_equal(coeffs.fC, 0.0f)
195+
&& transfer_fn_almost_equal(coeffs.fD, 0.0f)
196+
&& transfer_fn_almost_equal(coeffs.fE, 0.0f)
197+
&& transfer_fn_almost_equal(coeffs.fF, 0.0f);
198+
}
199+
200+
201+
static inline void value_to_parametric(SkColorSpaceTransferFn* coeffs, float exponent) {
202+
coeffs->fA = 1.0f;
203+
coeffs->fB = 0.0f;
204+
coeffs->fC = 0.0f;
205+
coeffs->fD = 0.0f;
206+
coeffs->fE = 0.0f;
207+
coeffs->fF = 0.0f;
208+
coeffs->fG = exponent;
209+
}
210+
211+
static inline bool named_to_parametric(SkColorSpaceTransferFn* coeffs,
212+
SkGammaNamed gammaNamed) {
213+
switch (gammaNamed) {
214+
case kSRGB_SkGammaNamed:
215+
*coeffs = gSRGB_TransferFn;
216+
return true;
217+
case k2Dot2Curve_SkGammaNamed:
218+
*coeffs = g2Dot2_TransferFn;
219+
return true;
220+
case kLinear_SkGammaNamed:
221+
*coeffs = gLinear_TransferFn;
222+
return true;
223+
default:
224+
return false;
225+
}
226+
}
227+
191228
// Return raw pointers to commonly used SkColorSpaces.
192229
// No need to ref/unref these, but if you do, do it in pairs.
193230
SkColorSpace* sk_srgb_singleton();

src/core/SkColorSpaceXform.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,23 @@ bool SkColorSpaceXform_skcms::apply(ColorFormat dstFormat, void* dst,
7777
}
7878

7979
void SkColorSpace::toProfile(skcms_ICCProfile* profile) const {
80-
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
81-
SkColorSpaceTransferFn tf;
82-
SkAssertResult(this->toXYZD50(&toXYZ) && this->isNumericalTransferFn(&tf));
83-
84-
skcms_Matrix3x3 m = { {
85-
{ toXYZ.get(0, 0), toXYZ.get(0, 1), toXYZ.get(0, 2) },
86-
{ toXYZ.get(1, 0), toXYZ.get(1, 1), toXYZ.get(1, 2) },
87-
{ toXYZ.get(2, 0), toXYZ.get(2, 1), toXYZ.get(2, 2) },
88-
} };
89-
90-
skcms_Init(profile);
91-
skcms_SetTransferFunction(profile, (const skcms_TransferFunction*)&tf);
92-
skcms_SetXYZD50(profile, &m);
80+
if (auto blob = this->onProfileData()) {
81+
SkAssertResult(skcms_Parse(blob->data(), blob->size(), profile));
82+
} else {
83+
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
84+
SkColorSpaceTransferFn tf;
85+
SkAssertResult(this->toXYZD50(&toXYZ) && this->isNumericalTransferFn(&tf));
86+
87+
skcms_Matrix3x3 m = { {
88+
{ toXYZ.get(0, 0), toXYZ.get(0, 1), toXYZ.get(0, 2) },
89+
{ toXYZ.get(1, 0), toXYZ.get(1, 1), toXYZ.get(1, 2) },
90+
{ toXYZ.get(2, 0), toXYZ.get(2, 1), toXYZ.get(2, 2) },
91+
} };
92+
93+
skcms_Init(profile);
94+
skcms_SetTransferFunction(profile, (const skcms_TransferFunction*)&tf);
95+
skcms_SetXYZD50(profile, &m);
96+
}
9397
}
9498

9599
std::unique_ptr<SkColorSpaceXform> SkMakeColorSpaceXform(SkColorSpace* src, SkColorSpace* dst) {

0 commit comments

Comments
 (0)