Image scaling operations - FilterMode::Box implemented for all pixel formats
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / portable / image-operations.h
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #ifndef DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_
19 #define DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/bitmap.h>
23 #include <dali/public-api/images/image-attributes.h>
24
25 // EXTERNAL INCLUDES
26 #include <stdint.h>
27
28 namespace Dali
29 {
30 namespace Internal
31 {
32 namespace Platform
33 {
34
35 /**
36  * @brief Identify which combination of x and y dimensions matter in terminating iterative box filtering.
37  */
38 enum BoxDimensionTest
39 {
40   BoxDimensionTestEither,
41   BoxDimensionTestBoth,
42   BoxDimensionTestX,
43   BoxDimensionTestY
44 };
45
46 /**
47  * @brief Apply requested attributes to bitmap.
48  * @param[in] bitmap The input bitmap.
49  * @param[in] requestedAttributes Attributes which should be applied to bitmap.
50  * @return A bitmap which results from applying the requested attributes to the bitmap passed-in, or the original bitmap passed in if the attributes have no effect.
51  */
52 Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, const ImageAttributes& requestedAttributes );
53
54 /**
55  * @brief Apply downscaling to a bitmap according to requested attributes.
56  * @note Only rough power of 2 box filtering is currently performed.
57  * @note The input bitmap may be modified and left in an invalid state so must be discarded.
58  **/
59 Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, const ImageAttributes& requestedAttributes );
60
61 /**
62  * @brief Destructive in-place downscaling by a power of 2 factor.
63  *
64  * A box filter with a 2x2 kernel is repeatedly applied as long as the result
65  * of the next downscaling step would not be smaller than the desired
66  * dimensions.
67  * @param[in,out] pixels The buffer both to read from and write the result to.
68  * @param[in]     inputWidth The width of the input image.
69  * @param[in]     inputHeight The height of the input image.
70  * @param[in]     desiredWidth The width the client is requesting.
71  * @param[in]     desiredHeight The height the client is requesting.
72  * @param[out]    outWidth  The resulting width after downscaling.
73  * @param[out]    outHeight The resulting height after downscaling.
74  */
75 void DownscaleInPlacePow2RGB888(
76     unsigned char * pixels,
77     unsigned int inputWidth, unsigned int inputHeight,
78     unsigned int desiredWidth, unsigned int desiredHeight,
79     BoxDimensionTest dimensionTest,
80     unsigned int& outWidth, unsigned int& outHeight );
81
82 /**
83  * @copydoc DownscaleInPlacePow2RGB888
84  */
85 void DownscaleInPlacePow2RGBA8888(
86     unsigned char * pixels,
87     unsigned int inputWidth, unsigned int inputHeight,
88     unsigned int desiredWidth, unsigned int desiredHeight,
89     BoxDimensionTest dimensionTest,
90     unsigned int& outWidth, unsigned int& outHeight );
91
92 /**
93  * @copydoc DownscaleInPlacePow2RGB888
94  *
95  * For the 2-byte packed 16 bit format RGB565.
96  */
97 void DownscaleInPlacePow2RGB565(
98     unsigned char * pixels,
99     unsigned int inputWidth, unsigned int inputHeight,
100     unsigned int desiredWidth, unsigned int desiredHeight,
101     BoxDimensionTest dimensionTest,
102     unsigned int& outWidth, unsigned int& outHeight );
103
104 /**
105  * @copydoc DownscaleInPlacePow2RGB888
106  *
107  * For 2-byte formats such as lum8alpha8, but not packed 16 bit formats like RGB565.
108  */
109 void DownscaleInPlacePow2ComponentPair(
110     unsigned char * pixels,
111     unsigned int inputWidth, unsigned int inputHeight,
112     unsigned int desiredWidth, unsigned int desiredHeight,
113     BoxDimensionTest dimensionTest,
114     unsigned int& outWidth, unsigned int& outHeight );
115
116 /**
117  * @copydoc DownscaleInPlacePow2RGB888
118  *
119  * For single-byte formats such as lum8 or alpha8.
120  */
121 void DownscaleInPlacePow2SingleBytePerPixel(
122     unsigned char * pixels,
123     unsigned int inputWidth, unsigned int inputHeight,
124     unsigned int desiredWidth, unsigned int desiredHeight,
125     BoxDimensionTest dimensionTest,
126     unsigned int& outWidth, unsigned int& outHeight );
127
128 /**
129  * @brief Average adjacent pairs of pixels, overwriting the input array.
130  * @param[in,out] pixels The array of pixels to work on.
131  * @param[i]      width  The number of pixels in the array passed-in.
132  */
133 void HalveScanlineInPlaceRGB888( unsigned char * pixels, unsigned int width );
134
135 /**
136  * @copydoc HalveScanlineInPlaceRGB888
137  */
138 void HalveScanlineInPlaceRGBA8888(
139     unsigned char * pixels,
140     unsigned int width );
141
142 /**
143  * @copydoc HalveScanlineInPlaceRGB888
144  */
145 void HalveScanlineInPlaceRGB565( unsigned char * pixels, unsigned int width );
146
147 /**
148  * @copydoc HalveScanlineInPlaceRGB888
149  */
150 void HalveScanlineInPlace2Bytes(
151     unsigned char * pixels,
152     unsigned int width );
153
154 /**
155  * @copydoc HalveScanlineInPlaceRGB888
156  */
157 void HalveScanlineInPlace1Byte(
158     unsigned char * pixels,
159     unsigned int width );
160
161 /**
162  * @brief Average pixels at corresponding offsets in two scanlines.
163  *
164  * outputScanline is allowed to alias scanline1.
165  * @param[in] scanline1 First scanline of pixels to average.
166  * @param[in] scanline2 Second scanline of pixels to average.
167  * @param[out] outputScanline Destination for the averaged pixels.
168  * @param[in] width The widths of all the scanlines passed-in.
169  */
170 void AverageScanlines1(
171     const unsigned char * scanline1,
172     const unsigned char * scanline2,
173     unsigned char* outputScanline,
174     /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/
175     unsigned int width );
176
177 /**
178  * @copydoc AverageScanlines1
179  */
180 void AverageScanlines2(
181     const unsigned char * scanline1,
182     const unsigned char * scanline2,
183     unsigned char* outputScanline,
184     /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/
185     unsigned int width );
186
187 /**
188  * @copydoc AverageScanlines1
189  */
190 void AverageScanlines3(
191     const unsigned char * scanline1,
192     const unsigned char * scanline2,
193     unsigned char* outputScanline,
194     /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/
195     unsigned int width );
196
197 /**
198  * @copydoc AverageScanlines1
199  */
200 void AverageScanlinesRGBA8888(
201     const unsigned char * scanline1,
202     const unsigned char * scanline2,
203     unsigned char * outputScanline,
204     unsigned int width );
205
206 /**
207  * @copydoc AverageScanlines1
208  */
209 void AverageScanlinesRGB565(
210     const unsigned char * scanline1,
211     const unsigned char * scanline2,
212     unsigned char* outputScanline,
213     unsigned int width );
214
215 /**
216  * @brief Inline functions exposed in header to allow unit testing.
217  */
218 namespace
219 {
220   /**
221    * @brief Average two integer arguments.
222    * @return The average of two uint arguments.
223    * @param[in] a First component to average.
224    * @param[in] b Second component to average.
225    **/
226   inline unsigned int AverageComponent( unsigned int a, unsigned int b )
227   {
228     unsigned int avg = (a + b) >> 1u;
229     return avg;
230   }
231
232   /**
233    * @brief Average a pair of RGB565 pixels.
234    * @return The average of two RGBA8888 pixels.
235    * @param[in] a First pixel to average.
236    * @param[in] b Second pixel to average
237    **/
238   inline uint32_t AveragePixelRGBA8888( uint32_t a, uint32_t b )
239   {
240     const unsigned int avg =
241       ((AverageComponent( (a & 0xff000000) >> 1u, (b & 0xff000000) >> 1u ) << 1u) & 0xff000000 ) +
242       (AverageComponent( a & 0x00ff0000, b & 0x00ff0000 ) & 0x00ff0000 ) +
243       (AverageComponent( a & 0x0000ff00, b & 0x0000ff00 ) & 0x0000ff00 ) +
244       (AverageComponent( a & 0x000000ff, b & 0x000000ff ) );
245     return avg;
246     ///@ToDo: Optimise by trying return (((a ^ b) & 0xfefefefeUL) >> 1) + (a & b);
247     ///@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.
248   }
249
250   /**
251    * @brief Average a pair of RGB565 pixels.
252    * @param a[in] Low 16 bits hold a color value as RGB565 to average with parameter b.
253    * @param b[in] Low 16 bits hold a color value as RGB565 to average with parameter a.
254    * @return The average color of the two RGB565 pixels passed in, in the low 16 bits of the returned value.
255    **/
256   inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b )
257   {
258     const unsigned int avg =
259       (AverageComponent( a & 0xf800, b & 0xf800 ) & 0xf800 ) +
260       (AverageComponent( a & 0x7e0,  b & 0x7e0 )  & 0x7e0 ) +
261       (AverageComponent( a & 0x1f,   b & 0x1f ) );
262     return avg;
263   }
264
265 } // namespace - unnamed
266 } /* namespace Platform */
267 } /* namespace Internal */
268 } /* namespace Dali */
269
270 #endif /* DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ */