| 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 1f3b61204919d0f42fdf57b1ff9190d783a962f4..f440d851ddf13892d4b3dbe152e747f6c18d2051 100644
|
| --- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
|
| +++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
|
| @@ -45,9 +45,6 @@
|
| #if !defined(PNG_LIBPNG_VER_MAJOR) || !defined(PNG_LIBPNG_VER_MINOR)
|
| #error version error: compile against a versioned libpng.
|
| #endif
|
| -#if USE(QCMSLIB)
|
| -#include "qcms.h"
|
| -#endif
|
|
|
| #if PNG_LIBPNG_VER_MAJOR > 1 || \
|
| (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4)
|
| @@ -96,10 +93,6 @@ class PNGImageReader final {
|
| m_currentBufferSize(0),
|
| m_decodingSizeOnly(false),
|
| m_hasAlpha(false)
|
| -#if USE(QCMSLIB)
|
| - ,
|
| - m_rowBuffer()
|
| -#endif
|
| {
|
| m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, pngFailed, 0);
|
| m_info = png_create_info_struct(m_png);
|
| @@ -150,12 +143,6 @@ class PNGImageReader final {
|
| void createInterlaceBuffer(int size) {
|
| m_interlaceBuffer = wrapArrayUnique(new png_byte[size]);
|
| }
|
| -#if USE(QCMSLIB)
|
| - png_bytep rowBuffer() const { return m_rowBuffer.get(); }
|
| - void createRowBuffer(int size) {
|
| - m_rowBuffer = wrapArrayUnique(new png_byte[size]);
|
| - }
|
| -#endif
|
|
|
| private:
|
| png_structp m_png;
|
| @@ -166,9 +153,6 @@ class PNGImageReader final {
|
| bool m_decodingSizeOnly;
|
| bool m_hasAlpha;
|
| std::unique_ptr<png_byte[]> m_interlaceBuffer;
|
| -#if USE(QCMSLIB)
|
| - std::unique_ptr<png_byte[]> m_rowBuffer;
|
| -#endif
|
| };
|
|
|
| PNGImageDecoder::PNGImageDecoder(AlphaOption alphaOption,
|
| @@ -231,11 +215,9 @@ void PNGImageDecoder::headerAvailable() {
|
| // 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.
|
| - bool imageHasAlpha = (colorType & PNG_COLOR_MASK_ALPHA) || trnsCount;
|
| #ifdef PNG_iCCP_SUPPORTED
|
| if (png_get_valid(png, info, PNG_INFO_sRGB)) {
|
| - setColorProfileAndComputeTransform(nullptr, 0, imageHasAlpha,
|
| - true /* useSRGB */);
|
| + setColorSpaceAndComputeTransform(nullptr, 0, true /* useSRGB */);
|
| } else {
|
| char* profileName = nullptr;
|
| int compressionType = 0;
|
| @@ -247,16 +229,23 @@ void PNGImageDecoder::headerAvailable() {
|
| png_uint_32 profileLength = 0;
|
| if (png_get_iCCP(png, info, &profileName, &compressionType, &profile,
|
| &profileLength)) {
|
| - setColorProfileAndComputeTransform(reinterpret_cast<char*>(profile),
|
| - profileLength, imageHasAlpha,
|
| - false /* useSRGB */);
|
| + setColorSpaceAndComputeTransform(reinterpret_cast<char*>(profile),
|
| + profileLength, false /* useSRGB */);
|
| }
|
| }
|
| #endif // PNG_iCCP_SUPPORTED
|
| }
|
|
|
| if (!hasColorProfile()) {
|
| - // Deal with gamma and keep it under our control.
|
| + // 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;
|
| @@ -324,15 +313,6 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
|
| }
|
| }
|
|
|
| -#if USE(QCMSLIB)
|
| - if (colorTransform()) {
|
| - m_reader->createRowBuffer(colorChannels * size().width());
|
| - if (!m_reader->rowBuffer()) {
|
| - longjmp(JMPBUF(png), 1);
|
| - return;
|
| - }
|
| - }
|
| -#endif
|
| buffer.setStatus(ImageFrame::FramePartial);
|
| buffer.setHasAlpha(false);
|
|
|
| @@ -389,37 +369,63 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer,
|
| png_progressive_combine_row(m_reader->pngPtr(), row, rowBuffer);
|
| }
|
|
|
| -#if USE(QCMSLIB)
|
| - if (qcms_transform* transform = colorTransform()) {
|
| - qcms_transform_data(transform, row, m_reader->rowBuffer(), size().width());
|
| - row = m_reader->rowBuffer();
|
| - }
|
| -#endif
|
| -
|
| // Write the decoded row pixels to the frame buffer. The repetitive
|
| // form of the row write loops is for speed.
|
| - ImageFrame::PixelData* address = buffer.getAddr(0, y);
|
| + ImageFrame::PixelData* const dstRow = buffer.getAddr(0, y);
|
| unsigned alphaMask = 255;
|
| int width = size().width();
|
|
|
| - png_bytep pixel = row;
|
| + png_bytep srcPtr = row;
|
| if (hasAlpha) {
|
| +#if USE(SKCOLORXFORM)
|
| + // Here we apply the color space transformation to the dst space.
|
| + // It does not really make sense to transform to a gamma-encoded
|
| + // space and then immediately after, perform a linear premultiply.
|
| + // Ideally we would pass kPremul_SkAlphaType to xform->apply(),
|
| + // instructing SkColorSpaceXform to perform the linear premultiply
|
| + // while the pixels are a linear space.
|
| + // We cannot do this because when we apply the gamma encoding after
|
| + // the premultiply, we will very likely end up with valid pixels
|
| + // where R, G, and/or B are greater than A. The legacy drawing
|
| + // pipeline does not know how to handle this.
|
| + if (SkColorSpaceXform* xform = colorTransform()) {
|
| + SkColorSpaceXform::ColorFormat colorFormat =
|
| + SkColorSpaceXform::kRGBA_8888_ColorFormat;
|
| + xform->apply(colorFormat, dstRow, colorFormat, srcPtr, size().width(),
|
| + kUnpremul_SkAlphaType);
|
| + srcPtr = (png_bytep)dstRow;
|
| + }
|
| +#endif
|
| +
|
| if (buffer.premultiplyAlpha()) {
|
| - for (int x = 0; x < width; ++x, pixel += 4) {
|
| - buffer.setRGBAPremultiply(address++, pixel[0], pixel[1], pixel[2],
|
| - pixel[3]);
|
| - alphaMask &= pixel[3];
|
| + for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
|
| + dstPixel++, srcPtr += 4) {
|
| + buffer.setRGBAPremultiply(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2],
|
| + srcPtr[3]);
|
| + alphaMask &= srcPtr[3];
|
| }
|
| } else {
|
| - for (int x = 0; x < width; ++x, pixel += 4) {
|
| - buffer.setRGBARaw(address++, pixel[0], pixel[1], pixel[2], pixel[3]);
|
| - alphaMask &= pixel[3];
|
| + for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
|
| + dstPixel++, srcPtr += 4) {
|
| + buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], srcPtr[3]);
|
| + alphaMask &= srcPtr[3];
|
| }
|
| }
|
| } else {
|
| - for (int x = 0; x < width; ++x, pixel += 3) {
|
| - buffer.setRGBARaw(address++, pixel[0], pixel[1], pixel[2], 255);
|
| + for (auto *dstPixel = dstRow; dstPixel < dstRow + width;
|
| + dstPixel++, srcPtr += 3) {
|
| + buffer.setRGBARaw(dstPixel, srcPtr[0], srcPtr[1], srcPtr[2], 255);
|
| + }
|
| +
|
| +#if USE(SKCOLORXFORM)
|
| + // We'll apply the color space xform to opaque pixels after they have been
|
| + // written to the ImageFrame, purely because SkColorSpaceXform supports
|
| + // RGBA (and not RGB).
|
| + if (SkColorSpaceXform* xform = colorTransform()) {
|
| + xform->apply(xformColorFormat(), dstRow, xformColorFormat(), dstRow,
|
| + size().width(), kOpaque_SkAlphaType);
|
| }
|
| +#endif
|
| }
|
|
|
| if (alphaMask != 255 && !buffer.hasAlpha())
|
|
|