Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Unified Diff: src/codec/SkPngCodec.cpp

Issue 1726823002: Set SkColorSpace object for PNGs and parse ICC profiles (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Add fColorProfile to SkCodec Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/codec/SkPngCodec.cpp
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index f946876af2734dd7f660066d68efaa0e91585363..23e205ebb2db463cb9beb8b1b59f807c5eaf5bf5 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -187,7 +187,8 @@ bool SkPngCodec::IsPng(const char* buf, size_t bytesRead) {
// If it returns false, the passed in fields (except stream) are unchanged.
static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
png_structp* png_ptrp, png_infop* info_ptrp,
- SkImageInfo* imageInfo, int* bitDepthPtr, int* numberPassesPtr) {
+ SkImageInfo* imageInfo, int* bitDepthPtr, int* numberPassesPtr,
+ SkColorSpace** colorSpace) {
scroggo 2016/02/24 13:58:12 add a comment for colorSpace?
msarett 2016/02/24 17:32:35 Done.
// The image is known to be a PNG. Decode enough to know the SkImageInfo.
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
sk_error_fn, sk_warning_fn);
@@ -310,6 +311,76 @@ static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
*numberPassesPtr = numberPasses;
}
+ // iCCP variables
scroggo 2016/02/24 13:58:12 Can you move these variables closer to where they'
msarett 2016/02/24 17:32:35 Done.
+ png_charp name;
+ int compression;
+ png_bytep profile;
+ png_uint_32 length;
+
+ // cHRM variables
+ png_fixed_point XYZ[9];
+ SkFloat3x3 toXYZD50;
+
+ // gAMA variables
+ png_fixed_point gamma;
+ SkFloat3 gammas;
+
+ if (colorSpace) {
+ // First check for an ICC profile
+ if (PNG_INFO_iCCP == png_get_iCCP(png_ptr, info_ptr, &name, &compression, &profile,
+ &length)) {
+
+ // Compression can only ever be "deflate", so this is uninteresting.
+ // Could knowing the name of the profile ever be interesting? Maybe for debugging?
+ *colorSpace = SkColorSpace::NewICC(profile, length);
+
+ // Second, check for sRGB.
+ } else if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) {
+
+ // Here we are ignoring the sRGB "intent". Should we use the "intent"?
+ *colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+
+ // Next, check for chromaticities.
+ } else if (png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &XYZ[0], &XYZ[1], &XYZ[2], &XYZ[3],
+ &XYZ[4], &XYZ[5], &XYZ[6], &XYZ[7], &XYZ[8])) {
+
+ // This could be wrong. I don't see any guarantee from the PNG specification that
+ // these XYZ values will be D50. In fact, libpng will set its XYZ values to D65
+ // values if it sees an sRGB chunk.
+ for (int i = 0; i < 9; i++) {
+ toXYZD50.fMat[i] = ((float) XYZ[i]) * 0.00001f;
+ }
+
+ if (!(PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma))) {
+ // If the image does not specify gamma, let's choose our own default.
+ // What should the default be? Instead of choosing a default, should
+ // we just give up on the color profile?
+ gamma = 0;
msarett 2016/02/24 01:01:11 I need to figure out the gamma value that means "l
+ }
+ gammas.fVec[0] = gammas.fVec[1] = gammas.fVec[2] = ((float) gamma) * 0.00001f;
+
+ *colorSpace = SkColorSpace::NewRGB(toXYZD50, gammas);
+
+ // Last, check for gamma.
+ } else if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) {
+
+ // Guess a default value for cHRM? Or should we just give up?
+ for (int i = 0; i < 9; i++) {
+ toXYZD50.fMat[i] = 0.0f;
msarett 2016/02/24 01:01:11 I need to figure out a default for cHRM.
+ }
+
+ // Set the gammas.
+ gammas.fVec[0] = gammas.fVec[1] = gammas.fVec[2] = ((float) gamma) * 0.00001f;
+
+ *colorSpace = SkColorSpace::NewRGB(toXYZD50, gammas);
+ }
+
+ // Finally, what should we do if there is no color space information in the PNG?
+ // The specification says that this indicates "gamma is unknown" and that the
+ // "color is device dependent". I'm assuming we can represent this with NULL.
+ // But should we guess sRGB? Are most images intended to be sRGB?
scroggo 2016/02/24 13:58:12 According to the W3C, "untagged" images should be
msarett 2016/02/24 17:32:35 I'm leaving this as is, in case we want to treat t
+ }
+
SkColorProfileType profileType = kLinear_SkColorProfileType;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) {
profileType = kSRGB_SkColorProfileType;
@@ -330,8 +401,9 @@ static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
}
SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, SkPngChunkReader* chunkReader,
- png_structp png_ptr, png_infop info_ptr, int bitDepth, int numberPasses)
- : INHERITED(info, stream)
+ png_structp png_ptr, png_infop info_ptr, int bitDepth, int numberPasses,
+ SkColorSpace* colorSpace)
+ : INHERITED(info, stream, colorSpace)
, fPngChunkReader(SkSafeRef(chunkReader))
, fPng_ptr(png_ptr)
, fInfo_ptr(info_ptr)
@@ -434,7 +506,7 @@ bool SkPngCodec::onRewind() {
png_structp png_ptr;
png_infop info_ptr;
if (!read_header(this->stream(), fPngChunkReader.get(), &png_ptr, &info_ptr,
- nullptr, nullptr, nullptr)) {
+ nullptr, nullptr, nullptr, nullptr)) {
return false;
}
@@ -541,8 +613,9 @@ uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const {
class SkPngScanlineDecoder : public SkPngCodec {
public:
SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream,
- SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr, int bitDepth)
- : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1)
+ SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr, int bitDepth,
+ SkColorSpace* colorSpace)
+ : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1, colorSpace)
, fSrcRow(nullptr)
{}
@@ -607,8 +680,9 @@ class SkPngInterlacedScanlineDecoder : public SkPngCodec {
public:
SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream,
SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr,
- int bitDepth, int numberPasses)
- : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, numberPasses)
+ int bitDepth, int numberPasses, SkColorSpace* colorSpace)
+ : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, numberPasses,
+ colorSpace)
, fHeight(-1)
, fCanSkipRewind(false)
{
@@ -733,17 +807,19 @@ SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkRead
SkImageInfo imageInfo;
int bitDepth;
int numberPasses;
+ SkColorSpace* colorSpace = nullptr;
if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &imageInfo, &bitDepth,
- &numberPasses)) {
+ &numberPasses, &colorSpace)) {
return nullptr;
}
if (1 == numberPasses) {
return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader,
- png_ptr, info_ptr, bitDepth);
+ png_ptr, info_ptr, bitDepth, colorSpace);
}
return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader,
- png_ptr, info_ptr, bitDepth, numberPasses);
+ png_ptr, info_ptr, bitDepth, numberPasses,
+ colorSpace);
}
« include/codec/SkCodec.h ('K') | « src/codec/SkPngCodec.h ('k') | src/core/SkColorSpace.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698