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

Unified Diff: third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp

Issue 2716533002: [PNGImageDecoder] Clean up readColorSpace, TODOs, cruft (Closed)
Patch Set: Remove unused transparency variables. Created 3 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
index a2ebf6cb967b33593313ca267d227800dbbf3fbe..6deba9ce22adfd250319cac12dada224f706df3d 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -54,58 +54,58 @@ PNGImageDecoder::PNGImageDecoder(AlphaOption alphaOption,
PNGImageDecoder::~PNGImageDecoder() {}
-inline float pngFixedToFloat(png_fixed_point x) {
- return ((float)x) * 0.00001f;
-}
-
inline sk_sp<SkColorSpace> readColorSpace(png_structp png, png_infop info) {
- if (png_get_valid(png, info, PNG_INFO_sRGB)) {
+ if (png_get_valid(png, info, PNG_INFO_sRGB))
return SkColorSpace::MakeSRGB();
- }
- png_charp name = nullptr;
- int compression = 0;
- png_bytep profile = nullptr;
- png_uint_32 length = 0;
- if (png_get_iCCP(png, info, &name, &compression, &profile, &length)) {
+ png_charp name;
+ int compression;
+ png_bytep profile;
+ png_uint_32 length;
+ if (png_get_iCCP(png, info, &name, &compression, &profile, &length))
return SkColorSpace::MakeICC(profile, length);
- }
png_fixed_point chrm[8];
- if (png_get_cHRM_fixed(png, info, &chrm[0], &chrm[1], &chrm[2], &chrm[3],
- &chrm[4], &chrm[5], &chrm[6], &chrm[7])) {
- SkColorSpacePrimaries primaries;
- primaries.fRX = pngFixedToFloat(chrm[2]);
- primaries.fRY = pngFixedToFloat(chrm[3]);
- primaries.fGX = pngFixedToFloat(chrm[4]);
- primaries.fGY = pngFixedToFloat(chrm[5]);
- primaries.fBX = pngFixedToFloat(chrm[6]);
- primaries.fBY = pngFixedToFloat(chrm[7]);
- primaries.fWX = pngFixedToFloat(chrm[0]);
- primaries.fWY = pngFixedToFloat(chrm[1]);
-
- SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
- if (primaries.toXYZD50(&toXYZD50)) {
- png_fixed_point gammaFixed;
- if (PNG_INFO_gAMA == png_get_gAMA_fixed(png, info, &gammaFixed)) {
- SkColorSpaceTransferFn fn;
- fn.fA = 1.0f;
- fn.fB = fn.fC = fn.fD = fn.fE = fn.fF = 0.0f;
- // This is necessary because the gAMA chunk actually stores 1/gamma.
- fn.fG = 1.0f / pngFixedToFloat(gammaFixed);
- return SkColorSpace::MakeRGB(fn, toXYZD50);
- }
-
- // Note that we only use the cHRM tag when gAMA is present. The
- // specification states that the cHRM is valid even without a gAMA
- // tag, but we cannot apply the cHRM without guessing a transfer
- // function. It's possible that we should guess sRGB transfer
- // function, given that unmarked PNGs should be treated as sRGB.
- // However, the current behavior matches Safari and Firefox.
- }
- }
-
- return nullptr;
+ if (!png_get_cHRM_fixed(png, info, &chrm[0], &chrm[1], &chrm[2], &chrm[3],
+ &chrm[4], &chrm[5], &chrm[6], &chrm[7]))
+ return nullptr;
+
+ png_fixed_point inverseGamma;
+ if (!png_get_gAMA_fixed(png, info, &inverseGamma))
+ return nullptr;
+
+ // cHRM and gAMA tags are both present. The PNG spec states that cHRM is
+ // valid even without gAMA but we cannot apply the cHRM without guessing
+ // a gAMA. Color correction is not a guessing game: match the behavior
+ // of Safari and Firefox instead (compat).
+
+ struct pngFixedToFloat {
+ explicit pngFixedToFloat(png_fixed_point value)
+ : floatValue(.00001f * value) {}
+ operator float() { return floatValue; }
+ float floatValue;
+ };
+
+ SkColorSpacePrimaries primaries;
+ primaries.fRX = pngFixedToFloat(chrm[2]);
+ primaries.fRY = pngFixedToFloat(chrm[3]);
+ primaries.fGX = pngFixedToFloat(chrm[4]);
+ primaries.fGY = pngFixedToFloat(chrm[5]);
+ primaries.fBX = pngFixedToFloat(chrm[6]);
+ primaries.fBY = pngFixedToFloat(chrm[7]);
+ primaries.fWX = pngFixedToFloat(chrm[0]);
+ primaries.fWY = pngFixedToFloat(chrm[1]);
+
+ SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
+ if (!primaries.toXYZD50(&toXYZD50))
+ return nullptr;
+
+ SkColorSpaceTransferFn fn;
+ fn.fG = 1.0f / pngFixedToFloat(inverseGamma);
+ fn.fA = 1.0f;
+ fn.fB = fn.fC = fn.fD = fn.fE = fn.fF = 0.0f;
+
+ return SkColorSpace::MakeRGB(fn, toXYZD50);
}
void PNGImageDecoder::headerAvailable() {
@@ -127,9 +127,9 @@ void PNGImageDecoder::headerAvailable() {
return;
}
- int bitDepth, colorType, interlaceType, compressionType, filterType, channels;
+ int bitDepth, colorType, interlaceType, compressionType;
png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType,
- &interlaceType, &compressionType, &filterType);
+ &interlaceType, &compressionType, nullptr);
// The options we set here match what Mozilla does.
@@ -138,12 +138,8 @@ void PNGImageDecoder::headerAvailable() {
(colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8))
png_set_expand(png);
- png_bytep trns = 0;
- int trnsCount = 0;
- if (png_get_valid(png, info, PNG_INFO_tRNS)) {
- png_get_tRNS(png, info, &trns, &trnsCount, 0);
+ if (png_get_valid(png, info, PNG_INFO_tRNS))
png_set_expand(png);
- }
if (bitDepth == 16)
png_set_strip_16(png);
@@ -154,27 +150,12 @@ void PNGImageDecoder::headerAvailable() {
if ((colorType & PNG_COLOR_MASK_COLOR) && !ignoresColorSpace()) {
// We only support color profiles for color PALETTE and RGB[A] PNG.
- // Supporting color profiles for gray-scale images is slightly tricky, at
- // least using the CoreGraphics ICC library, because we expand gray-scale
- // images to RGB but we do not similarly transform the color profile. We'd
- // either need to transform the color profile or we'd need to decode into a
- // gray-scale image buffer and hand that to CoreGraphics.
- sk_sp<SkColorSpace> colorSpace = readColorSpace(png, info);
- if (colorSpace) {
- setEmbeddedColorSpace(colorSpace);
- }
+ // TODO(msarret): Add GRAY profile support, block CYMK?
+ if (sk_sp<SkColorSpace> colorSpace = readColorSpace(png, info))
+ setEmbeddedColorSpace(std::move(colorSpace));
}
if (!hasEmbeddedColorSpace()) {
- // TODO (msarett):
- // Applying the transfer function (gamma) should be handled by
- // SkColorSpaceXform. Here we always convert to a transfer function that
- // is a 2.2 exponential. This is a little strange given that the dst
- // transfer function is not necessarily a 2.2 exponential.
- // TODO (msarett):
- // Often, PNGs that specify their transfer function with the gAMA tag will
- // also specify their gamut with the cHRM tag. We should read this tag
- // and do a full color space transformation if it is present.
const double inverseGamma = 0.45455;
const double defaultGamma = 2.2;
double gamma;
@@ -194,11 +175,11 @@ void PNGImageDecoder::headerAvailable() {
if (interlaceType == PNG_INTERLACE_ADAM7)
png_set_interlace_handling(png);
- // Update our info now.
+ // Update our info now (so we can get color channel info).
png_read_update_info(png, info);
- channels = png_get_channels(png, info);
- ASSERT(channels == 3 || channels == 4);
+ int channels = png_get_channels(png, info);
+ DCHECK(channels == 3 || channels == 4);
m_reader->setHasAlpha(channels == 4);
if (m_reader->decodingSizeOnly()) {
@@ -250,16 +231,16 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
}
/* libpng comments (here to explain what follows).
- *
- * this function is called for every row in the image. If the
- * image is interlacing, and you turned on the interlace handler,
- * this function will be called for every row in every pass.
- * Some of these rows will not be changed from the previous pass.
- * When the row is not changed, the new_row variable will be NULL.
- * The rows and passes are called in order, so you don't really
- * need the row_num and pass, but I'm supplying them because it
- * may make your life easier.
- */
+ *
+ * this function is called for every row in the image. If the
+ * image is interlacing, and you turned on the interlace handler,
+ * this function will be called for every row in every pass.
+ * Some of these rows will not be changed from the previous pass.
+ * When the row is not changed, the new_row variable will be NULL.
+ * The rows and passes are called in order, so you don't really
+ * need the row_num and pass, but I'm supplying them because it
+ * may make your life easier.
+ */
// Nothing to do if the row is unchanged, or the row is outside
// the image bounds: libpng may send extra rows, ignore them to
@@ -271,23 +252,23 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
return;
/* libpng comments (continued).
- *
- * For the non-NULL rows of interlaced images, you must call
- * png_progressive_combine_row() passing in the row and the
- * old row. You can call this function for NULL rows (it will
- * just return) and for non-interlaced images (it just does the
- * memcpy for you) if it will make the code easier. Thus, you
- * can just do this for all cases:
- *
- * png_progressive_combine_row(png_ptr, old_row, new_row);
- *
- * where old_row is what was displayed for previous rows. Note
- * that the first pass (pass == 0 really) will completely cover
- * the old row, so the rows do not have to be initialized. After
- * the first pass (and only for interlaced images), you will have
- * to pass the current row, and the function will combine the
- * old row and the new row.
- */
+ *
+ * For the non-NULL rows of interlaced images, you must call
+ * png_progressive_combine_row() passing in the row and the
+ * old row. You can call this function for NULL rows (it will
+ * just return) and for non-interlaced images (it just does the
+ * memcpy for you) if it will make the code easier. Thus, you
+ * can just do this for all cases:
+ *
+ * png_progressive_combine_row(png_ptr, old_row, new_row);
+ *
+ * where old_row is what was displayed for previous rows. Note
+ * that the first pass (pass == 0 really) will completely cover
+ * the old row, so the rows do not have to be initialized. After
+ * the first pass (and only for interlaced images), you will have
+ * to pass the current row, and the function will combine the
+ * old row and the new row.
+ */
bool hasAlpha = m_reader->hasAlpha();
png_bytep row = rowBuffer;
@@ -301,7 +282,6 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
// Write the decoded row pixels to the frame buffer. The repetitive
// form of the row write loops is for speed.
ImageFrame::PixelData* const dstRow = buffer.getAddr(0, y);
- unsigned alphaMask = 255;
int width = size().width();
png_bytep srcPtr = row;
@@ -321,26 +301,31 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
SkColorSpaceXform::kRGBA_8888_ColorFormat;
xform->apply(colorFormat, dstRow, colorFormat, srcPtr, size().width(),
kUnpremul_SkAlphaType);
- srcPtr = (png_bytep)dstRow;
+ srcPtr = png_bytep(dstRow);
}
+ unsigned alphaMask = 255;
if (buffer.premultiplyAlpha()) {
for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
- dstPixel++, srcPtr += 4) {
+ srcPtr += 4, ++dstPixel) {
buffer.setRGBAPremultiply(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2],
srcPtr[3]);
alphaMask &= srcPtr[3];
}
} else {
for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
- dstPixel++, srcPtr += 4) {
+ srcPtr += 4, ++dstPixel) {
buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], srcPtr[3]);
alphaMask &= srcPtr[3];
}
}
+
+ if (alphaMask != 255 && !buffer.hasAlpha())
+ buffer.setHasAlpha(true);
+
} else {
for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
- dstPixel++, srcPtr += 3) {
+ srcPtr += 3, ++dstPixel) {
buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], 255);
}
@@ -353,9 +338,6 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
}
}
- if (alphaMask != 255 && !buffer.hasAlpha())
- buffer.setHasAlpha(true);
-
buffer.setPixelsChanged(true);
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698