Changed alpha mask scaling to use Lanczos.
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / portable / alpha-mask.cpp
index e930fc6..3fdb96d 100644 (file)
@@ -17,6 +17,8 @@
 #include "pixel-manipulation.h"
 #include "alpha-mask.h"
 #include "pixel-buffer-impl.h"
+#include <dali/public-api/images/image-operations.h> // For ImageDimensions
+#include <platform-abstractions/portable/image-operations.h>
 
 namespace Dali
 {
@@ -25,23 +27,41 @@ namespace Internal
 namespace Adaptor
 {
 
-
-void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
+PixelBufferPtr ResizeMask( const PixelBuffer& inMask, ImageDimensions outDimensions )
 {
-  const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight());
-  const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ;
+  PixelBufferPtr mask;
+
+  if( inMask.GetWidth() != outDimensions.GetWidth() || inMask.GetHeight() != outDimensions.GetHeight() )
+  {
+    mask = PixelBuffer::New( outDimensions.GetWidth(), outDimensions.GetHeight(), inMask.GetPixelFormat() );
+    ImageDimensions inDimensions( inMask.GetWidth(), inMask.GetHeight() );
 
-  int numSamples = 1;
-  if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() )
+    if( Pixel::GetBytesPerPixel( inMask.GetPixelFormat() ) == 4 )
+    {
+      Dali::Internal::Platform::LanczosSample4BPP( inMask.GetBuffer(), inDimensions,
+                                                   mask->GetBuffer(), outDimensions );
+    }
+    else if( inMask.GetPixelFormat() == Pixel::L8 )
+    {
+      Dali::Internal::Platform::LanczosSample1BPP( inMask.GetBuffer(), inDimensions,
+                                                   mask->GetBuffer(), outDimensions );
+    }
+  }
+  else
   {
-    numSamples = 4;
+    mask = const_cast<PixelBuffer*>(&inMask);
   }
+  return mask;
+}
 
+void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& inMask )
+{
   int srcAlphaByteOffset=0;
   int srcAlphaMask=0;
-  Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
+  Dali::Pixel::Format srcPixelFormat = inMask.GetPixelFormat();
+
+  PixelBufferPtr mask = ResizeMask( inMask, ImageDimensions( buffer.GetWidth(), buffer.GetHeight() ) );
 
-  Channel alphaChannel = ALPHA;
   if( Pixel::HasAlpha(srcPixelFormat) )
   {
     Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
@@ -49,7 +69,6 @@ void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
   else if( srcPixelFormat == Pixel::L8 )
   {
     srcAlphaMask=0xFF;
-    alphaChannel = LUMINANCE;
   }
 
   int destAlphaByteOffset=0;
@@ -57,8 +76,7 @@ void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
   Dali::Pixel::GetAlphaOffsetAndMask( buffer.GetPixelFormat(), destAlphaByteOffset, destAlphaMask );
 
   unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
-  int srcStride = mask.GetWidth() * srcBytesPerPixel;
-  unsigned char* srcBuffer = mask.GetBuffer();
+  unsigned char* srcBuffer = mask->GetBuffer();
   unsigned char* destBuffer = buffer.GetBuffer();
 
   unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() );
@@ -72,16 +90,8 @@ void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
   {
     for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
     {
-      if( numSamples == 1 )
-      {
-        srcOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
-        unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
-        srcAlphaValue = float(alpha)/255.0f;
-      }
-      else
-      {
-        srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel );
-      }
+      unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
+      srcAlphaValue = float(alpha)/255.0f;
 
       unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
       float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
@@ -89,27 +99,20 @@ void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
       destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
       destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
 
+      srcOffset  += srcBytesPerPixel;
       destOffset += destBytesPerPixel;
     }
   }
 }
 
-PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask )
+PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& inMask )
 {
-  const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight());
-  const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ;
-
-  int numSamples = 1;
-  if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() )
-  {
-    numSamples = 4;
-  }
-
   // Set up source alpha offsets
   int srcAlphaByteOffset=0;
   int srcAlphaMask=0;
-  Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
-  Channel alphaChannel = ALPHA;
+  Dali::Pixel::Format srcPixelFormat = inMask.GetPixelFormat();
+
+  PixelBufferPtr mask = ResizeMask( inMask, ImageDimensions( buffer.GetWidth(), buffer.GetHeight() ) );
   if( Pixel::HasAlpha(srcPixelFormat) )
   {
     Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
@@ -117,12 +120,10 @@ PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuff
   else if( srcPixelFormat == Pixel::L8 )
   {
     srcAlphaMask=0xFF;
-    alphaChannel = LUMINANCE;
   }
 
   unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
-  int srcStride = mask.GetWidth() * srcBytesPerPixel;
-  unsigned char* srcBuffer = mask.GetBuffer();
+  unsigned char* srcBuffer = mask->GetBuffer();
 
   // Set up source color offsets
   Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
@@ -138,7 +139,6 @@ PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuff
   PixelBufferPtr newPixelBuffer = PixelBuffer::New( buffer.GetWidth(), buffer.GetHeight(),
                                                     destPixelFormat );
   unsigned char* destBuffer = newPixelBuffer->GetBuffer();
-
   unsigned char* oldBuffer = buffer.GetBuffer();
 
   int srcAlphaOffset=0;
@@ -153,16 +153,8 @@ PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuff
   {
     for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
     {
-      if( numSamples == 1 )
-      {
-        srcAlphaOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
-        unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
-        srcAlphaValue = float(alpha)/255.0f;
-      }
-      else
-      {
-        srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel );
-      }
+      unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
+      srcAlphaValue = float(alpha)/255.0f;
 
       ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset );
 
@@ -181,6 +173,7 @@ PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuff
       destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
 
       srcColorOffset += srcColorBytesPerPixel;
+      srcAlphaOffset += srcBytesPerPixel;
       destOffset += destBytesPerPixel;
     }
   }
@@ -188,56 +181,6 @@ PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuff
   return newPixelBuffer;
 }
 
-
-float ReadWeightedSample( unsigned char* buffer, Pixel::Format pixelFormat, int stride, float x, float y, int width, int height, Channel alphaChannel )
-{
-  int srcRow = floorf( y );
-  int srcCol = floorf( x );
-
-  int bytesPerPixel = Dali::Pixel::GetBytesPerPixel( pixelFormat );
-  int srcOffset = srcRow * stride + srcCol * bytesPerPixel;
-  float samples[4];
-
-  samples[0] = ReadChannel( buffer + srcOffset, pixelFormat, alphaChannel );
-
-  if( srcCol < width-1 )
-  {
-    samples[1] = ReadChannel( buffer + srcOffset+bytesPerPixel, pixelFormat, alphaChannel );
-  }
-  else
-  {
-    samples[1] = samples[0];
-  }
-
-  if( srcRow < height-1 )
-  {
-    samples[2] = ReadChannel( buffer + stride + srcOffset, pixelFormat, alphaChannel );
-  }
-  else
-  {
-    samples[2] = samples[0];
-  }
-
-  if( srcRow < height-1 && srcCol < width-1 )
-  {
-    samples[3] = ReadChannel( buffer + stride + srcOffset + bytesPerPixel, pixelFormat, alphaChannel );
-  }
-  else
-  {
-    samples[3] = samples[2];
-  }
-
-  // Bilinear interpolation:
-  float weight[4];
-  weight[0] = float(srcRow+1.0f) - y;
-  weight[1] = y - float(srcRow);
-  weight[2] = float(srcCol+1.0f) - x;
-  weight[3] = x - float(srcCol);
-
-  return ( weight[2] * (samples[0] * weight[0] + samples[1] * weight[1]) +
-           weight[3] * (samples[2] * weight[0] + samples[3] * weight[1]) ) / 255.0f;
-}
-
 } //namespace Adaptor
 
 }// namespace Internal