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_
22 #include <dali/integration-api/bitmap.h>
23 #include <dali/public-api/images/image-attributes.h>
36 * @brief Identify which combination of x and y dimensions matter in terminating iterative box filtering.
40 BoxDimensionTestEither,
47 * @brief Simple class for passing around pairs of small ints.
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.
57 * @brief Default constructor for the (0, 0) vector.
59 Vector2Uint16() : mData(0) {}
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,
66 Vector2Uint16( uint32_t width, uint32_t height )
68 DALI_ASSERT_DEBUG( width < ( 1u << 16 ) && "Width parameter not representable." );
69 DALI_ASSERT_DEBUG( height < ( 1u << 16 ) && "Height parameter not representable." );
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.
76 mData = (height << 16u) + width;
80 * @brief Copy constructor.
82 Vector2Uint16( const Vector2Uint16& rhs )
88 * @returns the x dimension stored in this 2-tuple.
90 uint16_t GetWidth() const
92 return mComponents[0];
96 * @returns the y dimension stored in this 2-tuple.
98 uint16_t GetHeight() const
100 return mComponents[1];
104 * @returns the x dimension stored in this 2-tuple.
106 uint16_t GetX() const
108 return mComponents[0];
112 * @returns the y dimension stored in this 2-tuple.
114 uint16_t GetY() const
116 return mComponents[1];
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:
130 * @brief Human readable text output.
132 std::ostream& operator<<( std::ostream& o, const Vector2Uint16& vector );
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.
139 typedef Vector2Uint16 ImageDimensions;
142 * @defgroup BitmapOperations Bitmap-to-Bitmap Image operations.
147 * @brief Apply requested attributes to bitmap.
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,
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
160 Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, const ImageAttributes& requestedAttributes );
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.
166 Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, ImageDimensions desired, ImageAttributes::ScalingMode scalingMode, ImageAttributes::FilterMode filterMode );
170 * @defgroup ImageBufferScalingAlgorithms Pixel buffer-level scaling algorithms.
175 * @brief Destructive in-place downscaling by a power of 2 factor.
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
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.
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,
198 unsigned& outHeight );
201 * @brief Destructive in-place downscaling by a power of 2 factor.
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
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.
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 );
224 * @copydoc DownscaleInPlacePow2RGB888
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 );
236 * @copydoc DownscaleInPlacePow2RGB888
238 * For the 2-byte packed 16 bit format RGB565.
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 );
250 * @copydoc DownscaleInPlacePow2RGB888
252 * For 2-byte formats such as lum8alpha8, but not packed 16 bit formats like RGB565.
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 );
264 * @copydoc DownscaleInPlacePow2RGB888
266 * For single-byte formats such as lum8 or alpha8.
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 );
278 * @brief Rescales an input image into the exact output dimensions passed-in.
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.
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 );
294 * @copydoc PointSample
296 * Specialised for 4-byte formats like RGBA8888 and BGRA8888.
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 );
306 * @copydoc PointSample
308 * Specialised for 3-byte formats like RGB888 and BGR888.
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 );
318 * @copydoc PointSample
320 * Specialised for 2-byte formats like LA88.
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 );
330 * @copydoc PointSample
332 * Specialised for 1-byte formats like L8 and A8.
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 );
344 * @defgroup ScalingAlgorithmFragments Composable subunits of the scaling algorithms.
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.
353 void HalveScanlineInPlaceRGB888( unsigned char * pixels, unsigned int width );
356 * @copydoc HalveScanlineInPlaceRGB888
358 void HalveScanlineInPlaceRGBA8888( unsigned char * pixels, unsigned int width );
361 * @copydoc HalveScanlineInPlaceRGB888
363 void HalveScanlineInPlaceRGB565( unsigned char * pixels, unsigned int width );
366 * @copydoc HalveScanlineInPlaceRGB888
368 void HalveScanlineInPlace2Bytes( unsigned char * pixels, unsigned int width );
371 * @copydoc HalveScanlineInPlaceRGB888
373 void HalveScanlineInPlace1Byte( unsigned char * pixels, unsigned int width );
376 * @brief Average pixels at corresponding offsets in two scanlines.
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.
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 );
391 * @copydoc AverageScanlines1
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 );
400 * @copydoc AverageScanlines1
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 );
409 * @copydoc AverageScanlines1
411 void AverageScanlinesRGBA8888( const unsigned char * scanline1,
412 const unsigned char * scanline2,
413 unsigned char * outputScanline,
414 unsigned int width );
417 * @copydoc AverageScanlines1
419 void AverageScanlinesRGB565( const unsigned char * scanline1,
420 const unsigned char * scanline2,
421 unsigned char* outputScanline,
422 unsigned int width );
426 * @defgroup TestableInlines Inline functions exposed in header to allow unit testing.
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.
436 inline unsigned int AverageComponent( unsigned int a, unsigned int b )
438 unsigned int avg = (a + b) >> 1u;
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
448 inline uint32_t AveragePixelRGBA8888( uint32_t a, uint32_t b )
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 ) );
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.
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.
466 inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b )
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 ) );
477 } /* namespace Platform */
478 } /* namespace Internal */
479 } /* namespace Dali */
481 #endif /* DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ */