Changed alpha mask scaling to use Lanczos.
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / portable / image-operations.h
index 2d26725..3b2ac9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 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_
 
-// INTERNAL INCLUDES
-#include <dali/integration-api/bitmap.h>
-#include <dali/public-api/images/image-attributes.h>
-
 // EXTERNAL INCLUDES
 #include <stdint.h>
 
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+#include <dali/public-api/images/image-operations.h>
+
 namespace Dali
 {
 namespace Internal
@@ -44,99 +44,21 @@ enum BoxDimensionTest
 };
 
 /**
- * @brief Simple class for passing around pairs of small ints.
- *
- * These are immutable. If you want to change a value, make a whole new object.
- * @note One of these can be passed in a single 32 bit integer register on
- * common architectures.
- */
-class Vector2Uint16
-{
-public:
-  /**
-   * @brief Default constructor for the (0, 0) vector.
-   */
-  Vector2Uint16() : mData(0) {}
-
-  /**
-   * @brief Constructor taking separate x and y (width and height) parameters.
-   * @param[in] width The width or X dimension of the vector. Make sure it is less than 65536,
-   * @param[in] height The height or Y dimension of the vector. Make sure it is less than 65536,
-   */
-  Vector2Uint16( uint32_t width, uint32_t height )
-  {
-    DALI_ASSERT_DEBUG( width < ( 1u << 16 ) && "Width parameter not representable." );
-    DALI_ASSERT_DEBUG( height < ( 1u << 16 ) && "Height parameter not representable." );
-
-    /* Do equivalent of the code below with one aligned memory access:
-     * mComponents[0] = width;
-     * mComponents[1] = height;
-     * Unit tests make sure this is equivalent.
-     **/
-    mData = (height << 16u) + width;
-  }
-
-  /**
-   * @brief Copy constructor.
-   */
-  Vector2Uint16( const Vector2Uint16& rhs )
-  {
-    mData = rhs.mData;
-  }
-
-  /**
-   * @returns the x dimension stored in this 2-tuple.
-   */
-  uint16_t GetWidth() const
-  {
-    return mComponents[0];
-  }
-
-  /**
-   * @returns the y dimension stored in this 2-tuple.
-   */
-  uint16_t GetHeight() const
-  {
-    return mComponents[1];
-  }
-
-  /**
-   * @returns the x dimension stored in this 2-tuple.
-   */
-  uint16_t GetX()  const
-  {
-    return mComponents[0];
-  }
-
-  /**
-   * @returns the y dimension stored in this 2-tuple.
-   */
-  uint16_t GetY() const
-  {
-    return mComponents[1];
-  }
-
-private:
-  union
-  {
-    // Addressable view of X and Y:
-    uint16_t mComponents[2];
-    // Packed view of X and Y to force alignment and allow a faster copy:
-    uint32_t mData;
-  };
-};
-
-/**
- * @brief Human readable text output.
- */
-std::ostream& operator<<( std::ostream& o, const Vector2Uint16& vector );
-
-/**
  * @brief The integer dimensions of an image or a region of an image packed into
  *        16 bits per component.
  * @note  This can only be used for images of up to 65535 x 65535 pixels.
   */
-typedef Vector2Uint16 ImageDimensions;
+typedef Uint16Pair ImageDimensions;
+
+/**
+ * @brief Work out the true desired width and height, accounting for special
+ * rules for zeros in either or both input requested dimensions.
+ *
+ * @param[in] rawDimensions Width and height of image before processing.
+ * @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 );
 
 /**
  * @defgroup BitmapOperations Bitmap-to-Bitmap Image operations.
@@ -157,13 +79,13 @@ typedef Vector2Uint16 ImageDimensions;
  *         bitmap passed-in, or the original bitmap passed in if the attributes
  *         have no effect.
  */
-Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, const ImageAttributes& requestedAttributes );
+Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr 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.
  **/
-Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, ImageDimensions desired, ImageAttributes::ScalingMode scalingMode, ImageAttributes::FilterMode filterMode );
+Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, ImageDimensions desired, FittingMode::Type fittingMode, SamplingMode::Type samplingMode );
 /**@}*/
 
 /**
@@ -192,8 +114,8 @@ void DownscaleInPlacePow2( unsigned char * const pixels,
                            unsigned int inputHeight,
                            unsigned int desiredWidth,
                            unsigned int desiredHeight,
-                           ImageAttributes::ScalingMode scalingMode,
-                           ImageAttributes::FilterMode filterMode,
+                           FittingMode::Type fittingMode,
+                           SamplingMode::Type samplingMode,
                            unsigned& outWidth,
                            unsigned& outHeight );
 
@@ -338,6 +260,103 @@ void PointSample1BPP( const unsigned char * inPixels,
                       unsigned int desiredWidth,
                       unsigned int desiredHeight );
 
+/**
+ * @brief Resample input image to output image using a bilinear filter.
+ *
+ * Each output pixel is formed of a weighted sum of a 2x2 block of four input
+ * pixels
+ * @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 );
+
+/**
+ * @copydoc LinearSample
+ *
+ * Specialised for one byte per pixel formats.
+ */
+void LinearSample1BPP( const unsigned char * __restrict__ inPixels,
+                       ImageDimensions inputDimensions,
+                       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 );
+
+/**
+ * @copydoc LinearSample
+ *
+ * Specialised for RGB565 16 bit pixel format.
+ */
+void LinearSampleRGB565( const unsigned char * __restrict__ inPixels,
+                       ImageDimensions inputDimensions,
+                       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 );
+
+/**
+ * @copydoc LinearSample
+ *
+ * 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 );
+
+/**
+ * @brief Resamples the input image with the Lanczos algorithm.
+ *
+ * @pre @p inPixels must not alias @p outPixels. The input image should be a totally
+ * separate buffer from the output buffer.
+ *
+ * @param[in] inPixels Pointer to the input image buffer.
+ * @param[in] inputDimensions The input dimensions 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 );
+
+/**
+ * @brief Resamples the input image with the Lanczos algorithm.
+ *
+ * @pre @p inPixels must not alias @p outPixels. The input image should be a totally
+ * separate buffer from the output buffer.
+ *
+ * @param[in] inPixels Pointer to the input image buffer.
+ * @param[in] inputDimensions The input dimensions 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 );
+
 /**@}*/
 
 /**
@@ -472,6 +491,42 @@ inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b )
   return avg;
 }
 
+/** @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 )
+{
+  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);
+  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 )
+{
+  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);
+  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 )
+{
+  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;
+  return rounded;
+}
+
 /**@}*/
 
 } /* namespace Platform */