aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2017-06-16 13:38:34 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-16 21:30:37 +0000
commit7a808d618e90e216cf4fa6369f658350319deb02 (patch)
tree1de807337207c8bb60e30bcf8686689c64f44b83
parent93323eb401dc9003dda881ac83222d115151947f (diff)
ICC: SkICC::WriteToICC Description Tag is function of input
BUG=skia:6720 Change-Id: I038079a6e15f884eb77b84d9c7c75f6b7fbedd37 Reviewed-on: https://skia-review.googlesource.com/20152 Commit-Queue: Hal Canary <halcanary@google.com> Reviewed-by: Matt Sarett <msarett@google.com>
-rw-r--r--src/core/SkICC.cpp58
-rw-r--r--src/core/SkICCPriv.h11
-rw-r--r--tests/ICCTest.cpp19
3 files changed, 76 insertions, 12 deletions
diff --git a/src/core/SkICC.cpp b/src/core/SkICC.cpp
index 40a733f872..c26f6d8e58 100644
--- a/src/core/SkICC.cpp
+++ b/src/core/SkICC.cpp
@@ -14,6 +14,7 @@
#include "SkFixed.h"
#include "SkICC.h"
#include "SkICCPriv.h"
+#include "SkMD5.h"
SkICC::SkICC(sk_sp<SkColorSpace> colorSpace)
: fColorSpace(std::move(colorSpace))
@@ -139,19 +140,19 @@ bool SkICC::rawTransferFnData(Tables* tables) 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 char kDescriptionTagBodyPrefix[12] =
+ { 'G', 'o', 'o', 'g', 'l', 'e', '/', 'S', 'k', 'i', 'a' , '/'};
+static constexpr size_t kDescriptionTagBodySize =
+ (sizeof(kDescriptionTagBodyPrefix) + 2 * sizeof(SkMD5::Digest)) * 2;
+
+static_assert(SkIsAlign4(kDescriptionTagBodySize), "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(kDescriptionTagBodySize), // Length of string
SkEndian_SwapBE32(28), // Offset of string
};
@@ -185,7 +186,7 @@ static constexpr uint32_t kICCNumEntries = 9;
static constexpr uint32_t kTAG_desc = SkSetFourByteTag('d', 'e', 's', 'c');
static constexpr uint32_t kTAG_desc_Bytes = sizeof(kDescriptionTagHeader) +
- sizeof(kDescriptionTagBody);
+ kDescriptionTagBodySize;
static constexpr uint32_t kTAG_desc_Offset = kICCHeaderSize +
kICCNumEntries * kICCTagTableEntrySize;
@@ -307,6 +308,42 @@ static bool is_3x3(const SkMatrix44& toXYZD50) {
1.0f == toXYZD50.get(3, 3);
}
+size_t SkICCWriteDescriptionTag(uint8_t* ptr,
+ const SkColorSpaceTransferFn& fn,
+ const SkMatrix44& toXYZD50) {
+ if (ptr) {
+ SkDEBUGCODE(const uint8_t* const ptrCheck = ptr);
+ memcpy(ptr, kDescriptionTagHeader, sizeof(kDescriptionTagHeader));
+ ptr += sizeof(kDescriptionTagHeader);
+
+ for (unsigned i = 0; i < sizeof(kDescriptionTagBodyPrefix); ++i) {
+ *ptr++ = 0;
+ *ptr++ = kDescriptionTagBodyPrefix[i];
+ }
+ SkMD5 md5;
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ float value = toXYZD50.getFloat(i,j);
+ md5.write(&value, sizeof(value));
+ }
+ }
+ static_assert(sizeof(fn) == sizeof(float) * 7, "packed");
+ md5.write(&fn, sizeof(fn));
+ SkMD5::Digest digest;
+ md5.finish(digest);
+ for (unsigned i = 0; i < sizeof(SkMD5::Digest); ++i) {
+ static const char gHex[] = "0123456789ABCDEF";
+ *ptr++ = 0;
+ *ptr++ = gHex[digest.data[i] >> 4];
+ *ptr++ = 0;
+ *ptr++ = gHex[digest.data[i] & 0xF];
+ }
+ SkASSERT(ptr == ptrCheck + kDescriptionTagBodySize + sizeof(kDescriptionTagHeader));
+ }
+ return kDescriptionTagBodySize + sizeof(kDescriptionTagHeader);
+}
+
+
sk_sp<SkData> SkICC::WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix44& toXYZD50) {
if (!is_3x3(toXYZD50) || !is_valid_transfer_fn(fn)) {
return nullptr;
@@ -324,10 +361,7 @@ sk_sp<SkData> SkICC::WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix
ptr += sizeof(kICCTagTable);
// Write profile description tag
- memcpy(ptr, kDescriptionTagHeader, sizeof(kDescriptionTagHeader));
- ptr += sizeof(kDescriptionTagHeader);
- memcpy(ptr, kDescriptionTagBody, sizeof(kDescriptionTagBody));
- ptr += sizeof(kDescriptionTagBody);
+ ptr += SkICCWriteDescriptionTag(ptr, fn, toXYZD50);
// Write XYZ tags
write_xyz_tag((uint32_t*) ptr, toXYZD50, 0);
diff --git a/src/core/SkICCPriv.h b/src/core/SkICCPriv.h
index 4c656f17d8..eb5c13d595 100644
--- a/src/core/SkICCPriv.h
+++ b/src/core/SkICCPriv.h
@@ -49,4 +49,15 @@ enum ParaCurveType {
kGABDE_ParaCurveType = 3,
kGABCDEF_ParaCurveType = 4,
};
+
+/*
+ * Given fn and toXYZD50, generate a ICC decription tag that includes a hash of
+ * the input. If ptr is not nullptr, write the tag there. Always returns
+ * length of the tag.
+ *
+ * Exposed for unit testing.
+ */
+size_t SkICCWriteDescriptionTag(uint8_t* ptr,
+ const SkColorSpaceTransferFn& fn,
+ const SkMatrix44& toXYZD50);
#endif // SkICCPriv_DEFINED
diff --git a/tests/ICCTest.cpp b/tests/ICCTest.cpp
index 5d541bdc27..3c855fb22d 100644
--- a/tests/ICCTest.cpp
+++ b/tests/ICCTest.cpp
@@ -11,6 +11,7 @@
#include "SkColorSpace_XYZ.h"
#include "SkData.h"
#include "SkICC.h"
+#include "SkICCPriv.h"
#include "SkMatrix44.h"
#include "SkStream.h"
#include "Test.h"
@@ -112,6 +113,14 @@ static inline void test_write_icc(skiatest::Reporter* r, const SkColorSpaceTrans
REPORTER_ASSERT(r, SkColorSpace::Equals(reference, colorSpace.get()));
}
+template <typename T>
+static bool equal(const SkTArray<T>& u, const SkTArray<T>& v) {
+ if (u.count() != v.count()) {
+ return false;
+ }
+ return u.count() == 0 || 0 == memcmp(&u[0], &v[0], sizeof(T) * u.count());
+}
+
DEF_TEST(ICC_WriteICC, r) {
SkColorSpaceTransferFn adobeFn;
adobeFn.fA = 1.0f;
@@ -138,6 +147,16 @@ DEF_TEST(ICC_WriteICC, r) {
srgbMatrix.set3x3RowMajorf(gSRGB_toXYZD50);
test_write_icc(r, srgbFn, srgbMatrix, SkColorSpace::MakeSRGB().get(),
false);
+
+ SkTArray<uint8_t> adobeTag;
+ adobeTag.reset(SkToInt(SkICCWriteDescriptionTag(nullptr, adobeFn, adobeMatrix)));
+ SkICCWriteDescriptionTag(&adobeTag[0], adobeFn, adobeMatrix);
+
+ SkTArray<uint8_t> srgbTag;
+ srgbTag.reset(SkToInt(SkICCWriteDescriptionTag(nullptr, srgbFn, srgbMatrix)));
+ SkICCWriteDescriptionTag(&srgbTag[0], srgbFn, srgbMatrix);
+
+ REPORTER_ASSERT(r, !equal(adobeTag, srgbTag));
}
static inline void test_raw_transfer_fn(skiatest::Reporter* r, SkICC* icc) {