Merge "Make a full screen window in the mobile emulator which has an HD screen" into...
[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 Simple class for passing around pairs of small ints.
48  *
49  * These are immutable. If you want to change a value, make a whole new object.
50  * @note One of these can be passed in a single 32 bit integer register on
51  * common architectures.
52  */
53 class Vector2Uint16
54 {
55 public:
56   /**
57    * @brief Default constructor for the (0, 0) vector.
58    */
59   Vector2Uint16() : mData(0) {}
60
61   /**
62    * @brief Constructor taking separate x and y (width and height) parameters.
63    * @param[in] width The width or X dimension of the vector. Make sure it is less than 65536,
64    * @param[in] height The height or Y dimension of the vector. Make sure it is less than 65536,
65    */
66   Vector2Uint16( uint32_t width, uint32_t height )
67   {
68     DALI_ASSERT_DEBUG( width < ( 1u << 16 ) && "Width parameter not representable." );
69     DALI_ASSERT_DEBUG( height < ( 1u << 16 ) && "Height parameter not representable." );
70
71     /* Do equivalent of the code below with one aligned memory access:
72      * mComponents[0] = width;
73      * mComponents[1] = height;
74      * Unit tests make sure this is equivalent.
75      **/
76     mData = (height << 16u) + width;
77   }
78
79   /**
80    * @brief Copy constructor.
81    */
82   Vector2Uint16( const Vector2Uint16& rhs )
83   {
84     mData = rhs.mData;
85   }
86
87   /**
88    * @returns the x dimension stored in this 2-tuple.
89    */
90   uint16_t GetWidth() const
91   {
92     return mComponents[0];
93   }
94
95   /**
96    * @returns the y dimension stored in this 2-tuple.
97    */
98   uint16_t GetHeight() const
99   {
100     return mComponents[1];
101   }
102
103   /**
104    * @returns the x dimension stored in this 2-tuple.
105    */
106   uint16_t GetX()  const
107   {
108     return mComponents[0];
109   }
110
111   /**
112    * @returns the y dimension stored in this 2-tuple.
113    */
114   uint16_t GetY() const
115   {
116     return mComponents[1];
117   }
118
119 private:
120   union
121   {
122     // Addressable view of X and Y:
123     uint16_t mComponents[2];
124     // Packed view of X and Y to force alignment and allow a faster copy:
125     uint32_t mData;
126   };
127 };
128
129 /**
130  * @brief Human readable text output.
131  */
132 std::ostream& operator<<( std::ostream& o, const Vector2Uint16& vector );
133
134 /**
135  * @brief The integer dimensions of an image or a region of an image packed into
136  *        16 bits per component.
137  * @note  This can only be used for images of up to 65535 x 65535 pixels.
138   */
139 typedef Vector2Uint16 ImageDimensions;
140
141 /**
142  * @defgroup BitmapOperations Bitmap-to-Bitmap Image operations.
143  * @{
144  */
145
146 /**
147  * @brief Apply requested attributes to bitmap.
148  *
149  * This is the top-level function which runs the on-load image post-processing
150  * pipeline. Bitmaps enter here as loaded from the file system by the file
151  * loaders and leave downscaled and filtered as requested by the application,
152  * ready for use.
153  *
154  * @param[in] bitmap The input bitmap.
155  * @param[in] requestedAttributes Attributes which should be applied to bitmap.
156  * @return A bitmap which results from applying the requested attributes to the
157  *         bitmap passed-in, or the original bitmap passed in if the attributes
158  *         have no effect.
159  */
160 Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, const ImageAttributes& requestedAttributes );
161
162 /**
163  * @brief Apply downscaling to a bitmap according to requested attributes.
164  * @note The input bitmap pixel buffer may be modified and used as scratch working space for efficiency, so it must be discarded.
165  **/
166 Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, ImageDimensions desired, ImageAttributes::ScalingMode scalingMode, ImageAttributes::FilterMode filterMode );
167 /**@}*/
168
169 /**
170  * @defgroup ImageBufferScalingAlgorithms Pixel buffer-level scaling algorithms.
171  * @{
172  */
173
174 /**
175  * @brief Destructive in-place downscaling by a power of 2 factor.
176  *
177  * A box filter with a 2x2 kernel is repeatedly applied as long as the result
178  * of the next downscaling step would not be smaller than the desired
179  * dimensions.
180  * @param[in,out] pixels The buffer both to read from and write the result to.
181  * @param[in]     pixelFormat The format of the image pointed at by pixels.
182  * @param[in]     inputWidth The width of the input image.
183  * @param[in]     inputHeight The height of the input image.
184  * @param[in]     desiredWidth The width the client is requesting.
185  * @param[in]     desiredHeight The height the client is requesting.
186  * @param[out]    outWidth  The resulting width after downscaling.
187  * @param[out]    outHeight The resulting height after downscaling.
188  */
189 void DownscaleInPlacePow2( unsigned char * const pixels,
190                            Pixel::Format pixelFormat,
191                            unsigned int inputWidth,
192                            unsigned int inputHeight,
193                            unsigned int desiredWidth,
194                            unsigned int desiredHeight,
195                            ImageAttributes::ScalingMode scalingMode,
196                            ImageAttributes::FilterMode filterMode,
197                            unsigned& outWidth,
198                            unsigned& outHeight );
199
200 /**
201  * @brief Destructive in-place downscaling by a power of 2 factor.
202  *
203  * A box filter with a 2x2 kernel is repeatedly applied as long as the result
204  * of the next downscaling step would not be smaller than the desired
205  * dimensions.
206  * @param[in,out] pixels The buffer both to read from and write the result to.
207  * @param[in]     inputWidth The width of the input image.
208  * @param[in]     inputHeight The height of the input image.
209  * @param[in]     desiredWidth The width the client is requesting.
210  * @param[in]     desiredHeight The height the client is requesting.
211  * @param[out]    outWidth  The resulting width after downscaling.
212  * @param[out]    outHeight The resulting height after downscaling.
213  */
214 void DownscaleInPlacePow2RGB888( unsigned char * pixels,
215                                  unsigned int inputWidth,
216                                  unsigned int inputHeight,
217                                  unsigned int desiredWidth,
218                                  unsigned int desiredHeight,
219                                  BoxDimensionTest dimensionTest,
220                                  unsigned int& outWidth,
221                                  unsigned int& outHeight );
222
223 /**
224  * @copydoc DownscaleInPlacePow2RGB888
225  */
226 void DownscaleInPlacePow2RGBA8888( unsigned char * pixels,
227                                    unsigned int inputWidth,
228                                    unsigned int inputHeight,
229                                    unsigned int desiredWidth,
230                                    unsigned int desiredHeight,
231                                    BoxDimensionTest dimensionTest,
232                                    unsigned int& outWidth,
233                                    unsigned int& outHeight );
234
235 /**
236  * @copydoc DownscaleInPlacePow2RGB888
237  *
238  * For the 2-byte packed 16 bit format RGB565.
239  */
240 void DownscaleInPlacePow2RGB565( unsigned char * pixels,
241                                  unsigned int inputWidth,
242                                  unsigned int inputHeight,
243                                  unsigned int desiredWidth,
244                                  unsigned int desiredHeight,
245                                  BoxDimensionTest dimensionTest,
246                                  unsigned int& outWidth,
247                                  unsigned int& outHeight );
248
249 /**
250  * @copydoc DownscaleInPlacePow2RGB888
251  *
252  * For 2-byte formats such as lum8alpha8, but not packed 16 bit formats like RGB565.
253  */
254 void DownscaleInPlacePow2ComponentPair( unsigned char * pixels,
255                                         unsigned int inputWidth,
256                                         unsigned int inputHeight,
257                                         unsigned int desiredWidth,
258                                         unsigned int desiredHeight,
259                                         BoxDimensionTest dimensionTest,
260                                         unsigned int& outWidth,
261                                         unsigned int& outHeight );
262
263 /**
264  * @copydoc DownscaleInPlacePow2RGB888
265  *
266  * For single-byte formats such as lum8 or alpha8.
267  */
268 void DownscaleInPlacePow2SingleBytePerPixel( unsigned char * pixels,
269                                              unsigned int inputWidth,
270                                              unsigned int inputHeight,
271                                              unsigned int desiredWidth,
272                                              unsigned int desiredHeight,
273                                              BoxDimensionTest dimensionTest,
274                                              unsigned int& outWidth,
275                                              unsigned int& outHeight );
276
277 /**
278  * @brief Rescales an input image into the exact output dimensions passed-in.
279  *
280  * Uses point sampling, equivalent to GL_NEAREST texture filter mode, for the
281  * fastest results, at the expense of aliasing (noisy images) when downscaling.
282  * @note inPixels is allowed to alias outPixels if this is a downscaling,
283  * but not for upscaling.
284  */
285 void PointSample( const unsigned char * inPixels,
286                   unsigned int inputWidth,
287                   unsigned int inputHeight,
288                   Pixel::Format pixelFormat,
289                   unsigned char * outPixels,
290                   unsigned int desiredWidth,
291                   unsigned int desiredHeight );
292
293 /**
294  * @copydoc PointSample
295  *
296  * Specialised for 4-byte formats like RGBA8888 and BGRA8888.
297  */
298 void PointSample4BPP( const unsigned char * inPixels,
299                       unsigned int inputWidth,
300                       unsigned int inputHeight,
301                       unsigned char * outPixels,
302                       unsigned int desiredWidth,
303                       unsigned int desiredHeight );
304
305 /**
306  * @copydoc PointSample
307  *
308  * Specialised for 3-byte formats like RGB888 and BGR888.
309  */
310 void PointSample3BPP( const unsigned char * inPixels,
311                       unsigned int inputWidth,
312                       unsigned int inputHeight,
313                       unsigned char * outPixels,
314                       unsigned int desiredWidth,
315                       unsigned int desiredHeight );
316
317 /**
318  * @copydoc PointSample
319  *
320  * Specialised for 2-byte formats like LA88.
321  */
322 void PointSample2BPP( const unsigned char * inPixels,
323                       unsigned int inputWidth,
324                       unsigned int inputHeight,
325                       unsigned char * outPixels,
326                       unsigned int desiredWidth,
327                       unsigned int desiredHeight );
328
329 /**
330  * @copydoc PointSample
331  *
332  * Specialised for 1-byte formats like L8 and A8.
333  */
334 void PointSample1BPP( const unsigned char * inPixels,
335                       unsigned int inputWidth,
336                       unsigned int inputHeight,
337                       unsigned char * outPixels,
338                       unsigned int desiredWidth,
339                       unsigned int desiredHeight );
340
341 /**@}*/
342
343 /**
344  * @defgroup ScalingAlgorithmFragments Composable subunits of the scaling algorithms.
345  * @{
346  */
347
348 /**
349  * @brief Average adjacent pairs of pixels, overwriting the input array.
350  * @param[in,out] pixels The array of pixels to work on.
351  * @param[i]      width  The number of pixels in the array passed-in.
352  */
353 void HalveScanlineInPlaceRGB888( unsigned char * pixels, unsigned int width );
354
355 /**
356  * @copydoc HalveScanlineInPlaceRGB888
357  */
358 void HalveScanlineInPlaceRGBA8888( unsigned char * pixels, unsigned int width );
359
360 /**
361  * @copydoc HalveScanlineInPlaceRGB888
362  */
363 void HalveScanlineInPlaceRGB565( unsigned char * pixels, unsigned int width );
364
365 /**
366  * @copydoc HalveScanlineInPlaceRGB888
367  */
368 void HalveScanlineInPlace2Bytes( unsigned char * pixels, unsigned int width );
369
370 /**
371  * @copydoc HalveScanlineInPlaceRGB888
372  */
373 void HalveScanlineInPlace1Byte( unsigned char * pixels, unsigned int width );
374
375 /**
376  * @brief Average pixels at corresponding offsets in two scanlines.
377  *
378  * outputScanline is allowed to alias scanline1.
379  * @param[in] scanline1 First scanline of pixels to average.
380  * @param[in] scanline2 Second scanline of pixels to average.
381  * @param[out] outputScanline Destination for the averaged pixels.
382  * @param[in] width The widths of all the scanlines passed-in.
383  */
384 void AverageScanlines1( const unsigned char * scanline1,
385                         const unsigned char * scanline2,
386                         unsigned char* outputScanline,
387                         /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/
388                         unsigned int width );
389
390 /**
391  * @copydoc AverageScanlines1
392  */
393 void AverageScanlines2( const unsigned char * scanline1,
394                         const unsigned char * scanline2,
395                         unsigned char* outputScanline,
396                         /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/
397                         unsigned int width );
398
399 /**
400  * @copydoc AverageScanlines1
401  */
402 void AverageScanlines3( const unsigned char * scanline1,
403                         const unsigned char * scanline2,
404                         unsigned char* outputScanline,
405                         /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/
406                         unsigned int width );
407
408 /**
409  * @copydoc AverageScanlines1
410  */
411 void AverageScanlinesRGBA8888( const unsigned char * scanline1,
412                                const unsigned char * scanline2,
413                                unsigned char * outputScanline,
414                                unsigned int width );
415
416 /**
417  * @copydoc AverageScanlines1
418  */
419 void AverageScanlinesRGB565( const unsigned char * scanline1,
420                              const unsigned char * scanline2,
421                              unsigned char* outputScanline,
422                              unsigned int width );
423 /**@}*/
424
425 /**
426  * @defgroup TestableInlines Inline functions exposed in header to allow unit testing.
427  * @{
428  */
429
430 /**
431  * @brief Average two integer arguments.
432  * @return The average of two uint arguments.
433  * @param[in] a First component to average.
434  * @param[in] b Second component to average.
435  **/
436 inline unsigned int AverageComponent( unsigned int a, unsigned int b )
437 {
438   unsigned int avg = (a + b) >> 1u;
439   return avg;
440 }
441
442 /**
443  * @brief Average a pair of RGBA8888 pixels.
444  * @return The average of two RGBA8888 pixels.
445  * @param[in] a First pixel to average.
446  * @param[in] b Second pixel to average
447  **/
448 inline uint32_t AveragePixelRGBA8888( uint32_t a, uint32_t b )
449 {
450   const unsigned int avg =
451     ((AverageComponent( (a & 0xff000000) >> 1u, (b & 0xff000000) >> 1u ) << 1u) & 0xff000000 ) +
452     (AverageComponent( a & 0x00ff0000, b & 0x00ff0000 ) & 0x00ff0000 ) +
453     (AverageComponent( a & 0x0000ff00, b & 0x0000ff00 ) & 0x0000ff00 ) +
454     (AverageComponent( a & 0x000000ff, b & 0x000000ff ) );
455   return avg;
456   ///@ToDo: Optimise by trying return (((a ^ b) & 0xfefefefeUL) >> 1) + (a & b);
457   ///@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.
458 }
459
460 /**
461  * @brief Average a pair of RGB565 pixels.
462  * @param a[in] Low 16 bits hold a color value as RGB565 to average with parameter b.
463  * @param b[in] Low 16 bits hold a color value as RGB565 to average with parameter a.
464  * @return The average color of the two RGB565 pixels passed in, in the low 16 bits of the returned value.
465  **/
466 inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b )
467 {
468   const unsigned int avg =
469     (AverageComponent( a & 0xf800, b & 0xf800 ) & 0xf800 ) +
470     (AverageComponent( a & 0x7e0,  b & 0x7e0 )  & 0x7e0 ) +
471     (AverageComponent( a & 0x1f,   b & 0x1f ) );
472   return avg;
473 }
474
475 /**@}*/
476
477 } /* namespace Platform */
478 } /* namespace Internal */
479 } /* namespace Dali */
480
481 #endif /* DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ */