aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2016-12-19 18:37:34 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-12-20 14:38:38 +0000
commit1bfcf887553a9d39b25f0d8c408b78841cd9d8fc (patch)
tree9f9f10119e05c83ba31c2a7bc7acbe8a8a7cc005
parentc468963b967b5e8cde4ed320f7130a9d703c2a4e (diff)
Implement SkICC::WriteICC()
BUG=skia: Change-Id: Idd950c3da2c517780b24e312a4e7cc16ee413c99 Reviewed-on: https://skia-review.googlesource.com/6270 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Matt Sarett <msarett@google.com>
-rw-r--r--src/core/SkColorSpace.cpp26
-rw-r--r--src/core/SkColorSpacePriv.h28
-rw-r--r--src/core/SkColorSpace_Base.h10
-rw-r--r--src/core/SkColorSpace_ICC.cpp8
-rw-r--r--src/core/SkColorSpace_XYZ.cpp6
-rw-r--r--src/core/SkICC.cpp193
-rw-r--r--src/core/SkICCPriv.h9
-rw-r--r--tests/ColorSpaceTest.cpp37
-rw-r--r--tests/ICCTest.cpp43
9 files changed, 170 insertions, 190 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 54c85f1330..f6cbf0acac 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -87,32 +87,6 @@ SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkData> profileData)
: fProfileData(std::move(profileData))
{}
-#if defined(SK_USE_LEGACY_D50_MATRICES)
-static constexpr float gSRGB_toXYZD50[] {
- 0.4358f, 0.3853f, 0.1430f, // Rx, Gx, Bx
- 0.2224f, 0.7170f, 0.0606f, // Ry, Gy, Gz
- 0.0139f, 0.0971f, 0.7139f, // Rz, Gz, Bz
-};
-
-static constexpr float gAdobeRGB_toXYZD50[] {
- 0.6098f, 0.2052f, 0.1492f, // Rx, Gx, Bx
- 0.3111f, 0.6257f, 0.0632f, // Ry, Gy, By
- 0.0195f, 0.0609f, 0.7448f, // Rz, Gz, Bz
-};
-#else
-static constexpr float gSRGB_toXYZD50[] {
- 0.4360747f, 0.3850649f, 0.1430804f, // Rx, Gx, Bx
- 0.2225045f, 0.7168786f, 0.0606169f, // Ry, Gy, Gz
- 0.0139322f, 0.0971045f, 0.7141733f, // Rz, Gz, Bz
-};
-
-static constexpr float gAdobeRGB_toXYZD50[] {
- 0.6097559f, 0.2052401f, 0.1492240f, // Rx, Gx, Bx
- 0.3111242f, 0.6256560f, 0.0632197f, // Ry, Gy, Gz
- 0.0194811f, 0.0608902f, 0.7448387f, // Rz, Gz, Bz
-};
-#endif
-
/**
* Checks if our toXYZ matrix is a close match to a known color gamut.
*
diff --git a/src/core/SkColorSpacePriv.h b/src/core/SkColorSpacePriv.h
index f1ef8dc6d6..5488939099 100644
--- a/src/core/SkColorSpacePriv.h
+++ b/src/core/SkColorSpacePriv.h
@@ -7,8 +7,36 @@
#include <math.h>
+#include "SkColorSpace_Base.h"
+
#define SkColorSpacePrintf(...)
+#if defined(SK_USE_LEGACY_D50_MATRICES)
+static constexpr float gSRGB_toXYZD50[] {
+ 0.4358f, 0.3853f, 0.1430f, // Rx, Gx, Bx
+ 0.2224f, 0.7170f, 0.0606f, // Ry, Gy, Gz
+ 0.0139f, 0.0971f, 0.7139f, // Rz, Gz, Bz
+};
+
+static constexpr float gAdobeRGB_toXYZD50[] {
+ 0.6098f, 0.2052f, 0.1492f, // Rx, Gx, Bx
+ 0.3111f, 0.6257f, 0.0632f, // Ry, Gy, By
+ 0.0195f, 0.0609f, 0.7448f, // Rz, Gz, Bz
+};
+#else
+static constexpr float gSRGB_toXYZD50[] {
+ 0.4360747f, 0.3850649f, 0.1430804f, // Rx, Gx, Bx
+ 0.2225045f, 0.7168786f, 0.0606169f, // Ry, Gy, Gz
+ 0.0139322f, 0.0971045f, 0.7141733f, // Rz, Gz, Bz
+};
+
+static constexpr float gAdobeRGB_toXYZD50[] {
+ 0.6097559f, 0.2052401f, 0.1492240f, // Rx, Gx, Bx
+ 0.3111242f, 0.6256560f, 0.0632197f, // Ry, Gy, Gz
+ 0.0194811f, 0.0608902f, 0.7448387f, // Rz, Gz, Bz
+};
+#endif
+
static inline bool color_space_almost_equal(float a, float b) {
return SkTAbs(a - b) < 0.01f;
}
diff --git a/src/core/SkColorSpace_Base.h b/src/core/SkColorSpace_Base.h
index af8ec3133f..c2e0dc57c3 100644
--- a/src/core/SkColorSpace_Base.h
+++ b/src/core/SkColorSpace_Base.h
@@ -200,16 +200,6 @@ protected:
SkColorSpace_Base(sk_sp<SkData> profileData);
private:
-
- /**
- * FIXME (msarett):
- * Hiding this function until we can determine if we need it. Known issues include:
- * Only writes 3x3 matrices
- * Only writes float gammas
- * Rejected by some parsers because the "profile description" is empty
- */
- sk_sp<SkData> writeToICC() const;
-
SkColorSpace_Base(SkGammaNamed gammaNamed, const SkMatrix44& toXYZ);
sk_sp<SkData> fProfileData;
diff --git a/src/core/SkColorSpace_ICC.cpp b/src/core/SkColorSpace_ICC.cpp
index adb54565d6..29291a3e00 100644
--- a/src/core/SkColorSpace_ICC.cpp
+++ b/src/core/SkColorSpace_ICC.cpp
@@ -375,14 +375,6 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkColorSpaceTransferF
return SkGammas::Type::kTable_Type;
}
case kTAG_ParaCurveType: {
- enum ParaCurveType {
- kExponential_ParaCurveType = 0,
- kGAB_ParaCurveType = 1,
- kGABC_ParaCurveType = 2,
- kGABDE_ParaCurveType = 3,
- kGABCDEF_ParaCurveType = 4,
- };
-
// Determine the format of the parametric curve tag.
uint16_t format = read_big_endian_u16(src + 8);
if (format > kGABCDEF_ParaCurveType) {
diff --git a/src/core/SkColorSpace_XYZ.cpp b/src/core/SkColorSpace_XYZ.cpp
index 30f70b6e26..4329ed8ef2 100644
--- a/src/core/SkColorSpace_XYZ.cpp
+++ b/src/core/SkColorSpace_XYZ.cpp
@@ -10,12 +10,6 @@
#include "SkColorSpacePriv.h"
#include "SkColorSpaceXform_Base.h"
-static constexpr float gSRGB_toXYZD50[] {
- 0.4358f, 0.3853f, 0.1430f, // Rx, Gx, Bx
- 0.2224f, 0.7170f, 0.0606f, // Ry, Gy, Gz
- 0.0139f, 0.0971f, 0.7139f, // Rz, Gz, Bz
-};
-
SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50)
: INHERITED(nullptr)
, fGammaNamed(gammaNamed)
diff --git a/src/core/SkICC.cpp b/src/core/SkICC.cpp
index 7b8ae9f5a0..b47cc71574 100644
--- a/src/core/SkICC.cpp
+++ b/src/core/SkICC.cpp
@@ -7,6 +7,7 @@
#include "SkColorSpace_Base.h"
#include "SkColorSpace_XYZ.h"
+#include "SkColorSpacePriv.h"
#include "SkEndian.h"
#include "SkFixed.h"
#include "SkICC.h"
@@ -41,33 +42,77 @@ bool SkICC::isNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const {
///////////////////////////////////////////////////////////////////////////////////////////////////
+// Google Skia (UTF-16)
+static constexpr uint8_t kDescriptionTagBody[] = {
+ 0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00,
+ 0x53, 0x00, 0x6b, 0x00, 0x69, 0x00, 0x61, 0x00, 0x20,
+ };
+static_assert(SkIsAlign4(sizeof(kDescriptionTagBody)), "Description must be aligned to 4-bytes.");
+static constexpr uint32_t kDescriptionTagHeader[7] {
+ SkEndian_SwapBE32(kTAG_TextType), // Type signature
+ 0, // Reserved
+ SkEndian_SwapBE32(1), // Number of records
+ SkEndian_SwapBE32(12), // Record size (must be 12)
+ SkEndian_SwapBE32(SkSetFourByteTag('e', 'n', 'U', 'S')), // English USA
+ SkEndian_SwapBE32(sizeof(kDescriptionTagBody)), // Length of string
+ SkEndian_SwapBE32(28), // Offset of string
+};
+
+static constexpr uint32_t kWhitePointTag[5] {
+ SkEndian_SwapBE32(kXYZ_PCSSpace),
+ 0,
+ SkEndian_SwapBE32(0x0000f6d6), // X = 0.96420 (D50)
+ SkEndian_SwapBE32(0x00010000), // Y = 1.00000 (D50)
+ SkEndian_SwapBE32(0x0000d32d), // Z = 0.82491 (D50)
+};
+
+// Google Inc. 2016 (UTF-16)
+static constexpr uint8_t kCopyrightTagBody[] = {
+ 0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00,
+ 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31,
+ 0x00, 0x36,
+};
+static_assert(SkIsAlign4(sizeof(kCopyrightTagBody)), "Copyright must be aligned to 4-bytes.");
+static constexpr uint32_t kCopyrightTagHeader[7] {
+ SkEndian_SwapBE32(kTAG_TextType), // Type signature
+ 0, // Reserved
+ SkEndian_SwapBE32(1), // Number of records
+ SkEndian_SwapBE32(12), // Record size (must be 12)
+ SkEndian_SwapBE32(SkSetFourByteTag('e', 'n', 'U', 'S')), // English USA
+ SkEndian_SwapBE32(sizeof(kCopyrightTagBody)), // Length of string
+ SkEndian_SwapBE32(28), // Offset of string
+};
+
// We will write a profile with the minimum nine required tags.
static constexpr uint32_t kICCNumEntries = 9;
static constexpr uint32_t kTAG_desc = SkSetFourByteTag('d', 'e', 's', 'c');
-static constexpr uint32_t kTAG_desc_Bytes = 12;
-static constexpr uint32_t kTAG_desc_Offset = kICCHeaderSize + kICCNumEntries*kICCTagTableEntrySize;
+static constexpr uint32_t kTAG_desc_Bytes = sizeof(kDescriptionTagHeader) +
+ sizeof(kDescriptionTagBody);
+static constexpr uint32_t kTAG_desc_Offset = kICCHeaderSize +
+ kICCNumEntries * kICCTagTableEntrySize;
static constexpr uint32_t kTAG_XYZ_Bytes = 20;
static constexpr uint32_t kTAG_rXYZ_Offset = kTAG_desc_Offset + kTAG_desc_Bytes;
static constexpr uint32_t kTAG_gXYZ_Offset = kTAG_rXYZ_Offset + kTAG_XYZ_Bytes;
static constexpr uint32_t kTAG_bXYZ_Offset = kTAG_gXYZ_Offset + kTAG_XYZ_Bytes;
-static constexpr uint32_t kTAG_TRC_Bytes = 14;
+static constexpr uint32_t kTAG_TRC_Bytes = 40;
static constexpr uint32_t kTAG_rTRC_Offset = kTAG_bXYZ_Offset + kTAG_XYZ_Bytes;
-static constexpr uint32_t kTAG_gTRC_Offset = kTAG_rTRC_Offset + SkAlign4(kTAG_TRC_Bytes);
-static constexpr uint32_t kTAG_bTRC_Offset = kTAG_gTRC_Offset + SkAlign4(kTAG_TRC_Bytes);
+static constexpr uint32_t kTAG_gTRC_Offset = kTAG_rTRC_Offset;
+static constexpr uint32_t kTAG_bTRC_Offset = kTAG_rTRC_Offset;
static constexpr uint32_t kTAG_wtpt = SkSetFourByteTag('w', 't', 'p', 't');
-static constexpr uint32_t kTAG_wtpt_Offset = kTAG_bTRC_Offset + SkAlign4(kTAG_TRC_Bytes);
+static constexpr uint32_t kTAG_wtpt_Offset = kTAG_bTRC_Offset + kTAG_TRC_Bytes;
static constexpr uint32_t kTAG_cprt = SkSetFourByteTag('c', 'p', 'r', 't');
-static constexpr uint32_t kTAG_cprt_Bytes = 12;
+static constexpr uint32_t kTAG_cprt_Bytes = sizeof(kCopyrightTagHeader) +
+ sizeof(kCopyrightTagBody);
static constexpr uint32_t kTAG_cprt_Offset = kTAG_wtpt_Offset + kTAG_XYZ_Bytes;
static constexpr uint32_t kICCProfileSize = kTAG_cprt_Offset + kTAG_cprt_Bytes;
-static constexpr uint32_t gICCHeader[kICCHeaderSize / 4] {
+static constexpr uint32_t kICCHeader[kICCHeaderSize / 4] {
SkEndian_SwapBE32(kICCProfileSize), // Size of the profile
0, // Preferred CMM type (ignored)
SkEndian_SwapBE32(0x02100000), // Version 2.1
@@ -91,7 +136,7 @@ static constexpr uint32_t gICCHeader[kICCHeaderSize / 4] {
SkEndian_SwapBE32(kICCNumEntries), // Number of tags
};
-static constexpr uint32_t gICCTagTable[3 * kICCNumEntries] {
+static constexpr uint32_t kICCTagTable[3 * kICCNumEntries] {
// Profile description
SkEndian_SwapBE32(kTAG_desc),
SkEndian_SwapBE32(kTAG_desc_Offset),
@@ -138,13 +183,6 @@ static constexpr uint32_t gICCTagTable[3 * kICCNumEntries] {
SkEndian_SwapBE32(kTAG_cprt_Bytes),
};
-static constexpr uint32_t kTAG_TextType = SkSetFourByteTag('m', 'l', 'u', 'c');
-static constexpr uint32_t gEmptyTextTag[3] {
- SkEndian_SwapBE32(kTAG_TextType), // Type signature
- 0, // Reserved
- 0, // Zero records
-};
-
static void write_xyz_tag(uint32_t* ptr, const SkMatrix44& toXYZ, int col) {
ptr[0] = SkEndian_SwapBE32(kXYZ_PCSSpace);
ptr[1] = 0;
@@ -153,39 +191,27 @@ static void write_xyz_tag(uint32_t* ptr, const SkMatrix44& toXYZ, int col) {
ptr[4] = SkEndian_SwapBE32(SkFloatToFixed(toXYZ.getFloat(2, col)));
}
-static void write_trc_tag(uint32_t* ptr, float value) {
- ptr[0] = SkEndian_SwapBE32(kTAG_CurveType);
+static void write_trc_tag(uint32_t* ptr, const SkColorSpaceTransferFn& fn) {
+ ptr[0] = SkEndian_SwapBE32(kTAG_ParaCurveType);
ptr[1] = 0;
+ ptr[2] = (uint32_t) (SkEndian_SwapBE16(kGABCDEF_ParaCurveType));
+ ptr[3] = SkEndian_SwapBE32(SkFloatToFixed(fn.fG));
+ ptr[4] = SkEndian_SwapBE32(SkFloatToFixed(fn.fA));
+ ptr[5] = SkEndian_SwapBE32(SkFloatToFixed(fn.fB));
+ ptr[6] = SkEndian_SwapBE32(SkFloatToFixed(fn.fC));
+ ptr[7] = SkEndian_SwapBE32(SkFloatToFixed(fn.fD));
+ ptr[8] = SkEndian_SwapBE32(SkFloatToFixed(fn.fE));
+ ptr[9] = SkEndian_SwapBE32(SkFloatToFixed(fn.fF));
+}
- // Gamma will be specified with a single value.
- ptr[2] = SkEndian_SwapBE32(1);
-
- // Convert gamma to 16-bit fixed point.
- uint16_t* ptr16 = (uint16_t*) (ptr + 3);
- ptr16[0] = SkEndian_SwapBE16((uint16_t) (value * 256.0f));
-
- // Pad tag with zero.
- ptr16[1] = 0;
+static bool is_3x3(const SkMatrix44& toXYZD50) {
+ return 0.0f == toXYZD50.get(3, 0) && 0.0f == toXYZD50.get(3, 1) && 0.0f == toXYZD50.get(3, 2) &&
+ 0.0f == toXYZD50.get(0, 3) && 0.0f == toXYZD50.get(1, 3) && 0.0f == toXYZD50.get(2, 3) &&
+ 1.0f == toXYZD50.get(3, 3);
}
-sk_sp<SkData> SkColorSpace_Base::writeToICC() const {
- // Return if this object was created from a profile, or if we have already serialized
- // the profile.
- if (fProfileData) {
- return fProfileData;
- }
- // Profile Data is be mandatory for A2B0 Color Spaces
- SkASSERT(type() == Type::kXYZ);
-
- // The client may create an SkColorSpace using an SkMatrix44, but currently we only
- // support writing profiles with 3x3 matrices.
- // TODO (msarett): Fix this!
- const SkColorSpace_XYZ* thisXYZ = static_cast<const SkColorSpace_XYZ*>(this);
- const SkMatrix44& toXYZD50 = *thisXYZ->toXYZD50();
- if (0.0f != toXYZD50.getFloat(3, 0) || 0.0f != toXYZD50.getFloat(3, 1) ||
- 0.0f != toXYZD50.getFloat(3, 2) || 0.0f != toXYZD50.getFloat(0, 3) ||
- 0.0f != toXYZD50.getFloat(1, 3) || 0.0f != toXYZD50.getFloat(2, 3))
- {
+sk_sp<SkData> SkICC::WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix44& toXYZD50) {
+ if (!is_3x3(toXYZD50) || !is_valid_transfer_fn(fn)) {
return nullptr;
}
@@ -193,16 +219,18 @@ sk_sp<SkData> SkColorSpace_Base::writeToICC() const {
uint8_t* ptr = (uint8_t*) profile.get();
// Write profile header
- memcpy(ptr, gICCHeader, sizeof(gICCHeader));
- ptr += sizeof(gICCHeader);
+ memcpy(ptr, kICCHeader, sizeof(kICCHeader));
+ ptr += sizeof(kICCHeader);
// Write tag table
- memcpy(ptr, gICCTagTable, sizeof(gICCTagTable));
- ptr += sizeof(gICCTagTable);
+ memcpy(ptr, kICCTagTable, sizeof(kICCTagTable));
+ ptr += sizeof(kICCTagTable);
// Write profile description tag
- memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag));
- ptr += sizeof(gEmptyTextTag);
+ memcpy(ptr, kDescriptionTagHeader, sizeof(kDescriptionTagHeader));
+ ptr += sizeof(kDescriptionTagHeader);
+ memcpy(ptr, kDescriptionTagBody, sizeof(kDescriptionTagBody));
+ ptr += sizeof(kDescriptionTagBody);
// Write XYZ tags
write_xyz_tag((uint32_t*) ptr, toXYZD50, 0);
@@ -212,61 +240,20 @@ sk_sp<SkData> SkColorSpace_Base::writeToICC() const {
write_xyz_tag((uint32_t*) ptr, toXYZD50, 2);
ptr += kTAG_XYZ_Bytes;
- // Write TRC tags
- SkGammaNamed gammaNamed = thisXYZ->gammaNamed();
- if (kNonStandard_SkGammaNamed == gammaNamed) {
- // FIXME (msarett):
- // Write the correct gamma representation rather than 2.2f.
- write_trc_tag((uint32_t*) ptr, 2.2f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- write_trc_tag((uint32_t*) ptr, 2.2f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- write_trc_tag((uint32_t*) ptr, 2.2f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- } else {
- switch (gammaNamed) {
- case kSRGB_SkGammaNamed:
- // FIXME (msarett):
- // kSRGB cannot be represented by a value. Here we fall through to 2.2f,
- // which is a close guess. To be more accurate, we need to represent sRGB
- // gamma with a parametric curve.
- case k2Dot2Curve_SkGammaNamed:
- write_trc_tag((uint32_t*) ptr, 2.2f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- write_trc_tag((uint32_t*) ptr, 2.2f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- write_trc_tag((uint32_t*) ptr, 2.2f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- break;
- case kLinear_SkGammaNamed:
- write_trc_tag((uint32_t*) ptr, 1.0f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- write_trc_tag((uint32_t*) ptr, 1.0f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- write_trc_tag((uint32_t*) ptr, 1.0f);
- ptr += SkAlign4(kTAG_TRC_Bytes);
- break;
- default:
- SkASSERT(false);
- break;
- }
- }
+ // Write TRC tag
+ write_trc_tag((uint32_t*) ptr, fn);
+ ptr += kTAG_TRC_Bytes;
- // Write white point tag
- uint32_t* ptr32 = (uint32_t*) ptr;
- ptr32[0] = SkEndian_SwapBE32(kXYZ_PCSSpace);
- ptr32[1] = 0;
- // TODO (msarett): These values correspond to the D65 white point. This may not always be
- // correct.
- ptr32[2] = SkEndian_SwapBE32(0x0000f351);
- ptr32[3] = SkEndian_SwapBE32(0x00010000);
- ptr32[4] = SkEndian_SwapBE32(0x000116cc);
- ptr += kTAG_XYZ_Bytes;
+ // Write white point tag (must be D50)
+ memcpy(ptr, kWhitePointTag, sizeof(kWhitePointTag));
+ ptr += sizeof(kWhitePointTag);
// Write copyright tag
- memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag));
+ memcpy(ptr, kCopyrightTagHeader, sizeof(kCopyrightTagHeader));
+ ptr += sizeof(kCopyrightTagHeader);
+ memcpy(ptr, kCopyrightTagBody, sizeof(kCopyrightTagBody));
+ ptr += sizeof(kCopyrightTagBody);
- // TODO (msarett): Should we try to hold onto the data so we can return immediately if
- // the client calls again?
+ SkASSERT(kICCProfileSize == ptr - (uint8_t*) profile.get());
return SkData::MakeFromMalloc(profile.release(), kICCProfileSize);
}
diff --git a/src/core/SkICCPriv.h b/src/core/SkICCPriv.h
index ac8566778d..bc8a9e9533 100644
--- a/src/core/SkICCPriv.h
+++ b/src/core/SkICCPriv.h
@@ -35,3 +35,12 @@ static constexpr uint32_t kTAG_A2B0 = SkSetFourByteTag('A', '2', 'B', '0');
static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', 'v');
static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', 'a');
+static constexpr uint32_t kTAG_TextType = SkSetFourByteTag('m', 'l', 'u', 'c');
+
+enum ParaCurveType {
+ kExponential_ParaCurveType = 0,
+ kGAB_ParaCurveType = 1,
+ kGABC_ParaCurveType = 2,
+ kGABDE_ParaCurveType = 3,
+ kGABCDEF_ParaCurveType = 4,
+};
diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp
index 070d50264f..df253c09e3 100644
--- a/tests/ColorSpaceTest.cpp
+++ b/tests/ColorSpaceTest.cpp
@@ -142,43 +142,6 @@ DEF_TEST(ColorSpaceSRGBLinearCompare, r) {
REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
}
-class ColorSpaceTest {
-public:
- static sk_sp<SkData> WriteToICC(SkColorSpace* space) {
- return as_CSB(space)->writeToICC();
- }
-};
-
-DEF_TEST(ColorSpaceWriteICC, r) {
- // Test writing a new ICC profile
- sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
- sk_sp<SkData> namedData = ColorSpaceTest::WriteToICC(namedColorSpace.get());
- sk_sp<SkColorSpace> iccColorSpace = SkColorSpace::MakeICC(namedData->data(), namedData->size());
- test_space(r, iccColorSpace.get(), g_sRGB_R, g_sRGB_G, g_sRGB_B, k2Dot2Curve_SkGammaNamed);
- // FIXME (msarett): Test disabled. sRGB profiles are written approximately as 2.2f curves.
- // REPORTER_ASSERT(r, iccColorSpace == namedColorSpace);
-
- // Test saving the original ICC data
- sk_sp<SkData> monitorData = SkData::MakeFromFileName(
- GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str());
- REPORTER_ASSERT(r, monitorData);
- if (!monitorData) {
- return;
- }
- sk_sp<SkColorSpace> monitorSpace = SkColorSpace::MakeICC(monitorData->data(),
- monitorData->size());
- sk_sp<SkData> newMonitorData = ColorSpaceTest::WriteToICC(monitorSpace.get());
- sk_sp<SkColorSpace> newMonitorSpace = SkColorSpace::MakeICC(newMonitorData->data(),
- newMonitorData->size());
- SkASSERT(SkColorSpace_Base::Type::kXYZ == as_CSB(monitorSpace)->type());
- SkColorSpace_XYZ* monitorSpaceXYZ = static_cast<SkColorSpace_XYZ*>(monitorSpace.get());
- SkASSERT(SkColorSpace_Base::Type::kXYZ == as_CSB(newMonitorSpace)->type());
- SkColorSpace_XYZ* newMonitorSpaceXYZ = static_cast<SkColorSpace_XYZ*>(newMonitorSpace.get());
- REPORTER_ASSERT(r, *monitorSpaceXYZ->toXYZD50() == *newMonitorSpaceXYZ->toXYZD50());
- REPORTER_ASSERT(r, monitorSpaceXYZ->toXYZD50Hash() == newMonitorSpaceXYZ->toXYZD50Hash());
- REPORTER_ASSERT(r, monitorSpaceXYZ->gammaNamed() == newMonitorSpaceXYZ->gammaNamed());
-}
-
DEF_TEST(ColorSpace_Named, r) {
const struct {
SkColorSpace::Named fNamed;
diff --git a/tests/ICCTest.cpp b/tests/ICCTest.cpp
index 38d6801c5f..4bc296d140 100644
--- a/tests/ICCTest.cpp
+++ b/tests/ICCTest.cpp
@@ -7,9 +7,11 @@
#include "Resources.h"
#include "SkColorSpace.h"
+#include "SkColorSpacePriv.h"
#include "SkData.h"
#include "SkICC.h"
#include "SkMatrix44.h"
+#include "SkStream.h"
#include "Test.h"
static bool almost_equal(float a, float b) {
@@ -95,3 +97,44 @@ DEF_TEST(ICC_IsNumericalTransferFn, r) {
sk_sp<SkICC> upperRight = SkICC::Make(data->data(), data->size());
test_is_numerical_transfer_fn(r, upperRight.get(), false, referenceFn);
}
+
+static inline void test_write_icc(skiatest::Reporter* r, const SkColorSpaceTransferFn& fn,
+ const SkMatrix44& toXYZD50, SkColorSpace* reference,
+ bool writeToFile) {
+ sk_sp<SkData> profile = SkICC::WriteToICC(fn, toXYZD50);
+ if (writeToFile) {
+ SkFILEWStream stream("out.icc");
+ stream.write(profile->data(), profile->size());
+ }
+
+ sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(profile->data(), profile->size());
+ REPORTER_ASSERT(r, SkColorSpace::Equals(reference, colorSpace.get()));
+}
+
+DEF_TEST(ICC_WriteICC, r) {
+ SkColorSpaceTransferFn adobeFn;
+ adobeFn.fA = 1.0f;
+ adobeFn.fB = 0.0f;
+ adobeFn.fC = 0.0f;
+ adobeFn.fD = 0.0f;
+ adobeFn.fE = 0.0f;
+ adobeFn.fF = 0.0f;
+ adobeFn.fG = 2.2f;
+ SkMatrix44 adobeMatrix(SkMatrix44::kUninitialized_Constructor);
+ adobeMatrix.set3x3RowMajorf(gAdobeRGB_toXYZD50);
+ test_write_icc(r, adobeFn, adobeMatrix,
+ SkColorSpace::MakeNamed(SkColorSpace::kAdobeRGB_Named).get(), false);
+
+ SkColorSpaceTransferFn srgbFn;
+ srgbFn.fA = 1.0f / 1.055f;
+ srgbFn.fB = 0.055f / 1.055f;
+ srgbFn.fC = 1.0f / 12.92f;
+ srgbFn.fD = 0.04045f;
+ srgbFn.fE = 0.0f;
+ srgbFn.fF = 0.0f;
+ srgbFn.fG = 2.4f;
+ SkMatrix44 srgbMatrix(SkMatrix44::kUninitialized_Constructor);
+ srgbMatrix.set3x3RowMajorf(gSRGB_toXYZD50);
+ test_write_icc(r, srgbFn, srgbMatrix, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).get(),
+ false);
+}