2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #ifndef DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_
19 #define DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_
25 #include <dali/integration-api/bitmap.h>
26 #include <dali/public-api/images/image-operations.h>
36 * @brief Identify which combination of x and y dimensions matter in terminating iterative box filtering.
40 BoxDimensionTestEither,
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.
51 typedef Uint16Pair ImageDimensions;
54 * @brief Work out the true desired width and height, accounting for special
55 * rules for zeros in either or both input requested dimensions.
57 * @param[in] rawDimensions Width and height of image before processing.
58 * @param[in] requestedDimensions Width and height of area to scale image into. Can be zero.
59 * @return Dimensions of area to scale image into after special rules are applied.
61 ImageDimensions CalculateDesiredDimensions( ImageDimensions rawDimensions, ImageDimensions requestedDimensions );
64 * @defgroup BitmapOperations Bitmap-to-Bitmap Image operations.
69 * @brief Apply requested attributes to bitmap.
71 * This is the top-level function which runs the on-load image post-processing
72 * pipeline. Bitmaps enter here as loaded from the file system by the file
73 * loaders and leave downscaled and filtered as requested by the application,
76 * @param[in] bitmap The input bitmap.
77 * @param[in] requestedAttributes Attributes which should be applied to bitmap.
78 * @return A bitmap which results from applying the requested attributes to the
79 * bitmap passed-in, or the original bitmap passed in if the attributes
82 Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode = FittingMode::DEFAULT, SamplingMode::Type samplingMode = SamplingMode::DEFAULT );
85 * @brief Apply downscaling to a bitmap according to requested attributes.
86 * @note The input bitmap pixel buffer may be modified and used as scratch working space for efficiency, so it must be discarded.
88 Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, ImageDimensions desired, FittingMode::Type fittingMode, SamplingMode::Type samplingMode );
92 * @defgroup ImageBufferScalingAlgorithms Pixel buffer-level scaling algorithms.
97 * @brief Destructive in-place downscaling by a power of 2 factor.
99 * A box filter with a 2x2 kernel is repeatedly applied as long as the result
100 * of the next downscaling step would not be smaller than the desired
102 * @param[in,out] pixels The buffer both to read from and write the result to.
103 * @param[in] pixelFormat The format of the image pointed at by pixels.
104 * @param[in] inputWidth The width of the input image.
105 * @param[in] inputHeight The height of the input image.
106 * @param[in] desiredWidth The width the client is requesting.
107 * @param[in] desiredHeight The height the client is requesting.
108 * @param[out] outWidth The resulting width after downscaling.
109 * @param[out] outHeight The resulting height after downscaling.
111 void DownscaleInPlacePow2( unsigned char * const pixels,
112 Pixel::Format pixelFormat,
113 unsigned int inputWidth,
114 unsigned int inputHeight,
115 unsigned int desiredWidth,
116 unsigned int desiredHeight,
117 FittingMode::Type fittingMode,
118 SamplingMode::Type samplingMode,
120 unsigned& outHeight );
123 * @brief Destructive in-place downscaling by a power of 2 factor.
125 * A box filter with a 2x2 kernel is repeatedly applied as long as the result
126 * of the next downscaling step would not be smaller than the desired
128 * @param[in,out] pixels The buffer both to read from and write the result to.
129 * @param[in] inputWidth The width of the input image.
130 * @param[in] inputHeight The height of the input image.
131 * @param[in] desiredWidth The width the client is requesting.
132 * @param[in] desiredHeight The height the client is requesting.
133 * @param[out] outWidth The resulting width after downscaling.
134 * @param[out] outHeight The resulting height after downscaling.
136 void DownscaleInPlacePow2RGB888( unsigned char * pixels,
137 unsigned int inputWidth,
138 unsigned int inputHeight,
139 unsigned int desiredWidth,
140 unsigned int desiredHeight,
141 BoxDimensionTest dimensionTest,
142 unsigned int& outWidth,
143 unsigned int& outHeight );
146 * @copydoc DownscaleInPlacePow2RGB888
148 void DownscaleInPlacePow2RGBA8888( unsigned char * pixels,
149 unsigned int inputWidth,
150 unsigned int inputHeight,
151 unsigned int desiredWidth,
152 unsigned int desiredHeight,
153 BoxDimensionTest dimensionTest,
154 unsigned int& outWidth,
155 unsigned int& outHeight );
158 * @copydoc DownscaleInPlacePow2RGB888
160 * For the 2-byte packed 16 bit format RGB565.
162 void DownscaleInPlacePow2RGB565( unsigned char * pixels,
163 unsigned int inputWidth,
164 unsigned int inputHeight,
165 unsigned int desiredWidth,
166 unsigned int desiredHeight,
167 BoxDimensionTest dimensionTest,
168 unsigned int& outWidth,
169 unsigned int& outHeight );
172 * @copydoc DownscaleInPlacePow2RGB888
174 * For 2-byte formats such as lum8alpha8, but not packed 16 bit formats like RGB565.
176 void DownscaleInPlacePow2ComponentPair( unsigned char * pixels,
177 unsigned int inputWidth,
178 unsigned int inputHeight,
179 unsigned int desiredWidth,
180 unsigned int desiredHeight,
181 BoxDimensionTest dimensionTest,
182 unsigned int& outWidth,
183 unsigned int& outHeight );
186 * @copydoc DownscaleInPlacePow2RGB888
188 * For single-byte formats such as lum8 or alpha8.
190 void DownscaleInPlacePow2SingleBytePerPixel( unsigned char * pixels,
191 unsigned int inputWidth,
192 unsigned int inputHeight,
193 unsigned int desiredWidth,
194 unsigned int desiredHeight,
195 BoxDimensionTest dimensionTest,
196 unsigned int& outWidth,
197 unsigned int& outHeight );
200 * @brief Rescales an input image into the exact output dimensions passed-in.
202 * Uses point sampling, equivalent to GL_NEAREST texture filter mode, for the
203 * fastest results, at the expense of aliasing (noisy images) when downscaling.
204 * @note inPixels is allowed to alias outPixels if this is a downscaling,
205 * but not for upscaling.
207 void PointSample( const unsigned char * inPixels,
208 unsigned int inputWidth,
209 unsigned int inputHeight,
210 Pixel::Format pixelFormat,
211 unsigned char * outPixels,
212 unsigned int desiredWidth,
213 unsigned int desiredHeight );
216 * @copydoc PointSample
218 * Specialised for 4-byte formats like RGBA8888 and BGRA8888.
220 void PointSample4BPP( const unsigned char * inPixels,
221 unsigned int inputWidth,
222 unsigned int inputHeight,
223 unsigned char * outPixels,
224 unsigned int desiredWidth,
225 unsigned int desiredHeight );
228 * @copydoc PointSample
230 * Specialised for 3-byte formats like RGB888 and BGR888.
232 void PointSample3BPP( const unsigned char * inPixels,
233 unsigned int inputWidth,
234 unsigned int inputHeight,
235 unsigned char * outPixels,
236 unsigned int desiredWidth,
237 unsigned int desiredHeight );
240 * @copydoc PointSample
242 * Specialised for 2-byte formats like LA88.
244 void PointSample2BPP( const unsigned char * inPixels,
245 unsigned int inputWidth,
246 unsigned int inputHeight,
247 unsigned char * outPixels,
248 unsigned int desiredWidth,
249 unsigned int desiredHeight );
252 * @copydoc PointSample
254 * Specialised for 1-byte formats like L8 and A8.
256 void PointSample1BPP( const unsigned char * inPixels,
257 unsigned int inputWidth,
258 unsigned int inputHeight,
259 unsigned char * outPixels,
260 unsigned int desiredWidth,
261 unsigned int desiredHeight );
264 * @brief Resample input image to output image using a bilinear filter.
266 * Each output pixel is formed of a weighted sum of a 2x2 block of four input
268 * @pre inPixels must not alias outPixels. The input image should be a totally
269 * separate buffer from the input one.
271 void LinearSample( const unsigned char * __restrict__ inPixels,
272 ImageDimensions inDimensions,
273 Pixel::Format pixelFormat,
274 unsigned char * __restrict__ outPixels,
275 ImageDimensions outDimensions );
278 * @copydoc LinearSample
280 * Specialised for one byte per pixel formats.
282 void LinearSample1BPP( const unsigned char * __restrict__ inPixels,
283 ImageDimensions inputDimensions,
284 unsigned char * __restrict__ outPixels,
285 ImageDimensions desiredDimensions );
288 * @copydoc LinearSample
290 * Specialised for two byte per pixel formats.
292 void LinearSample2BPP( const unsigned char * __restrict__ inPixels,
293 ImageDimensions inputDimensions,
294 unsigned char * __restrict__ outPixels,
295 ImageDimensions desiredDimensions );
298 * @copydoc LinearSample
300 * Specialised for RGB565 16 bit pixel format.
302 void LinearSampleRGB565( const unsigned char * __restrict__ inPixels,
303 ImageDimensions inputDimensions,
304 unsigned char * __restrict__ outPixels,
305 ImageDimensions desiredDimensions );
308 * @copydoc LinearSample
310 * Specialised for three byte per pixel formats like RGB888.
312 void LinearSample3BPP( const unsigned char * __restrict__ inPixels,
313 ImageDimensions inputDimensions,
314 unsigned char * __restrict__ outPixels,
315 ImageDimensions desiredDimensions );
318 * @copydoc LinearSample
320 * Specialised for four byte per pixel formats like RGBA8888.
321 * @note, If used on RGBA8888, the A component will be blended independently.
323 void LinearSample4BPP( const unsigned char * __restrict__ inPixels,
324 ImageDimensions inputDimensions,
325 unsigned char * __restrict__ outPixels,
326 ImageDimensions desiredDimensions );
331 * @defgroup ScalingAlgorithmFragments Composable subunits of the scaling algorithms.
336 * @brief Average adjacent pairs of pixels, overwriting the input array.
337 * @param[in,out] pixels The array of pixels to work on.
338 * @param[i] width The number of pixels in the array passed-in.
340 void HalveScanlineInPlaceRGB888( unsigned char * pixels, unsigned int width );
343 * @copydoc HalveScanlineInPlaceRGB888
345 void HalveScanlineInPlaceRGBA8888( unsigned char * pixels, unsigned int width );
348 * @copydoc HalveScanlineInPlaceRGB888
350 void HalveScanlineInPlaceRGB565( unsigned char * pixels, unsigned int width );
353 * @copydoc HalveScanlineInPlaceRGB888
355 void HalveScanlineInPlace2Bytes( unsigned char * pixels, unsigned int width );
358 * @copydoc HalveScanlineInPlaceRGB888
360 void HalveScanlineInPlace1Byte( unsigned char * pixels, unsigned int width );
363 * @brief Average pixels at corresponding offsets in two scanlines.
365 * outputScanline is allowed to alias scanline1.
366 * @param[in] scanline1 First scanline of pixels to average.
367 * @param[in] scanline2 Second scanline of pixels to average.
368 * @param[out] outputScanline Destination for the averaged pixels.
369 * @param[in] width The widths of all the scanlines passed-in.
371 void AverageScanlines1( const unsigned char * scanline1,
372 const unsigned char * scanline2,
373 unsigned char* outputScanline,
374 /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/
375 unsigned int width );
378 * @copydoc AverageScanlines1
380 void AverageScanlines2( const unsigned char * scanline1,
381 const unsigned char * scanline2,
382 unsigned char* outputScanline,
383 /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/
384 unsigned int width );
387 * @copydoc AverageScanlines1
389 void AverageScanlines3( const unsigned char * scanline1,
390 const unsigned char * scanline2,
391 unsigned char* outputScanline,
392 /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/
393 unsigned int width );
396 * @copydoc AverageScanlines1
398 void AverageScanlinesRGBA8888( const unsigned char * scanline1,
399 const unsigned char * scanline2,
400 unsigned char * outputScanline,
401 unsigned int width );
404 * @copydoc AverageScanlines1
406 void AverageScanlinesRGB565( const unsigned char * scanline1,
407 const unsigned char * scanline2,
408 unsigned char* outputScanline,
409 unsigned int width );
413 * @defgroup TestableInlines Inline functions exposed in header to allow unit testing.
418 * @brief Average two integer arguments.
419 * @return The average of two uint arguments.
420 * @param[in] a First component to average.
421 * @param[in] b Second component to average.
423 inline unsigned int AverageComponent( unsigned int a, unsigned int b )
425 unsigned int avg = (a + b) >> 1u;
430 * @brief Average a pair of RGBA8888 pixels.
431 * @return The average of two RGBA8888 pixels.
432 * @param[in] a First pixel to average.
433 * @param[in] b Second pixel to average
435 inline uint32_t AveragePixelRGBA8888( uint32_t a, uint32_t b )
437 const unsigned int avg =
438 ((AverageComponent( (a & 0xff000000) >> 1u, (b & 0xff000000) >> 1u ) << 1u) & 0xff000000 ) +
439 (AverageComponent( a & 0x00ff0000, b & 0x00ff0000 ) & 0x00ff0000 ) +
440 (AverageComponent( a & 0x0000ff00, b & 0x0000ff00 ) & 0x0000ff00 ) +
441 (AverageComponent( a & 0x000000ff, b & 0x000000ff ) );
443 ///@ToDo: Optimise by trying return (((a ^ b) & 0xfefefefeUL) >> 1) + (a & b);
444 ///@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.
448 * @brief Average a pair of RGB565 pixels.
449 * @param a[in] Low 16 bits hold a color value as RGB565 to average with parameter b.
450 * @param b[in] Low 16 bits hold a color value as RGB565 to average with parameter a.
451 * @return The average color of the two RGB565 pixels passed in, in the low 16 bits of the returned value.
453 inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b )
455 const unsigned int avg =
456 (AverageComponent( a & 0xf800, b & 0xf800 ) & 0xf800 ) +
457 (AverageComponent( a & 0x7e0, b & 0x7e0 ) & 0x7e0 ) +
458 (AverageComponent( a & 0x1f, b & 0x1f ) );
462 /** @return The weighted blend of two integers as a 16.16 fixed-point number, given a 0.16 fixed-point blending factor. */
463 inline unsigned int WeightedBlendIntToFixed1616(unsigned int a, unsigned int b, unsigned int fractBlend )
465 DALI_ASSERT_DEBUG( fractBlend <= 65535u && "Factor should be in 0.16 fixed-point." );
466 const unsigned int weightedAFixed = a * (65535u - fractBlend);
467 const unsigned int weightedBFixed = b * fractBlend;
468 const unsigned blended = (weightedAFixed + weightedBFixed);
472 /** @brief Blend two 16.16 inputs to give a 16.32 output. */
473 inline uint64_t WeightedBlendFixed1616ToFixed1632(unsigned int a, unsigned int b, unsigned int fractBlend )
475 DALI_ASSERT_DEBUG( fractBlend <= 65535u && "Factor should be in 0.16 fixed-point." );
476 // Blend while promoting intermediates to 16.32 fixed point:
477 const uint64_t weightedAFixed = uint64_t(a) * (65535u - fractBlend);
478 const uint64_t weightedBFixed = uint64_t(b) * fractBlend;
479 const uint64_t blended = (weightedAFixed + weightedBFixed);
484 * @brief Blend 4 taps into one value using horizontal and vertical weights.
486 inline unsigned int BilinearFilter1Component(unsigned int tl, unsigned int tr, unsigned int bl, unsigned int br, unsigned int fractBlendHorizontal, unsigned int fractBlendVertical )
488 DALI_ASSERT_DEBUG( fractBlendHorizontal <= 65535u && "Factor should be in 0.16 fixed-point." );
489 DALI_ASSERT_DEBUG( fractBlendVertical <= 65535u && "Factor should be in 0.16 fixed-point." );
491 const unsigned int topBlend = WeightedBlendIntToFixed1616( tl, tr, fractBlendHorizontal );
492 const unsigned int botBlend = WeightedBlendIntToFixed1616( bl, br, fractBlendHorizontal );
493 const uint64_t blended2x2 = WeightedBlendFixed1616ToFixed1632( topBlend, botBlend, fractBlendVertical );
494 const unsigned int rounded = (blended2x2 + (1u << 31u) ) >> 32u;
500 } /* namespace Platform */
501 } /* namespace Internal */
502 } /* namespace Dali */
504 #endif /* DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ */