From 9d15dab754f9d2633d34db041dc453249dd7e8ac Mon Sep 17 00:00:00 2001 From: msarett Date: Wed, 24 Aug 2016 07:36:06 -0700 Subject: Parse ICC profiles from webps BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2269333002 Review-Url: https://codereview.chromium.org/2269333002 --- resources/webp-color-profile-crash.webp | Bin 0 -> 35882 bytes resources/webp-color-profile-lossless.webp | Bin 0 -> 43866 bytes resources/webp-color-profile-lossy-alpha.webp | Bin 0 -> 16018 bytes resources/webp-color-profile-lossy.webp | Bin 0 -> 19436 bytes src/codec/SkWebpCodec.cpp | 38 +++++++++++---- src/codec/SkWebpCodec.h | 2 +- tests/ColorSpaceTest.cpp | 66 +++++++++++++------------- 7 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 resources/webp-color-profile-crash.webp create mode 100644 resources/webp-color-profile-lossless.webp create mode 100644 resources/webp-color-profile-lossy-alpha.webp create mode 100644 resources/webp-color-profile-lossy.webp diff --git a/resources/webp-color-profile-crash.webp b/resources/webp-color-profile-crash.webp new file mode 100644 index 0000000000..3b0904e0f2 Binary files /dev/null and b/resources/webp-color-profile-crash.webp differ diff --git a/resources/webp-color-profile-lossless.webp b/resources/webp-color-profile-lossless.webp new file mode 100644 index 0000000000..4fd63d5794 Binary files /dev/null and b/resources/webp-color-profile-lossless.webp differ diff --git a/resources/webp-color-profile-lossy-alpha.webp b/resources/webp-color-profile-lossy-alpha.webp new file mode 100644 index 0000000000..1a13084e77 Binary files /dev/null and b/resources/webp-color-profile-lossy-alpha.webp differ diff --git a/resources/webp-color-profile-lossy.webp b/resources/webp-color-profile-lossy.webp new file mode 100644 index 0000000000..fdff0a9941 Binary files /dev/null and b/resources/webp-color-profile-lossy.webp differ diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp index e4341421bb..c28d077bb3 100644 --- a/src/codec/SkWebpCodec.cpp +++ b/src/codec/SkWebpCodec.cpp @@ -18,6 +18,7 @@ // If moving libwebp out of skia source tree, path for webp headers must be // updated accordingly. Here, we enforce using local copy in webp sub-directory. #include "webp/decode.h" +#include "webp/demux.h" #include "webp/encode.h" bool SkWebpCodec::IsWebp(const void* buf, size_t bytesRead) { @@ -97,18 +98,35 @@ SkCodec* SkWebpCodec::NewFromStream(SkStream* stream) { return nullptr; } + // FIXME (msarett): + // Temporary strategy for getting ICC profiles from webps. Once the incremental decoding + // API lands, we will use the WebPDemuxer to manage the entire decode. + sk_sp colorSpace = nullptr; + const void* memory = stream->getMemoryBase(); + if (memory) { + WebPData data = { (const uint8_t*) memory, stream->getLength() }; + WebPDemuxState state; + SkAutoTCallVProc demux(WebPDemuxPartial(&data, &state)); + + WebPChunkIterator chunkIterator; + SkAutoTCallVProc autoCI(&chunkIterator); + if (demux && WebPDemuxGetChunk(demux, "ICCP", 1, &chunkIterator)) { + colorSpace = SkColorSpace::NewICC(chunkIterator.chunk.bytes, chunkIterator.chunk.size); + } + } + + if (!colorSpace) { + colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); + } + SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, 8); - return new SkWebpCodec(features.width, features.height, info, streamDeleter.release()); + return new SkWebpCodec(features.width, features.height, info, colorSpace, + streamDeleter.release()); } // This version is slightly different from SkCodecPriv's version of conversion_possible. It // supports both byte orders for 8888. static bool webp_conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) { - // FIXME: skbug.com/4895 - // Currently, we ignore the SkColorProfileType on the SkImageInfo. We - // will treat the encoded data as linear regardless of what the client - // requests. - if (!valid_alpha(dst.alphaType(), src.alphaType())) { return false; } @@ -271,7 +289,7 @@ SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, } } -SkWebpCodec::SkWebpCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream) - // The spec says an unmarked image is sRGB, so we return that space here. - // TODO: Add support for parsing ICC profiles from webps. - : INHERITED(width, height, info, stream, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)) {} +SkWebpCodec::SkWebpCodec(int width, int height, const SkEncodedInfo& info, + sk_sp colorSpace, SkStream* stream) + : INHERITED(width, height, info, stream, colorSpace) +{} diff --git a/src/codec/SkWebpCodec.h b/src/codec/SkWebpCodec.h index 908bf2cd4f..6fda7c2824 100644 --- a/src/codec/SkWebpCodec.h +++ b/src/codec/SkWebpCodec.h @@ -34,7 +34,7 @@ protected: bool onGetValidSubset(SkIRect* /* desiredSubset */) const override; private: - SkWebpCodec(int width, int height, const SkEncodedInfo&, SkStream*); + SkWebpCodec(int width, int height, const SkEncodedInfo&, sk_sp, SkStream*); typedef SkCodec INHERITED; }; diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp index 393d75310b..3eb145b2e8 100644 --- a/tests/ColorSpaceTest.cpp +++ b/tests/ColorSpaceTest.cpp @@ -21,9 +21,9 @@ static void test_space(skiatest::Reporter* r, SkColorSpace* space, const float red[], const float green[], const float blue[], const SkColorSpace::GammaNamed expectedGamma) { + REPORTER_ASSERT(r, nullptr != space); REPORTER_ASSERT(r, expectedGamma == space->gammaNamed()); - const SkMatrix44& mat = space->xyz(); const float src[] = { 1, 0, 0, 1, @@ -39,23 +39,15 @@ static void test_space(skiatest::Reporter* r, SkColorSpace* space, } } -const float g_sRGB_XYZ[] = { 0.4358f, 0.2224f, 0.0139f, // R - 0.3853f, 0.7170f, 0.0971f, // G - 0.1430f, 0.0606f, 0.7139f }; // B - -DEF_TEST(ColorSpace_sRGB, r) { - test_space(r, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).get(), - g_sRGB_XYZ, &g_sRGB_XYZ[3], &g_sRGB_XYZ[6], SkColorSpace::kSRGB_GammaNamed); - -} - static SkStreamAsset* resource(const char path[]) { SkString fullPath = GetResourcePath(path); return SkStream::NewFromFile(fullPath.c_str()); } -DEF_TEST(ColorSpaceParsePngICCProfile, r) { - SkAutoTDelete stream(resource("color_wheel_with_profile.png")); +static void test_path(skiatest::Reporter* r, const char* path, + const float red[], const float green[], const float blue[], + const SkColorSpace::GammaNamed expectedGamma) { + SkAutoTDelete stream(resource(path)); REPORTER_ASSERT(r, nullptr != stream); if (!stream) { return; @@ -63,36 +55,44 @@ DEF_TEST(ColorSpaceParsePngICCProfile, r) { SkAutoTDelete codec(SkCodec::NewFromStream(stream.release())); REPORTER_ASSERT(r, nullptr != codec); + if (!codec) { + return; + } -#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6) SkColorSpace* colorSpace = codec->getInfo().colorSpace(); - REPORTER_ASSERT(r, nullptr != colorSpace); - - test_space(r, colorSpace, &g_sRGB_XYZ[0], &g_sRGB_XYZ[3], &g_sRGB_XYZ[6], - SkColorSpace::kSRGB_GammaNamed); -#endif + test_space(r, colorSpace, red, green, blue, expectedGamma); } -DEF_TEST(ColorSpaceParseJpegICCProfile, r) { - SkAutoTDelete stream(resource("icc-v2-gbr.jpg")); - REPORTER_ASSERT(r, nullptr != stream); - if (!stream) { - return; - } +const float g_sRGB_XYZ[] = { 0.4358f, 0.2224f, 0.0139f, // R + 0.3853f, 0.7170f, 0.0971f, // G + 0.1430f, 0.0606f, 0.7139f }; // B - SkAutoTDelete codec(SkCodec::NewFromStream(stream.release())); - REPORTER_ASSERT(r, nullptr != codec); - if (!codec) { - return; - } +DEF_TEST(ColorSpace_sRGB, r) { + test_space(r, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).get(), + g_sRGB_XYZ, &g_sRGB_XYZ[3], &g_sRGB_XYZ[6], SkColorSpace::kSRGB_GammaNamed); - SkColorSpace* colorSpace = codec->getInfo().colorSpace(); - REPORTER_ASSERT(r, nullptr != colorSpace); +} + +DEF_TEST(ColorSpaceParseICCProfiles, r) { + +#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6) + test_path(r, "color_wheel_with_profile.png", &g_sRGB_XYZ[0], &g_sRGB_XYZ[3], &g_sRGB_XYZ[6], + SkColorSpace::kSRGB_GammaNamed); +#endif const float red[] = { 0.385117f, 0.716904f, 0.0970612f }; const float green[] = { 0.143051f, 0.0606079f, 0.713913f }; const float blue[] = { 0.436035f, 0.222488f, 0.013916f }; - test_space(r, colorSpace, red, green, blue, SkColorSpace::k2Dot2Curve_GammaNamed); + test_path(r, "icc-v2-gbr.jpg", red, green, blue, SkColorSpace::k2Dot2Curve_GammaNamed); + + test_path(r, "webp-color-profile-crash.webp", + red, green, blue, SkColorSpace::kNonStandard_GammaNamed); + test_path(r, "webp-color-profile-lossless.webp", + red, green, blue, SkColorSpace::kNonStandard_GammaNamed); + test_path(r, "webp-color-profile-lossy.webp", + red, green, blue, SkColorSpace::kNonStandard_GammaNamed); + test_path(r, "webp-color-profile-lossy-alpha.webp", + red, green, blue, SkColorSpace::kNonStandard_GammaNamed); } DEF_TEST(ColorSpaceSRGBCompare, r) { -- cgit v1.2.3