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(); |