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