Parse ICC profiles from webps
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2269333002 Review-Url: https://codereview.chromium.org/2269333002
This commit is contained in:
parent
66933552f1
commit
9d15dab754
BIN
resources/webp-color-profile-crash.webp
Normal file
BIN
resources/webp-color-profile-crash.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
resources/webp-color-profile-lossless.webp
Normal file
BIN
resources/webp-color-profile-lossless.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
BIN
resources/webp-color-profile-lossy-alpha.webp
Normal file
BIN
resources/webp-color-profile-lossy-alpha.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
resources/webp-color-profile-lossy.webp
Normal file
BIN
resources/webp-color-profile-lossy.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@ -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<SkColorSpace> colorSpace = nullptr;
|
||||
const void* memory = stream->getMemoryBase();
|
||||
if (memory) {
|
||||
WebPData data = { (const uint8_t*) memory, stream->getLength() };
|
||||
WebPDemuxState state;
|
||||
SkAutoTCallVProc<WebPDemuxer, WebPDemuxDelete> demux(WebPDemuxPartial(&data, &state));
|
||||
|
||||
WebPChunkIterator chunkIterator;
|
||||
SkAutoTCallVProc<WebPChunkIterator, WebPDemuxReleaseChunkIterator> 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<SkColorSpace> colorSpace, SkStream* stream)
|
||||
: INHERITED(width, height, info, stream, colorSpace)
|
||||
{}
|
||||
|
@ -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<SkColorSpace>, SkStream*);
|
||||
|
||||
typedef SkCodec INHERITED;
|
||||
};
|
||||
|
@ -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,42 +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<SkStream> stream(resource("color_wheel_with_profile.png"));
|
||||
REPORTER_ASSERT(r, nullptr != stream);
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
|
||||
REPORTER_ASSERT(r, nullptr != codec);
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
DEF_TEST(ColorSpaceParseJpegICCProfile, r) {
|
||||
SkAutoTDelete<SkStream> stream(resource("icc-v2-gbr.jpg"));
|
||||
static void test_path(skiatest::Reporter* r, const char* path,
|
||||
const float red[], const float green[], const float blue[],
|
||||
const SkColorSpace::GammaNamed expectedGamma) {
|
||||
SkAutoTDelete<SkStream> stream(resource(path));
|
||||
REPORTER_ASSERT(r, nullptr != stream);
|
||||
if (!stream) {
|
||||
return;
|
||||
@ -87,12 +60,39 @@ DEF_TEST(ColorSpaceParseJpegICCProfile, r) {
|
||||
}
|
||||
|
||||
SkColorSpace* colorSpace = codec->getInfo().colorSpace();
|
||||
REPORTER_ASSERT(r, nullptr != colorSpace);
|
||||
test_space(r, colorSpace, red, green, blue, expectedGamma);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user