Chromium Code Reviews| Index: Source/core/platform/image-decoders/ImageDecoder.h |
| diff --git a/Source/core/platform/image-decoders/ImageDecoder.h b/Source/core/platform/image-decoders/ImageDecoder.h |
| index 724e27c918dc3e3c7a5dcd00f2ef98bfa3cd2aeb..27b08a61eee9d8eac74be358be5db3e19994b723 100644 |
| --- a/Source/core/platform/image-decoders/ImageDecoder.h |
| +++ b/Source/core/platform/image-decoders/ImageDecoder.h |
| @@ -178,7 +178,125 @@ namespace WebCore { |
| *dest = SkPackARGB32NoCheck(a, r, g, b); |
| } |
| + inline void fillRowFromRGBSource(int rowIndex, const unsigned char* src) |
|
Peter Kasting
2013/06/01 01:22:12
I don't think we gain much from having these first
|
| + { |
| + fillRowFromRGBSource(getAddr(0, rowIndex), src, width()); |
| + } |
| + |
| + inline void fillRowFromRGBASource(int rowIndex, const unsigned char* src) |
| + { |
| + bool dummy; |
| + fillRowFromRGBASource<false>(getAddr(0, rowIndex), src, width(), dummy); |
| + } |
| + |
| + inline void fillRowFromRGBASourceWithNonTrivialAlphaDetection(int rowIndex, const unsigned char *src, bool& hasNonTrivialAlpha) |
| + { |
| + fillRowFromRGBASource<true>(getAddr(0, rowIndex), src, width(), hasNonTrivialAlpha); |
| + } |
| + |
| + inline void fillRowFromInvertedCMYK(int rowIndex, const unsigned char* src) |
| + { |
| + fillRowFromInvertedCMYK(getAddr(0, rowIndex), src, width()); |
| + } |
| + |
| private: |
| + // We have specialized fill functions for each case. This way we avoid branches in the loop which gives performace. |
| + // Note: we could benefit further from turning on auto vectorization in the compiler. |
| + |
| + ALWAYS_INLINE static void fillRowFromRGBSource(PixelData* dst, const unsigned char* src, int numPixels) |
| + { |
| + const unsigned char* pixel = src; |
| + for (int i = 0; i < numPixels; ++i, pixel += 3) |
| + dst[i] = SkPackARGB32NoCheck(255, pixel[0], pixel[1], pixel[2]); |
| + } |
| + |
| + template <bool shouldUpdate> |
| + inline static void updateAlphaMask(unsigned char alpha, unsigned char& mask) |
|
Peter Kasting
2013/06/01 01:22:12
Nit: Honestly, I'm not convinced pulling this into
|
| + { |
| + if (shouldUpdate) |
| + mask &= alpha; |
| + } |
| + |
| + template <bool shouldUpdateAlphaMask> |
| + ALWAYS_INLINE static void fillRowFromRGBASourceNoPremultiply(PixelData* dst, const unsigned char* src, int numPixels, unsigned char& alphaMask) |
| + { |
| + const unsigned char* pixel = src; |
| + for (int i = 0; i < numPixels; ++i, pixel += 4) { |
| + unsigned char alpha = pixel[3]; |
| + dst[i] = SkPackARGB32NoCheck(alpha, pixel[0], pixel[1], pixel[2]); |
| + updateAlphaMask<shouldUpdateAlphaMask>(alpha, alphaMask); |
| + } |
| + } |
| + |
| + template <bool shouldUpdateAlphaMask> |
| + ALWAYS_INLINE static void fillRowFromRGBASourcePremultiply(PixelData* dst, const unsigned char* src, int numPixels, unsigned char& alphaMask) |
| + { |
| + const unsigned char* pixel = src; |
| + for (int i = 0; i < numPixels; ++i, pixel += 4) { |
| + unsigned char r = pixel[0]; |
| + unsigned char g = pixel[1]; |
| + unsigned char b = pixel[2]; |
| + unsigned char a = pixel[3]; |
| + |
| + updateAlphaMask<shouldUpdateAlphaMask>(a, alphaMask); |
| + |
| + // Note: if once we start using auto vectorization we should reevaluate whether the fast paths are |
| + // worthwile when alpha is zero or 255. Currently without vectorization they are. |
| + if (!a) { |
| + dst[i] = 0; |
| + continue; |
| + } |
| + if (a < 255) { |
| + unsigned alphaMult = a * fixPointMult; |
| + r = fixPointUnsignedMultiply(r, alphaMult); |
| + g = fixPointUnsignedMultiply(g, alphaMult); |
| + b = fixPointUnsignedMultiply(b, alphaMult); |
| + } |
| + dst[i] = SkPackARGB32NoCheck(a, r, g, b); |
| + } |
| + } |
| + |
| + template <bool shouldUpdateHasNonTrivialAlpha> |
| + ALWAYS_INLINE void fillRowFromRGBASource(PixelData* dst, const unsigned char* src, int numPixels, bool& hasNonTrivialAlpha) |
|
Peter Kasting
2013/06/01 01:22:12
Nit: If you take a bool* as the last arg, we can p
|
| + { |
| + unsigned char alphaMask = 255; |
| + if (m_premultiplyAlpha) |
| + fillRowFromRGBASourcePremultiply<shouldUpdateHasNonTrivialAlpha>(dst, src, numPixels, alphaMask); |
| + else |
| + fillRowFromRGBASourceNoPremultiply<shouldUpdateHasNonTrivialAlpha>(dst, src, numPixels, alphaMask); |
| + |
| + if (shouldUpdateHasNonTrivialAlpha) |
| + hasNonTrivialAlpha = alphaMask != 255; |
| + } |
| + |
| + ALWAYS_INLINE static void fillRowFromInvertedCMYK(PixelData* dst, const unsigned char* src, int numPixels) |
| + { |
| + // Source is 'Inverted CMYK', output is RGB. |
| + // See: http://www.easyrgb.com/math.php?MATH=M12#text12 |
| + // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb |
| + // From CMYK to CMY: |
| + // X = X * (1 - K ) + K [for X = C, M, or Y] |
| + // Thus, from Inverted CMYK to CMY is: |
| + // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK |
| + // From CMY (0..1) to RGB (0..1): |
| + // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] |
| + |
| + const unsigned char* pixel = src; |
| + for (int i = 0; i < numPixels; ++i, pixel += 4) { |
| + unsigned char c = pixel[0]; |
| + unsigned char m = pixel[1]; |
| + unsigned char y = pixel[2]; |
| + unsigned char k = pixel[3]; |
| + |
| + unsigned kMult = k * fixPointMult; |
| + c = fixPointUnsignedMultiply(c, kMult); |
| + m = fixPointUnsignedMultiply(m, kMult); |
| + y = fixPointUnsignedMultiply(y, kMult); |
| + |
| + dst[i] = SkPackARGB32NoCheck(255, c, m, y); |
|
Peter Kasting
2013/06/01 01:22:12
It strikes me that this function is effectively id
|
| + } |
| + } |
| + |
| int width() const |
| { |
| return m_bitmap->bitmap().width(); |