Fast apply alpha 95/275095/3
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 16 May 2022 12:56:46 +0000 (21:56 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Wed, 18 May 2022 05:19:04 +0000 (14:19 +0900)
Use bit-operation only during calculation x * y / 255.
It will increase performance a little

Change-Id: I91f39bb9f572486a6b2a00501edd73b921e3bf84
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali/internal/imaging/common/alpha-mask.cpp
dali/internal/imaging/common/image-operations.h
dali/internal/imaging/common/pixel-buffer-impl.cpp

index 9abdfec..276751a 100644 (file)
@@ -18,7 +18,7 @@
 #include <dali/internal/imaging/common/image-operations.h>
 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
 #include <dali/internal/imaging/common/pixel-manipulation.h>
-#include <dali/public-api/images/image-operations.h> // For ImageDimensions
+#include <dali/public-api/images/image-operations.h> // For ImageDimensions and MultiplyAndNormalizeColor
 
 namespace Dali
 {
@@ -85,7 +85,7 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
               for(const Channel& channel : validChannelList)
               {
                 auto color = ReadChannel(destBuffer + destOffset, destPixelFormat, channel);
-                WriteChannel(destBuffer + destOffset, destPixelFormat, channel, color * srcAlpha / 255);
+                WriteChannel(destBuffer + destOffset, destPixelFormat, channel, Platform::MultiplyAndNormalizeColor(color, srcAlpha));
               }
             }
             else
@@ -112,10 +112,10 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
 
       for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
       {
-        unsigned char srcAlpha  = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
-        unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
+        uint8_t srcAlpha  = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
+        uint8_t destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
 
-        destAlpha = (static_cast<std::uint16_t>(destAlpha) * static_cast<std::uint16_t>(srcAlpha)) / 255;
+        destAlpha = Platform::MultiplyAndNormalizeColor(srcAlpha, destAlpha);
 
         destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
         destBuffer[destOffset + destAlphaByteOffset] |= (destAlpha & destAlphaMask);
@@ -184,7 +184,7 @@ PixelBufferPtr CreateNewMaskedBuffer(const PixelBuffer& buffer, const PixelBuffe
       if(hasAlpha)
       {
         destAlpha = ConvertAlphaChannelToA8(oldBuffer, srcColorOffset, srcColorPixelFormat);
-        destAlpha = (static_cast<std::uint16_t>(destAlpha) * static_cast<std::uint16_t>(srcAlpha)) / 255;
+        destAlpha = Platform::MultiplyAndNormalizeColor(srcAlpha, destAlpha);
       }
       else
       {
index fd330a0..57d1255 100644 (file)
@@ -694,6 +694,19 @@ inline unsigned int BilinearFilter1Component(unsigned int tl, unsigned int tr, u
   return rounded;
 }
 
+/**
+ * @brief Fast multiply & divide by 255. It wiil be useful when we applying alpha value in color
+ *
+ * @param x The value between [0..255]
+ * @param y The value between [0..255]
+ * @return (x*y)/255
+ */
+inline uint8_t MultiplyAndNormalizeColor(const uint8_t& x, const uint8_t& y) noexcept
+{
+  const uint32_t xy = static_cast<const uint32_t>(x) * y;
+  return ((xy << 15) + (xy << 7) + xy) >> 23;
+}
+
 /**@}*/
 
 } /* namespace Platform */
index f2594ac..533db68 100644 (file)
@@ -486,7 +486,7 @@ void PixelBuffer::MultiplyColorByAlpha()
               for(const Channel& channel : validChannelList)
               {
                 auto color = ReadChannel(&pixel[x], mPixelFormat, channel);
-                WriteChannel(&pixel[x], mPixelFormat, channel, color * alpha / 255);
+                WriteChannel(&pixel[x], mPixelFormat, channel, Platform::MultiplyAndNormalizeColor(color, alpha));
               }
             }
             else