X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=platform-abstractions%2Fportable%2Fimage-operations.h;h=b83cca12a03814173af828ee54926506c990b009;hb=6774f439cf1f339c40364110cb2eebd185bff000;hp=de5bee7ab89c3f17223443a58cdcbdc052c4532a;hpb=0589d408a11b9f2f33a9a08b8ee39da150264220;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/platform-abstractions/portable/image-operations.h b/platform-abstractions/portable/image-operations.h index de5bee7..b83cca1 100644 --- a/platform-abstractions/portable/image-operations.h +++ b/platform-abstractions/portable/image-operations.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,20 @@ #ifndef DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ #define DALI_INTERNAL_PLATFORM_IMAGE_OPERATIONS_H_ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include -#include +#include +#include + +#ifdef DALI_ADAPTOR_COMPILATION +#include +#else +#include +#endif -// EXTERNAL INCLUDES -#include namespace Dali { @@ -44,19 +52,57 @@ enum BoxDimensionTest }; /** + * @brief The integer dimensions of an image or a region of an image packed into + * 16 bits per component. + * @note This can only be used for images of up to 65535 x 65535 pixels. + */ +typedef Uint16Pair ImageDimensions; + +/** + * @brief Work out the true desired width and height, accounting for special + * rules for zeros in either or both input requested dimensions. + * + * @param[in] rawDimensions Width and height of image before processing. + * @param[in] requestedDimensions Width and height of area to scale image into. Can be zero. + * @return Dimensions of area to scale image into after special rules are applied. + */ +ImageDimensions CalculateDesiredDimensions( ImageDimensions rawDimensions, ImageDimensions requestedDimensions ); + +/** + * @defgroup BitmapOperations Bitmap-to-Bitmap Image operations. + * @{ + */ + +/** * @brief Apply requested attributes to bitmap. + * + * This is the top-level function which runs the on-load image post-processing + * pipeline. Bitmaps enter here as loaded from the file system by the file + * loaders and leave downscaled and filtered as requested by the application, + * ready for use. + * * @param[in] bitmap The input bitmap. * @param[in] requestedAttributes Attributes which should be applied to bitmap. - * @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. + * @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. */ -Integration::BitmapPtr ApplyAttributesToBitmap( Integration::BitmapPtr bitmap, const ImageAttributes& requestedAttributes ); +Dali::Devel::PixelBuffer ApplyAttributesToBitmap( Dali::Devel::PixelBuffer bitmap, ImageDimensions dimensions, FittingMode::Type fittingMode = FittingMode::DEFAULT, SamplingMode::Type samplingMode = SamplingMode::DEFAULT ); /** * @brief Apply downscaling to a bitmap according to requested attributes. - * @note Only rough power of 2 box filtering is currently performed. - * @note The input bitmap may be modified and left in an invalid state so must be discarded. + * @note The input bitmap pixel buffer may be modified and used as scratch working space for efficiency, so it must be discarded. **/ -Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, const ImageAttributes& requestedAttributes ); +Dali::Devel::PixelBuffer DownscaleBitmap( Dali::Devel::PixelBuffer bitmap, + ImageDimensions desired, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode ); +/**@}*/ + +/** + * @defgroup ImageBufferScalingAlgorithms Pixel buffer-level scaling algorithms. + * @{ + */ /** * @brief Destructive in-place downscaling by a power of 2 factor. @@ -65,6 +111,7 @@ Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, const Image * of the next downscaling step would not be smaller than the desired * dimensions. * @param[in,out] pixels The buffer both to read from and write the result to. + * @param[in] pixelFormat The format of the image pointed at by pixels. * @param[in] inputWidth The width of the input image. * @param[in] inputHeight The height of the input image. * @param[in] desiredWidth The width the client is requesting. @@ -72,58 +119,301 @@ Integration::BitmapPtr DownscaleBitmap( Integration::Bitmap& bitmap, const Image * @param[out] outWidth The resulting width after downscaling. * @param[out] outHeight The resulting height after downscaling. */ -void DownscaleInPlacePow2RGB888( - unsigned char * pixels, - unsigned int inputWidth, unsigned int inputHeight, - unsigned int desiredWidth, unsigned int desiredHeight, - BoxDimensionTest dimensionTest, - unsigned int& outWidth, unsigned int& outHeight ); +void DownscaleInPlacePow2( unsigned char * const pixels, + Pixel::Format pixelFormat, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned int desiredWidth, + unsigned int desiredHeight, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + unsigned& outWidth, + unsigned& outHeight ); + +/** + * @brief Destructive in-place downscaling by a power of 2 factor. + * + * A box filter with a 2x2 kernel is repeatedly applied as long as the result + * of the next downscaling step would not be smaller than the desired + * dimensions. + * @param[in,out] pixels The buffer both to read from and write the result to. + * @param[in] inputWidth The width of the input image. + * @param[in] inputHeight The height of the input image. + * @param[in] desiredWidth The width the client is requesting. + * @param[in] desiredHeight The height the client is requesting. + * @param[out] outWidth The resulting width after downscaling. + * @param[out] outHeight The resulting height after downscaling. + */ +void DownscaleInPlacePow2RGB888( unsigned char * pixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned int desiredWidth, + unsigned int desiredHeight, + BoxDimensionTest dimensionTest, + unsigned int& outWidth, + unsigned int& outHeight ); /** * @copydoc DownscaleInPlacePow2RGB888 */ -void DownscaleInPlacePow2RGBA8888( - unsigned char * pixels, - unsigned int inputWidth, unsigned int inputHeight, - unsigned int desiredWidth, unsigned int desiredHeight, - BoxDimensionTest dimensionTest, - unsigned int& outWidth, unsigned int& outHeight ); +void DownscaleInPlacePow2RGBA8888( unsigned char * pixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned int desiredWidth, + unsigned int desiredHeight, + BoxDimensionTest dimensionTest, + unsigned int& outWidth, + unsigned int& outHeight ); /** * @copydoc DownscaleInPlacePow2RGB888 * * For the 2-byte packed 16 bit format RGB565. */ -void DownscaleInPlacePow2RGB565( - unsigned char * pixels, - unsigned int inputWidth, unsigned int inputHeight, - unsigned int desiredWidth, unsigned int desiredHeight, - BoxDimensionTest dimensionTest, - unsigned int& outWidth, unsigned int& outHeight ); +void DownscaleInPlacePow2RGB565( unsigned char * pixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned int desiredWidth, + unsigned int desiredHeight, + BoxDimensionTest dimensionTest, + unsigned int& outWidth, + unsigned int& outHeight ); /** * @copydoc DownscaleInPlacePow2RGB888 * * For 2-byte formats such as lum8alpha8, but not packed 16 bit formats like RGB565. */ -void DownscaleInPlacePow2ComponentPair( - unsigned char * pixels, - unsigned int inputWidth, unsigned int inputHeight, - unsigned int desiredWidth, unsigned int desiredHeight, - BoxDimensionTest dimensionTest, - unsigned int& outWidth, unsigned int& outHeight ); +void DownscaleInPlacePow2ComponentPair( unsigned char * pixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned int desiredWidth, + unsigned int desiredHeight, + BoxDimensionTest dimensionTest, + unsigned int& outWidth, + unsigned int& outHeight ); /** * @copydoc DownscaleInPlacePow2RGB888 * * For single-byte formats such as lum8 or alpha8. */ -void DownscaleInPlacePow2SingleBytePerPixel( - unsigned char * pixels, - unsigned int inputWidth, unsigned int inputHeight, - unsigned int desiredWidth, unsigned int desiredHeight, - BoxDimensionTest dimensionTest, - unsigned int& outWidth, unsigned int& outHeight ); +void DownscaleInPlacePow2SingleBytePerPixel( unsigned char * pixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned int desiredWidth, + unsigned int desiredHeight, + BoxDimensionTest dimensionTest, + unsigned int& outWidth, + unsigned int& outHeight ); + +/** + * @brief Rescales an input image into the exact output dimensions passed-in. + * + * Uses point sampling, equivalent to GL_NEAREST texture filter mode, for the + * fastest results, at the expense of aliasing (noisy images) when downscaling. + * @note inPixels is allowed to alias outPixels if this is a downscaling, + * but not for upscaling. + */ +void PointSample( const unsigned char * inPixels, + unsigned int inputWidth, + unsigned int inputHeight, + Pixel::Format pixelFormat, + unsigned char * outPixels, + unsigned int desiredWidth, + unsigned int desiredHeight ); + +/** + * @copydoc PointSample + * + * Specialised for 4-byte formats like RGBA8888 and BGRA8888. + */ +void PointSample4BPP( const unsigned char * inPixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned char * outPixels, + unsigned int desiredWidth, + unsigned int desiredHeight ); + +/** + * @copydoc PointSample + * + * Specialised for 3-byte formats like RGB888 and BGR888. + */ +void PointSample3BPP( const unsigned char * inPixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned char * outPixels, + unsigned int desiredWidth, + unsigned int desiredHeight ); + +/** + * @copydoc PointSample + * + * Specialised for 2-byte formats like LA88. + */ +void PointSample2BPP( const unsigned char * inPixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned char * outPixels, + unsigned int desiredWidth, + unsigned int desiredHeight ); + +/** + * @copydoc PointSample + * + * Specialised for 1-byte formats like L8 and A8. + */ +void PointSample1BPP( const unsigned char * inPixels, + unsigned int inputWidth, + unsigned int inputHeight, + unsigned char * outPixels, + unsigned int desiredWidth, + unsigned int desiredHeight ); + +/** + * @brief Resample input image to output image using a bilinear filter. + * + * Each output pixel is formed of a weighted sum of a 2x2 block of four input + * pixels + * @pre inPixels must not alias outPixels. The input image should be a totally + * separate buffer from the input one. + */ +void LinearSample( const unsigned char * __restrict__ inPixels, + ImageDimensions inDimensions, + Pixel::Format pixelFormat, + unsigned char * __restrict__ outPixels, + ImageDimensions outDimensions ); + +/** + * @copydoc LinearSample + * + * Specialised for one byte per pixel formats. + */ +void LinearSample1BPP( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @copydoc LinearSample + * + * Specialised for two byte per pixel formats. + */ +void LinearSample2BPP( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @copydoc LinearSample + * + * Specialised for RGB565 16 bit pixel format. + */ +void LinearSampleRGB565( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @copydoc LinearSample + * + * Specialised for three byte per pixel formats like RGB888. + */ +void LinearSample3BPP( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @copydoc LinearSample + * + * Specialised for four byte per pixel formats like RGBA8888. + * @note, If used on RGBA8888, the A component will be blended independently. + */ +void LinearSample4BPP( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @brief Resamples the input image with the Lanczos algorithm. + * + * @pre @p inPixels must not alias @p outPixels. The input image should be a totally + * separate buffer from the output buffer. + * + * @param[in] inPixels Pointer to the input image buffer. + * @param[in] inputDimensions The input dimensions of the image. + * @param[out] outPixels Pointer to the output image buffer. + * @param[in] desiredDimensions The output dimensions of the image. + */ +void LanczosSample4BPP( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @brief Resamples the input image with the Lanczos algorithm. + * + * @pre @p inPixels must not alias @p outPixels. The input image should be a totally + * separate buffer from the output buffer. + * + * @param[in] inPixels Pointer to the input image buffer. + * @param[in] inputDimensions The input dimensions of the image. + * @param[out] outPixels Pointer to the output image buffer. + * @param[in] desiredDimensions The output dimensions of the image. + */ +void LanczosSample1BPP( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions ); + +/** + * @brief Resamples the input image with the Lanczos algorithm. + * + * @pre @p inPixels must not alias @p outPixels. The input image should be a totally + * separate buffer from the output buffer. + * + * @param[in] inPixels Pointer to the input image buffer. + * @param[in] inputDimensions The input dimensions of the image. + * @param[out] outPixels Pointer to the output image buffer. + * @param[in] desiredDimensions The output dimensions of the image. + */ +void Resample( const unsigned char * __restrict__ inPixels, + ImageDimensions inputDimensions, + unsigned char * __restrict__ outPixels, + ImageDimensions desiredDimensions, + Resampler::Filter filterType, + int numChannels, bool hasAlpha ); + + +/** + * @brief Rotates the input image with an implementation of the 'Rotate by Shear' algorithm. + * + * @param[in] pixelsIn The input buffer. + * @param[in] widthIn The width of the input buffer. + * @param[in] heightIn The height of the input buffer. + * @param[in] pixelSize The size of the pixel. + * @param[in] radians The rotation angle in radians. + * @param[out] pixelsOut The rotated output buffer. + * @param[out] widthOut The width of the output buffer. + * @param[out] heightOut The height of the output buffer. + */ +void RotateByShear( const uint8_t* const pixelsIn, + unsigned int widthIn, + unsigned int heightIn, + unsigned int pixelSize, + float radians, + uint8_t*& pixelsOut, + unsigned int& widthOut, + unsigned int& heightOut ); + +/**@}*/ + +/** + * @defgroup ScalingAlgorithmFragments Composable subunits of the scaling algorithms. + * @{ + */ /** * @brief Average adjacent pairs of pixels, overwriting the input array. @@ -135,9 +425,7 @@ void HalveScanlineInPlaceRGB888( unsigned char * pixels, unsigned int width ); /** * @copydoc HalveScanlineInPlaceRGB888 */ -void HalveScanlineInPlaceRGBA8888( - unsigned char * pixels, - unsigned int width ); +void HalveScanlineInPlaceRGBA8888( unsigned char * pixels, unsigned int width ); /** * @copydoc HalveScanlineInPlaceRGB888 @@ -147,16 +435,12 @@ void HalveScanlineInPlaceRGB565( unsigned char * pixels, unsigned int width ); /** * @copydoc HalveScanlineInPlaceRGB888 */ -void HalveScanlineInPlace2Bytes( - unsigned char * pixels, - unsigned int width ); +void HalveScanlineInPlace2Bytes( unsigned char * pixels, unsigned int width ); /** * @copydoc HalveScanlineInPlaceRGB888 */ -void HalveScanlineInPlace1Byte( - unsigned char * pixels, - unsigned int width ); +void HalveScanlineInPlace1Byte( unsigned char * pixels, unsigned int width ); /** * @brief Average pixels at corresponding offsets in two scanlines. @@ -167,54 +451,52 @@ void HalveScanlineInPlace1Byte( * @param[out] outputScanline Destination for the averaged pixels. * @param[in] width The widths of all the scanlines passed-in. */ -void AverageScanlines1( - const unsigned char * scanline1, - const unsigned char * scanline2, - unsigned char* outputScanline, - /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/ - unsigned int width ); +void AverageScanlines1( const unsigned char * scanline1, + const unsigned char * scanline2, + unsigned char* outputScanline, + /** Image width in pixels (1 byte == 1 pixel: e.g. lum8 or alpha8).*/ + unsigned int width ); /** * @copydoc AverageScanlines1 */ -void AverageScanlines2( - const unsigned char * scanline1, - const unsigned char * scanline2, - unsigned char* outputScanline, - /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/ - unsigned int width ); +void AverageScanlines2( const unsigned char * scanline1, + const unsigned char * scanline2, + unsigned char* outputScanline, + /** Image width in pixels (2 bytes == 1 pixel: e.g. lum8alpha8).*/ + unsigned int width ); /** * @copydoc AverageScanlines1 */ -void AverageScanlines3( - const unsigned char * scanline1, - const unsigned char * scanline2, - unsigned char* outputScanline, - /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/ - unsigned int width ); +void AverageScanlines3( const unsigned char * scanline1, + const unsigned char * scanline2, + unsigned char* outputScanline, + /** Image width in pixels (3 bytes == 1 pixel: e.g. RGB888).*/ + unsigned int width ); /** * @copydoc AverageScanlines1 */ -void AverageScanlinesRGBA8888( - const unsigned char * scanline1, - const unsigned char * scanline2, - unsigned char * outputScanline, - unsigned int width ); +void AverageScanlinesRGBA8888( const unsigned char * scanline1, + const unsigned char * scanline2, + unsigned char * outputScanline, + unsigned int width ); /** * @copydoc AverageScanlines1 */ -void AverageScanlinesRGB565( - const unsigned char * scanline1, - const unsigned char * scanline2, - unsigned char* outputScanline, - unsigned int width ); +void AverageScanlinesRGB565( const unsigned char * scanline1, + const unsigned char * scanline2, + unsigned char* outputScanline, + unsigned int width ); +/**@}*/ /** - * @brief Inline functions exposed in header to allow unit testing. + * @defgroup TestableInlines Inline functions exposed in header to allow unit testing. + * @{ */ + /** * @brief Average two integer arguments. * @return The average of two uint arguments. @@ -228,7 +510,7 @@ inline unsigned int AverageComponent( unsigned int a, unsigned int b ) } /** - * @brief Average a pair of RGB565 pixels. + * @brief Average a pair of RGBA8888 pixels. * @return The average of two RGBA8888 pixels. * @param[in] a First pixel to average. * @param[in] b Second pixel to average @@ -260,6 +542,44 @@ inline uint32_t AveragePixelRGB565( uint32_t a, uint32_t b ) return avg; } +/** @return The weighted blend of two integers as a 16.16 fixed-point number, given a 0.16 fixed-point blending factor. */ +inline unsigned int WeightedBlendIntToFixed1616(unsigned int a, unsigned int b, unsigned int fractBlend ) +{ + DALI_ASSERT_DEBUG( fractBlend <= 65535u && "Factor should be in 0.16 fixed-point." ); + const unsigned int weightedAFixed = a * (65535u - fractBlend); + const unsigned int weightedBFixed = b * fractBlend; + const unsigned blended = (weightedAFixed + weightedBFixed); + return blended; +} + +/** @brief Blend two 16.16 inputs to give a 16.32 output. */ +inline uint64_t WeightedBlendFixed1616ToFixed1632(unsigned int a, unsigned int b, unsigned int fractBlend ) +{ + DALI_ASSERT_DEBUG( fractBlend <= 65535u && "Factor should be in 0.16 fixed-point." ); + // Blend while promoting intermediates to 16.32 fixed point: + const uint64_t weightedAFixed = uint64_t(a) * (65535u - fractBlend); + const uint64_t weightedBFixed = uint64_t(b) * fractBlend; + const uint64_t blended = (weightedAFixed + weightedBFixed); + return blended; +} + +/** + * @brief Blend 4 taps into one value using horizontal and vertical weights. + */ +inline unsigned int BilinearFilter1Component(unsigned int tl, unsigned int tr, unsigned int bl, unsigned int br, unsigned int fractBlendHorizontal, unsigned int fractBlendVertical ) +{ + DALI_ASSERT_DEBUG( fractBlendHorizontal <= 65535u && "Factor should be in 0.16 fixed-point." ); + DALI_ASSERT_DEBUG( fractBlendVertical <= 65535u && "Factor should be in 0.16 fixed-point." ); + + const unsigned int topBlend = WeightedBlendIntToFixed1616( tl, tr, fractBlendHorizontal ); + const unsigned int botBlend = WeightedBlendIntToFixed1616( bl, br, fractBlendHorizontal ); + const uint64_t blended2x2 = WeightedBlendFixed1616ToFixed1632( topBlend, botBlend, fractBlendVertical ); + const unsigned int rounded = (blended2x2 + (1u << 31u) ) >> 32u; + return rounded; +} + +/**@}*/ + } /* namespace Platform */ } /* namespace Internal */ } /* namespace Dali */