Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / image-operations.h
index 33f1c2d..57d1255 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-#ifndef DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_
-#define DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_
+#ifndef DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H
+#define DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H
 
 // EXTERNAL INCLUDES
 #include <stdint.h>
 
 // INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/public-api/images/image-operations.h>
 #include <third-party/resampler/resampler.h>
-#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 
 namespace Dali
 {
@@ -33,7 +33,6 @@ namespace Internal
 {
 namespace Platform
 {
-
 /**
  * @brief Identify which combination of x and y dimensions matter in terminating iterative box filtering.
  */
@@ -60,7 +59,7 @@ typedef Uint16Pair ImageDimensions;
  * @param[in] requestedDimensions Width and height of area to scale image into. Can be zero.
  * @return Dimensions of area to scale image into after special rules are applied.
  */
-ImageDimensions CalculateDesiredDimensions( ImageDimensions rawDimensions, ImageDimensions requestedDimensions );
+ImageDimensions CalculateDesiredDimensions(ImageDimensions rawDimensions, ImageDimensions requestedDimensions);
 
 /**
  * @defgroup BitmapOperations Bitmap-to-Bitmap Image operations.
@@ -81,16 +80,16 @@ ImageDimensions CalculateDesiredDimensions( ImageDimensions rawDimensions, Image
  *         bitmap passed-in, or the original bitmap passed in if the attributes
  *         have no effect.
  */
-Dali::Devel::PixelBuffer ApplyAttributesToBitmap( Dali::Devel::PixelBuffer bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode = FittingMode::DEFAULT, SamplingMode::Type samplingMode = SamplingMode::DEFAULT );
+Dali::Devel::PixelBuffer ApplyAttributesToBitmap(Dali::Devel::PixelBuffer bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode = FittingMode::DEFAULT, SamplingMode::Type samplingMode = SamplingMode::DEFAULT);
 
 /**
  * @brief Apply downscaling to a bitmap according to requested attributes.
  * @note The input bitmap pixel buffer may be modified and used as scratch working space for efficiency, so it must be discarded.
  **/
-Dali::Devel::PixelBuffer DownscaleBitmap( Dali::Devel::PixelBuffer bitmap,
-                                          ImageDimensions desired,
-                                          FittingMode::Type fittingMode,
-                                          SamplingMode::Type samplingMode );
+Dali::Devel::PixelBuffer DownscaleBitmap(Dali::Devel::PixelBuffer bitmap,
+                                         ImageDimensions          desired,
+                                         FittingMode::Type        fittingMode,
+                                         SamplingMode::Type       samplingMode);
 /**@}*/
 
 /**
@@ -108,21 +107,25 @@ Dali::Devel::PixelBuffer DownscaleBitmap( Dali::Devel::PixelBuffer bitmap,
  * @param[in]     pixelFormat The format of the image pointed at by pixels.
  * @param[in]     inputWidth The width of the input image.
  * @param[in]     inputHeight The height of the input image.
+ * @param[in]     inputStride The stride of the input image.
  * @param[in]     desiredWidth The width the client is requesting.
  * @param[in]     desiredHeight The height the client is requesting.
  * @param[out]    outWidth  The resulting width after downscaling.
  * @param[out]    outHeight The resulting height after downscaling.
- */
-void DownscaleInPlacePow2( unsigned char * const pixels,
-                           Pixel::Format pixelFormat,
-                           unsigned int inputWidth,
-                           unsigned int inputHeight,
-                           unsigned int desiredWidth,
-                           unsigned int desiredHeight,
-                           FittingMode::Type fittingMode,
-                           SamplingMode::Type samplingMode,
-                           unsigned& outWidth,
-                           unsigned& outHeight );
+ * @param[out]    outStride The resulting stride after downscaling.
+ */
+void DownscaleInPlacePow2(unsigned char* const pixels,
+                          Pixel::Format        pixelFormat,
+                          unsigned int         inputWidth,
+                          unsigned int         inputHeight,
+                          unsigned int         inputStride,
+                          unsigned int         desiredWidth,
+                          unsigned int         desiredHeight,
+                          FittingMode::Type    fittingMode,
+                          SamplingMode::Type   samplingMode,
+                          unsigned&            outWidth,
+                          unsigned&            outHeight,
+                          unsigned&            outStride);
 
 /**
  * @brief Destructive in-place downscaling by a power of 2 factor.
@@ -133,73 +136,85 @@ void DownscaleInPlacePow2( unsigned char * const pixels,
  * @param[in,out] pixels The buffer both to read from and write the result to.
  * @param[in]     inputWidth The width of the input image.
  * @param[in]     inputHeight The height of the input image.
+ * @param[in]     inputStride The stride of the input image.
  * @param[in]     desiredWidth The width the client is requesting.
  * @param[in]     desiredHeight The height the client is requesting.
  * @param[out]    outWidth  The resulting width after downscaling.
  * @param[out]    outHeight The resulting height after downscaling.
+ * @param[out]    outStride The resulting stride after downscaling.
  */
-void DownscaleInPlacePow2RGB888( unsigned char * pixels,
-                                 unsigned int inputWidth,
-                                 unsigned int inputHeight,
-                                 unsigned int desiredWidth,
-                                 unsigned int desiredHeight,
-                                 BoxDimensionTest dimensionTest,
-                                 unsigned int& outWidth,
-                                 unsigned int& outHeight );
+void DownscaleInPlacePow2RGB888(unsigned char*   pixels,
+                                unsigned int     inputWidth,
+                                unsigned int     inputHeight,
+                                unsigned int     inputStride,
+                                unsigned int     desiredWidth,
+                                unsigned int     desiredHeight,
+                                BoxDimensionTest dimensionTest,
+                                unsigned int&    outWidth,
+                                unsigned int&    outHeight,
+                                unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
  */
-void DownscaleInPlacePow2RGBA8888( unsigned char * pixels,
-                                   unsigned int inputWidth,
-                                   unsigned int inputHeight,
-                                   unsigned int desiredWidth,
-                                   unsigned int desiredHeight,
-                                   BoxDimensionTest dimensionTest,
-                                   unsigned int& outWidth,
-                                   unsigned int& outHeight );
+void DownscaleInPlacePow2RGBA8888(unsigned char*   pixels,
+                                  unsigned int     inputWidth,
+                                  unsigned int     inputHeight,
+                                  unsigned int     inputStride,
+                                  unsigned int     desiredWidth,
+                                  unsigned int     desiredHeight,
+                                  BoxDimensionTest dimensionTest,
+                                  unsigned int&    outWidth,
+                                  unsigned int&    outHeight,
+                                  unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
  *
  * For the 2-byte packed 16 bit format RGB565.
  */
-void DownscaleInPlacePow2RGB565( unsigned char * pixels,
-                                 unsigned int inputWidth,
-                                 unsigned int inputHeight,
-                                 unsigned int desiredWidth,
-                                 unsigned int desiredHeight,
-                                 BoxDimensionTest dimensionTest,
-                                 unsigned int& outWidth,
-                                 unsigned int& outHeight );
+void DownscaleInPlacePow2RGB565(unsigned char*   pixels,
+                                unsigned int     inputWidth,
+                                unsigned int     inputHeight,
+                                unsigned int     inputStride,
+                                unsigned int     desiredWidth,
+                                unsigned int     desiredHeight,
+                                BoxDimensionTest dimensionTest,
+                                unsigned int&    outWidth,
+                                unsigned int&    outHeight,
+                                unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
  *
  * For 2-byte formats such as lum8alpha8, but not packed 16 bit formats like RGB565.
  */
-void DownscaleInPlacePow2ComponentPair( unsigned char * pixels,
-                                        unsigned int inputWidth,
-                                        unsigned int inputHeight,
-                                        unsigned int desiredWidth,
-                                        unsigned int desiredHeight,
-                                        BoxDimensionTest dimensionTest,
-                                        unsigned int& outWidth,
-                                        unsigned int& outHeight );
+void DownscaleInPlacePow2ComponentPair(unsigned char*   pixels,
+                                       unsigned int     inputWidth,
+                                       unsigned int     inputHeight,
+                                       unsigned int     inputStride,
+                                       unsigned int     desiredWidth,
+                                       unsigned int     desiredHeight,
+                                       BoxDimensionTest dimensionTest,
+                                       unsigned int&    outWidth,
+                                       unsigned int&    outHeight,
+                                       unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
  *
  * For single-byte formats such as lum8 or alpha8.
  */
-void DownscaleInPlacePow2SingleBytePerPixel( unsigned char * pixels,
-                                             unsigned int inputWidth,
-                                             unsigned int inputHeight,
-                                             unsigned int desiredWidth,
-                                             unsigned int desiredHeight,
-                                             BoxDimensionTest dimensionTest,
-                                             unsigned int& outWidth,
-                                             unsigned int& outHeight );
+void DownscaleInPlacePow2SingleBytePerPixel(unsigned char*   pixels,
+                                            unsigned int     inputWidth,
+                                            unsigned int     inputHeight,
+                                            unsigned int     inputStride,
+                                            unsigned int     desiredWidth,
+                                            unsigned int     desiredHeight,
+                                            BoxDimensionTest dimensionTest,
+                                            unsigned int&    outWidth,
+                                            unsigned int&    outHeight,
+                                            unsigned int&    outStride);
 
 /**
  * @brief Rescales an input image into the exact output dimensions passed-in.
@@ -209,61 +224,66 @@ void DownscaleInPlacePow2SingleBytePerPixel( unsigned char * pixels,
  * @note inPixels is allowed to alias outPixels if this is a downscaling,
  * but not for upscaling.
  */
-void PointSample( const unsigned char * inPixels,
-                  unsigned int inputWidth,
-                  unsigned int inputHeight,
-                  Pixel::Format pixelFormat,
-                  unsigned char * outPixels,
-                  unsigned int desiredWidth,
-                  unsigned int desiredHeight );
+void PointSample(const unsigned char* inPixels,
+                 unsigned int         inputWidth,
+                 unsigned int         inputHeight,
+                 unsigned int         inputStride,
+                 Pixel::Format        pixelFormat,
+                 unsigned char*       outPixels,
+                 unsigned int         desiredWidth,
+                 unsigned int         desiredHeight);
 
 /**
  * @copydoc PointSample
  *
  * Specialised for 4-byte formats like RGBA8888 and BGRA8888.
  */
-void PointSample4BPP( const unsigned char * inPixels,
-                      unsigned int inputWidth,
-                      unsigned int inputHeight,
-                      unsigned char * outPixels,
-                      unsigned int desiredWidth,
-                      unsigned int desiredHeight );
+void PointSample4BPP(const unsigned char* inPixels,
+                     unsigned int         inputWidth,
+                     unsigned int         inputHeight,
+                     unsigned int         inputStride,
+                     unsigned char*       outPixels,
+                     unsigned int         desiredWidth,
+                     unsigned int         desiredHeight);
 
 /**
  * @copydoc PointSample
  *
  * Specialised for 3-byte formats like RGB888 and BGR888.
  */
-void PointSample3BPP( const unsigned char * inPixels,
-                      unsigned int inputWidth,
-                      unsigned int inputHeight,
-                      unsigned char * outPixels,
-                      unsigned int desiredWidth,
-                      unsigned int desiredHeight );
+void PointSample3BPP(const unsigned char* inPixels,
+                     unsigned int         inputWidth,
+                     unsigned int         inputHeight,
+                     unsigned int         inputStride,
+                     unsigned char*       outPixels,
+                     unsigned int         desiredWidth,
+                     unsigned int         desiredHeight);
 
 /**
  * @copydoc PointSample
  *
  * Specialised for 2-byte formats like LA88.
  */
-void PointSample2BPP( const unsigned char * inPixels,
-                      unsigned int inputWidth,
-                      unsigned int inputHeight,
-                      unsigned char * outPixels,
-                      unsigned int desiredWidth,
-                      unsigned int desiredHeight );
+void PointSample2BPP(const unsigned char* inPixels,
+                     unsigned int         inputWidth,
+                     unsigned int         inputHeight,
+                     unsigned int         inputStride,
+                     unsigned char*       outPixels,
+                     unsigned int         desiredWidth,
+                     unsigned int         desiredHeight);
 
 /**
  * @copydoc PointSample
  *
  * Specialised for 1-byte formats like L8 and A8.
  */
-void PointSample1BPP( const unsigned char * inPixels,
-                      unsigned int inputWidth,
-                      unsigned int inputHeight,
-                      unsigned char * outPixels,
-                      unsigned int desiredWidth,
-                      unsigned int desiredHeight );
+void PointSample1BPP(const unsigned char* inPixels,
+                     unsigned int         inputWidth,
+                     unsigned int         inputHeight,
+                     unsigned int         inputStride,
+                     unsigned char*       outPixels,
+                     unsigned int         desiredWidth,
+                     unsigned int         desiredHeight);
 
 /**
  * @brief Resample input image to output image using a bilinear filter.
@@ -273,51 +293,56 @@ void PointSample1BPP( const unsigned char * inPixels,
  * @pre inPixels must not alias outPixels. The input image should be a totally
  * separate buffer from the input one.
  */
-void LinearSample( const unsigned char * __restrict__ inPixels,
-                   ImageDimensions inDimensions,
-                   Pixel::Format pixelFormat,
-                   unsigned char * __restrict__ outPixels,
-                   ImageDimensions outDimensions );
+void LinearSample(const unsigned char* __restrict__ inPixels,
+                  ImageDimensions inDimensions,
+                  unsigned int    inStride,
+                  Pixel::Format   pixelFormat,
+                  unsigned char* __restrict__ outPixels,
+                  ImageDimensions outDimensions);
 
 /**
  * @copydoc LinearSample
  *
  * Specialised for one byte per pixel formats.
  */
-void LinearSample1BPP( const unsigned char * __restrict__ inPixels,
-                       ImageDimensions inputDimensions,
-                       unsigned char * __restrict__ outPixels,
-                       ImageDimensions desiredDimensions );
+void LinearSample1BPP(const unsigned char* __restrict__ inPixels,
+                      ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
+                      unsigned char* __restrict__ outPixels,
+                      ImageDimensions desiredDimensions);
 
 /**
  * @copydoc LinearSample
  *
  * Specialised for two byte per pixel formats.
  */
-void LinearSample2BPP( const unsigned char * __restrict__ inPixels,
-                       ImageDimensions inputDimensions,
-                       unsigned char * __restrict__ outPixels,
-                       ImageDimensions desiredDimensions );
+void LinearSample2BPP(const unsigned char* __restrict__ inPixels,
+                      ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
+                      unsigned char* __restrict__ outPixels,
+                      ImageDimensions desiredDimensions);
 
 /**
  * @copydoc LinearSample
  *
  * Specialised for RGB565 16 bit pixel format.
  */
-void LinearSampleRGB565( const unsigned char * __restrict__ inPixels,
-                       ImageDimensions inputDimensions,
-                       unsigned char * __restrict__ outPixels,
-                       ImageDimensions desiredDimensions );
+void LinearSampleRGB565(const unsigned char* __restrict__ inPixels,
+                        ImageDimensions inputDimensions,
+                        unsigned int    inputStride,
+                        unsigned char* __restrict__ outPixels,
+                        ImageDimensions desiredDimensions);
 
 /**
  * @copydoc LinearSample
  *
  * Specialised for three byte per pixel formats like RGB888.
  */
-void LinearSample3BPP( const unsigned char * __restrict__ inPixels,
-                       ImageDimensions inputDimensions,
-                       unsigned char * __restrict__ outPixels,
-                       ImageDimensions desiredDimensions );
+void LinearSample3BPP(const unsigned char* __restrict__ inPixels,
+                      ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
+                      unsigned char* __restrict__ outPixels,
+                      ImageDimensions desiredDimensions);
 
 /**
  * @copydoc LinearSample
@@ -325,10 +350,11 @@ void LinearSample3BPP( const unsigned char * __restrict__ inPixels,
  * Specialised for four byte per pixel formats like RGBA8888.
  * @note, If used on RGBA8888, the A component will be blended independently.
  */
-void LinearSample4BPP( const unsigned char * __restrict__ inPixels,
-                       ImageDimensions inputDimensions,
-                       unsigned char * __restrict__ outPixels,
-                       ImageDimensions desiredDimensions );
+void LinearSample4BPP(const unsigned char* __restrict__ inPixels,
+                      ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
+                      unsigned char* __restrict__ outPixels,
+                      ImageDimensions desiredDimensions);
 
 /**
  * @brief Resamples the input image with the Lanczos algorithm.
@@ -338,13 +364,15 @@ void LinearSample4BPP( const unsigned char * __restrict__ inPixels,
  *
  * @param[in] inPixels Pointer to the input image buffer.
  * @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride of the image.
  * @param[out] outPixels Pointer to the output image buffer.
  * @param[in] desiredDimensions The output dimensions of the image.
  */
-void LanczosSample4BPP( const unsigned char * __restrict__ inPixels,
-                        ImageDimensions inputDimensions,
-                        unsigned char * __restrict__ outPixels,
-                        ImageDimensions desiredDimensions );
+void LanczosSample4BPP(const unsigned char* __restrict__ inPixels,
+                       ImageDimensions inputDimensions,
+                       unsigned int    inputStride,
+                       unsigned char* __restrict__ outPixels,
+                       ImageDimensions desiredDimensions);
 
 /**
  * @brief Resamples the input image with the Lanczos algorithm.
@@ -354,13 +382,15 @@ void LanczosSample4BPP( const unsigned char * __restrict__ inPixels,
  *
  * @param[in] inPixels Pointer to the input image buffer.
  * @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride of the image.
  * @param[out] outPixels Pointer to the output image buffer.
  * @param[in] desiredDimensions The output dimensions of the image.
  */
-void LanczosSample1BPP( const unsigned char * __restrict__ inPixels,
-                        ImageDimensions inputDimensions,
-                        unsigned char * __restrict__ outPixels,
-                        ImageDimensions desiredDimensions );
+void LanczosSample1BPP(const unsigned char* __restrict__ inPixels,
+                       ImageDimensions inputDimensions,
+                       unsigned int    inputStride,
+                       unsigned char* __restrict__ outPixels,
+                       ImageDimensions desiredDimensions);
 
 /**
  * @brief Resamples the input image with the Lanczos algorithm.
@@ -370,16 +400,75 @@ void LanczosSample1BPP( const unsigned char * __restrict__ inPixels,
  *
  * @param[in] inPixels Pointer to the input image buffer.
  * @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride of the image.
  * @param[out] outPixels Pointer to the output image buffer.
  * @param[in] desiredDimensions The output dimensions of the image.
  */
-void Resample( const unsigned char * __restrict__ inPixels,
-               ImageDimensions inputDimensions,
-               unsigned char * __restrict__ outPixels,
-               ImageDimensions desiredDimensions,
-               Resampler::Filter filterType,
-               int numChannels, bool hasAlpha );
+void Resample(const unsigned char* __restrict__ inPixels,
+              ImageDimensions inputDimensions,
+              unsigned int    inputStride,
+              unsigned char* __restrict__ outPixels,
+              ImageDimensions   desiredDimensions,
+              Resampler::Filter filterType,
+              int               numChannels,
+              bool              hasAlpha);
 
+/**
+ * @brief Rotates the input image with an implementation of the 'Rotate by Shear' algorithm.
+ *
+ * @pre @p pixelsIn must not alias @p pixelsOut. The input image should be a totally
+ * separate buffer from the output buffer.
+ *
+ * @note This function allocates memory in @p pixelsOut which has to be released by calling @e free()
+ *
+ * @param[in] pixelsIn The input buffer.
+ * @param[in] widthIn The width of the input buffer.
+ * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
+ * @param[in] pixelSize The size of the pixel.
+ * @param[in] radians The rotation angle in radians.
+ * @param[out] pixelsOut The rotated output buffer.
+ * @param[out] widthOut The width of the output buffer.
+ * @param[out] heightOut The height of the output buffer.
+ */
+void RotateByShear(const uint8_t* const pixelsIn,
+                   unsigned int         widthIn,
+                   unsigned int         heightIn,
+                   unsigned int         strideIn,
+                   unsigned int         pixelSize,
+                   float                radians,
+                   uint8_t*&            pixelsOut,
+                   unsigned int&        widthOut,
+                   unsigned int&        heightOut);
+
+/**
+ * @brief Applies to the input image a horizontal shear transformation.
+ *
+ * @pre @p pixelsIn must not alias @p pixelsOut. The input image should be a totally
+ * separate buffer from the output buffer.
+ * @pre The maximun/minimum shear angle is +/-45 degrees (PI/4 around 0.79 radians).
+ *
+ * @note This function allocates memory in @p pixelsOut which has to be released by calling @e free()
+ *
+ * @param[in] pixelsIn The input buffer.
+ * @param[in] widthIn The width of the input buffer.
+ * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
+ * @param[in] pixelSize The size of the pixel.
+ * @param[in] radians The shear angle in radians.
+ * @param[out] pixelsOut The rotated output buffer.
+ * @param[out] widthOut The width of the output buffer.
+ * @param[out] heightOut The height of the output buffer.
+ */
+void HorizontalShear(const uint8_t* const pixelsIn,
+                     unsigned int         widthIn,
+                     unsigned int         heightIn,
+                     unsigned int         strideIn,
+                     unsigned int         pixelSize,
+                     float                radians,
+                     uint8_t*&            pixelsOut,
+                     unsigned int&        widthOut,
+                     unsigned int&        heightOut);
 
 /**@}*/
 
@@ -393,27 +482,27 @@ void Resample( const unsigned char * __restrict__ inPixels,
  * @param[in,out] pixels The array of pixels to work on.
  * @param[i]      width  The number of pixels in the array passed-in.
  */
-void HalveScanlineInPlaceRGB888( unsigned char * pixels, unsigned int width );
+void HalveScanlineInPlaceRGB888(unsigned char* pixels, unsigned int width);
 
 /**
  * @copydoc HalveScanlineInPlaceRGB888
  */
-void HalveScanlineInPlaceRGBA8888( unsigned char * pixels, unsigned int width );
+void HalveScanlineInPlaceRGBA8888(unsigned char* pixels, unsigned int width);
 
 /**
  * @copydoc HalveScanlineInPlaceRGB888
  */
-void HalveScanlineInPlaceRGB565( unsigned char * pixels, unsigned int width );
+void HalveScanlineInPlaceRGB565(unsigned char* pixels, unsigned int width);
 
 /**
  * @copydoc HalveScanlineInPlaceRGB888
  */
-void HalveScanlineInPlace2Bytes( unsigned char * pixels, unsigned int width );
+void HalveScanlineInPlace2Bytes(unsigned char* pixels, unsigned int width);
 
 /**
  * @copydoc HalveScanlineInPlaceRGB888
  */
-void HalveScanlineInPlace1Byte( unsigned char * pixels, unsigned int width );
+void HalveScanlineInPlace1Byte(unsigned char* pixels, unsigned int width);
 
 /**
  * @brief Average pixels at corresponding offsets in two scanlines.
@@ -424,45 +513,45 @@ void HalveScanlineInPlace1Byte( unsigned char * pixels, unsigned int width );
  * @param[out] outputScanline Destination for the averaged pixels.
  * @param[in] width The widths of all the scanlines passed-in.
  */
-void AverageScanlines1( const unsigned char * scanline1,
-                        const unsigned char * scanline2,
-                        unsigned char* outputScanline,
-                        /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/
-                        unsigned int width );
+void AverageScanlines1(const unsigned char* scanline1,
+                       const unsigned char* scanline2,
+                       unsigned char*       outputScanline,
+                       /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/
+                       unsigned int width);
 
 /**
  * @copydoc AverageScanlines1
  */
-void AverageScanlines2( const unsigned char * scanline1,
-                        const unsigned char * scanline2,
-                        unsigned char* outputScanline,
-                        /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/
-                        unsigned int width );
+void AverageScanlines2(const unsigned char* scanline1,
+                       const unsigned char* scanline2,
+                       unsigned char*       outputScanline,
+                       /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/
+                       unsigned int width);
 
 /**
  * @copydoc AverageScanlines1
  */
-void AverageScanlines3( const unsigned char * scanline1,
-                        const unsigned char * scanline2,
-                        unsigned char* outputScanline,
-                        /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/
-                        unsigned int width );
+void AverageScanlines3(const unsigned char* scanline1,
+                       const unsigned char* scanline2,
+                       unsigned char*       outputScanline,
+                       /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/
+                       unsigned int width);
 
 /**
  * @copydoc AverageScanlines1
  */
-void AverageScanlinesRGBA8888( const unsigned char * scanline1,
-                               const unsigned char * scanline2,
-                               unsigned char * outputScanline,
-                               unsigned int width );
+void AverageScanlinesRGBA8888(const unsigned char* scanline1,
+                              const unsigned char* scanline2,
+                              unsigned char*       outputScanline,
+                              unsigned int         width);
 
 /**
  * @copydoc AverageScanlines1
  */
-void AverageScanlinesRGB565( const unsigned char * scanline1,
-                             const unsigned char * scanline2,
-                             unsigned char* outputScanline,
-                             unsigned int width );
+void AverageScanlinesRGB565(const unsigned char* scanline1,
+                            const unsigned char* scanline2,
+                            unsigned char*       outputScanline,
+                            unsigned int         width);
 /**@}*/
 
 /**
@@ -476,7 +565,7 @@ void AverageScanlinesRGB565( const unsigned char * scanline1,
  * @param[in] a First component to average.
  * @param[in] b Second component to average.
  **/
-inline unsigned int AverageComponent( unsigned int a, unsigned int b )
+inline unsigned int AverageComponent(unsigned int a, unsigned int b)
 {
   unsigned int avg = (a + b) >> 1u;
   return avg;
@@ -488,15 +577,19 @@ inline unsigned int AverageComponent( unsigned int a, unsigned int b )
  * @param[in] a First pixel to average.
  * @param[in] b Second pixel to average
  **/
-inline uint32_t AveragePixelRGBA8888( uint32_t a, uint32_t b )
+inline uint32_t AveragePixelRGBA8888(uint32_t a, uint32_t b)
 {
-  const unsigned int avg =
-    ((AverageComponent( (a & 0xff000000) >> 1u, (b & 0xff000000) >> 1u ) << 1u) & 0xff000000 ) +
-    (AverageComponent( a & 0x00ff0000, b & 0x00ff0000 ) & 0x00ff0000 ) +
-    (AverageComponent( a & 0x0000ff00, b & 0x0000ff00 ) & 0x0000ff00 ) +
-    (AverageComponent( a & 0x000000ff, b & 0x000000ff ) );
-  return avg;
-  ///@ToDo: Optimise by trying return (((a ^ b) & 0xfefefefeUL) >> 1) + (a & b);
+  /**
+   * @code
+   * const unsigned int avg =
+   *   (AverageComponent((a & 0xff000000) >> 1u, (b & 0xff000000) >> 1u) << 1u) & 0xff000000) +
+   *   (AverageComponent(a & 0x00ff0000, b & 0x00ff0000) & 0x00ff0000) +
+   *   (AverageComponent(a & 0x0000ff00, b & 0x0000ff00) & 0x0000ff00) +
+   *   (AverageComponent(a & 0x000000ff, b & 0x000000ff);
+   * return avg;
+   * @endcode
+   */
+  return (((a ^ b) & 0xfefefefeu) >> 1) + (a & b);
   ///@ToDo: Optimise for ARM using the single ARMV6 instruction: UHADD8  R4, R0, R5. This is not Neon. It runs in the normal integer pipeline so there is no downside like a stall moving between integer and copro.
 }
 
@@ -506,55 +599,118 @@ inline uint32_t AveragePixelRGBA8888( uint32_t a, uint32_t b )
  * @param b[in] Low 16 bits hold a color value as RGB565 to average with parameter a.
  * @return The average color of the two RGB565 pixels passed in, in the low 16 bits of the returned value.
  **/
-inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b )
+inline uint32_t AveragePixelRGB565(uint32_t a, uint32_t b)
 {
-  const unsigned int avg =
-    (AverageComponent( a & 0xf800, b & 0xf800 ) & 0xf800 ) +
-    (AverageComponent( a & 0x7e0,  b & 0x7e0 )  & 0x7e0 ) +
-    (AverageComponent( a & 0x1f,   b & 0x1f ) );
-  return avg;
+  /**
+   * @code
+   * const unsigned int avg =
+   *   (AverageComponent(a & 0xf800, b & 0xf800) & 0xf800) +
+   *   (AverageComponent(a & 0x7e0, b & 0x7e0) & 0x7e0) +
+   *   (AverageComponent(a & 0x1f, b & 0x1f));
+   * return avg;
+   * @endcode
+   */
+  return (((a ^ b) & 0xf7deu) >> 1) + (a & b);
 }
 
 /** @return The weighted blend of two integers as a 16.16 fixed-point number, given a 0.16 fixed-point blending factor. */
-inline unsigned int WeightedBlendIntToFixed1616(unsigned int a, unsigned int b, unsigned int fractBlend )
+inline unsigned int WeightedBlendIntToFixed1616(unsigned int a, unsigned int b, unsigned int fractBlend)
 {
-  DALI_ASSERT_DEBUG( fractBlend <= 65535u && "Factor should be in 0.16 fixed-point." );
-  const unsigned int weightedAFixed = a * (65535u - fractBlend);
-  const unsigned int weightedBFixed = b * fractBlend;
-  const unsigned blended = (weightedAFixed + weightedBFixed);
+  DALI_ASSERT_DEBUG(fractBlend <= 65535u && "Factor should be in 0.16 fixed-point.");
+  /**
+   * @code
+   * const unsigned int weightedAFixed = a * (65535u - fractBlend);
+   * const unsigned int weightedBFixed = b * fractBlend;
+   * const unsigned     blended        = (weightedAFixed + weightedBFixed);
+   * @endcode
+   */
+  const unsigned int blended = (a << 16) - a + (static_cast<int32_t>(b) - static_cast<int32_t>(a)) * fractBlend;
   return blended;
 }
 
 /** @brief Blend two 16.16 inputs to give a 16.32 output. */
-inline uint64_t WeightedBlendFixed1616ToFixed1632(unsigned int a, unsigned int b, unsigned int fractBlend )
+inline uint64_t WeightedBlendFixed1616ToFixed1632(unsigned int a, unsigned int b, unsigned int fractBlend)
 {
-  DALI_ASSERT_DEBUG( fractBlend <= 65535u && "Factor should be in 0.16 fixed-point." );
-  // Blend while promoting intermediates to 16.32 fixed point:
-  const uint64_t weightedAFixed = uint64_t(a) * (65535u - fractBlend);
-  const uint64_t weightedBFixed = uint64_t(b) * fractBlend;
-  const uint64_t blended = (weightedAFixed + weightedBFixed);
+  DALI_ASSERT_DEBUG(fractBlend <= 65535u && "Factor should be in 0.16 fixed-point.");
+  /**
+   * @code
+   * // Blend while promoting intermediates to 16.32 fixed point:
+   * const uint64_t weightedAFixed = uint64_t(a) * (65535u - fractBlend);
+   * const uint64_t weightedBFixed = uint64_t(b) * fractBlend;
+   * const uint64_t blended        = (weightedAFixed + weightedBFixed);
+   * @endcode
+   */
+  const uint64_t blended = (static_cast<uint64_t>(a) << 16) - a + (static_cast<int64_t>(b) - static_cast<int64_t>(a)) * fractBlend;
   return blended;
 }
 
 /**
  * @brief Blend 4 taps into one value using horizontal and vertical weights.
  */
-inline unsigned int BilinearFilter1Component(unsigned int tl, unsigned int tr, unsigned int bl, unsigned int br, unsigned int fractBlendHorizontal, unsigned int fractBlendVertical )
+inline unsigned int BilinearFilter1Component(unsigned int tl, unsigned int tr, unsigned int bl, unsigned int br, unsigned int fractBlendHorizontal, unsigned int fractBlendVertical)
 {
-  DALI_ASSERT_DEBUG( fractBlendHorizontal <= 65535u && "Factor should be in 0.16 fixed-point." );
-  DALI_ASSERT_DEBUG( fractBlendVertical   <= 65535u && "Factor should be in 0.16 fixed-point." );
-
-  const unsigned int topBlend = WeightedBlendIntToFixed1616( tl, tr, fractBlendHorizontal );
-  const unsigned int botBlend = WeightedBlendIntToFixed1616( bl, br, fractBlendHorizontal );
-  const uint64_t blended2x2 = WeightedBlendFixed1616ToFixed1632( topBlend, botBlend, fractBlendVertical );
-  const unsigned int rounded = (blended2x2 + (1u << 31u) ) >> 32u;
+  DALI_ASSERT_DEBUG(fractBlendHorizontal <= 65535u && "Factor should be in 0.16 fixed-point.");
+  DALI_ASSERT_DEBUG(fractBlendVertical <= 65535u && "Factor should be in 0.16 fixed-point.");
+
+  /**
+   * @code
+   * const unsigned int topBlend   = WeightedBlendIntToFixed1616(tl, tr, fractBlendHorizontal);
+   * const unsigned int botBlend   = WeightedBlendIntToFixed1616(bl, br, fractBlendHorizontal);
+   * const uint64_t     blended2x2 = WeightedBlendFixed1616ToFixed1632(topBlend, botBlend, fractBlendVertical);
+   * const unsigned int rounded    = (blended2x2 + (1u << 31u)) >> 32u;
+   * @endcode
+   */
+
+  /**
+   * Hard-coding optimize!
+   *
+   * Let p = 65536, s.t we can optimze it as << 16.
+   * Let x = fractBlendHorizontal, y = fractBlendVertical.
+   * topBlend = (tl*p - tl - tl*x + tr*x)
+   * botBlend = (bl*p - bl - bl*x + br*x)
+   * blended2x2 = topBlend*p - topBlend - topBlend*y + botBlend*y
+   *
+   * And now we can split all values.
+   * tl*p*p - tl*p - tl*x*p + tr*x*p  -  tl*p + tl + tl*x - tr*x  -  tl*y*p + tl*y + tl*x*y - tr*x*y  +  bl*y*p - bl*y - bl*x*y + br*x*y;
+   * --> (collect by p, x, and y)
+   * (tl)*p*p + (-2tl + (-tl + tr)*x + (-tl+bl)*y)*p + tl + (tl - tr)*x + (tl - bl)*y + (tl - tr - bl + br)*x*y
+   *
+   * A = (tl - tr) * x;
+   * B = (tl - bl) * y;
+   * C = (tl - tr - bl + br) * x * y;
+   * D = (2*tl + A + B)
+   * -->
+   * (tl << 32) - (D << 16) + tl + A + B + C
+   *
+   * Becareful of overflow and negative value.
+   */
+  const int32_t A = (static_cast<int32_t>(tl) - static_cast<int32_t>(tr)) * static_cast<int32_t>(fractBlendHorizontal);
+  const int32_t B = (static_cast<int32_t>(tl) - static_cast<int32_t>(bl)) * static_cast<int32_t>(fractBlendVertical);
+  const int64_t C = (static_cast<int64_t>(tl) - static_cast<int64_t>(tr) - static_cast<int64_t>(bl) + static_cast<int64_t>(br)) * static_cast<int64_t>(fractBlendHorizontal) * static_cast<int64_t>(fractBlendVertical);
+  const int64_t D = ((static_cast<int64_t>(tl) << 1) + A + B);
+
+  const uint64_t     blended2x2 = (static_cast<int64_t>(tl) << 32u) - (D << 16u) + tl + A + B + C;
+  const unsigned int rounded    = (blended2x2 + (1u << 31u)) >> 32u;
   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 */
 } /* namespace Internal */
 } /* namespace Dali */
 
-#endif /* DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ */
+#endif /* DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H */