*/
int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
{
- unsigned outWidth = -1, outHeight = -1;
+ unsigned outWidth = -1, outHeight = -1, outStride = -1;
// Do downscaling to 1 x 1 so we can easily assert the value of the single pixel produced:
unsigned char check_4x4[16 * 3] = {
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(check_4x4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(check_4x4, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(check_4x4[0], (unsigned char)0x7f, TEST_LOCATION);
// Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
unsigned char single_4x4[16 * 3] = {
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(single_4x4[0], (unsigned char)0xf, TEST_LOCATION);
// Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
// (white pixel at bottom-right of image)
unsigned char single_4x4_2[16 * 3] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4_2, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4_2, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(single_4x4_2[0], (unsigned char)0xf, TEST_LOCATION);
// Build a larger ~600 x ~600 uniform magenta image for tests which only test output dimensions:
}
// Scaling to 0 x 0 should stop at 1 x 1:
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+ DALI_TEST_CHECK(outStride == outWidth);
// Scaling to 1 x 1 should hit 1 x 1:
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 608, 608, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 608, 608, 608, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+ DALI_TEST_CHECK(outStride == outWidth);
// Scaling to original dimensions should NOP:
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 384, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 384, 384, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 384u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 384u, TEST_LOCATION);
+ DALI_TEST_CHECK(outStride == outWidth);
// More dimension tests:
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 44, 11, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 44, 11, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 44u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 44u, TEST_LOCATION);
+ DALI_TEST_CHECK(outStride == outWidth);
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 3, 48, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 3, 48, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_EQUALS(outWidth, 48u, TEST_LOCATION);
DALI_TEST_EQUALS(outHeight, 48u, TEST_LOCATION);
+ DALI_TEST_CHECK(outStride == outWidth);
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 3, 3, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 3, 3, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_CHECK(outWidth == 3u && outHeight == 3u);
+ DALI_TEST_CHECK(outStride == outWidth);
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 320, 320, 5, 5, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 320, 320, 320, 5, 5, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_CHECK(outWidth == 5u && outHeight == 5u);
+ DALI_TEST_CHECK(outStride == outWidth);
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 448, 448, 7, 7, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 448, 448, 448, 7, 7, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_CHECK(outWidth == 7u && outHeight == 7u);
+ DALI_TEST_CHECK(outStride == outWidth);
- Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 11, 11, BoxDimensionTestBoth, outWidth, outHeight);
+ Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 11, 11, BoxDimensionTestBoth, outWidth, outHeight, outStride);
DALI_TEST_CHECK(outWidth == 11u && outHeight == 11u);
+ DALI_TEST_CHECK(outStride == outWidth);
// Check that no pixel values were modified by the repeated averaging of identical pixels in tests above:
unsigned int numNonMagenta = 0u;
*/
void TestDownscaleOutputsExpectedDimensionsRGBA8888(uint32_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
{
- unsigned int resultingWidth = -1, resultingHeight = -1;
+ unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
Dali::Internal::Platform::DownscaleInPlacePow2RGBA8888(
reinterpret_cast<unsigned char*>(pixels),
inputWidth,
inputHeight,
+ inputWidth,
desiredWidth,
desiredHeight,
BoxDimensionTestBoth,
resultingWidth,
- resultingHeight);
+ resultingHeight,
+ resultingStride);
DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+ DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
}
/**
*/
void TestDownscaleOutputsExpectedDimensionsRGB565(uint16_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
{
- unsigned int resultingWidth = -1, resultingHeight = -1;
+ unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
Dali::Internal::Platform::DownscaleInPlacePow2RGB565(
reinterpret_cast<unsigned char*>(pixels),
inputWidth,
inputHeight,
+ inputWidth,
desiredWidth,
desiredHeight,
BoxDimensionTestBoth,
resultingWidth,
- resultingHeight);
+ resultingHeight,
+ resultingStride);
DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+ DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
}
/**
*/
void TestDownscaleOutputsExpectedDimensions2ComponentPair(uint8_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
{
- unsigned int resultingWidth = -1, resultingHeight = -1;
+ unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
Dali::Internal::Platform::DownscaleInPlacePow2ComponentPair(
pixels,
inputWidth,
inputHeight,
+ inputWidth,
desiredWidth,
desiredHeight,
BoxDimensionTestBoth,
resultingWidth,
- resultingHeight);
+ resultingHeight,
+ resultingStride);
DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+ DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
}
/**
*/
void TestDownscaleOutputsExpectedDimensionsSingleComponent(uint8_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
{
- unsigned int resultingWidth = -1, resultingHeight = -1;
+ unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
Dali::Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(
pixels,
inputWidth,
inputHeight,
+ inputWidth,
desiredWidth,
desiredHeight,
BoxDimensionTestBoth,
resultingWidth,
- resultingHeight);
+ resultingHeight,
+ resultingStride);
DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+ DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
}
/**
image[i] = 0xffffffff;
}
unsigned char* const pixels = reinterpret_cast<unsigned char*>(image);
- unsigned int resultingWidth = -1, resultingHeight = -1;
+ unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
// Test downscaling where the input size is an exact multiple of the desired size:
// (We expect a perfect result here)
- DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 75u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 75u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 512, 512, 16, 16, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 512, 512, 512, 16, 16, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 16u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 16u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 512, 64, 16, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 512, 64, 512, 16, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 16u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 2u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 64, 1024, 4, 64, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 64, 1024, 64, 4, 64, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 4u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 64u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
// Test downscaling where the input size is slightly off being an exact multiple of the desired size:
// (We expect a perfect match at the end because of rounding-down to an even width and height at each step)
- DownscaleInPlacePow2RGBA8888(pixels, 601, 603, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 601, 603, 601, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 75u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 75u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 736 + 1, 352 + 3, 23, 11, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 736 + 1, 352 + 3, 736 + 1, 23, 11, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 23u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 11u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 384 + 3, 896 + 1, 3, 7, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 384 + 3, 896 + 1, 384 + 3, 3, 7, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 3u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 7u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
// Test downscales with source dimensions which are under a nice power of two by one:
// The target is hit exactly due to losing spare columns or rows at each iteration:
- DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 7, 3, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 63, 7, 3, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 3u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
// Asking to downscale a bit smaller should stop at the dimensions of the last test as one more halving would go down to 3 x 1, which is too small.
- DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 4, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 63, 4, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 3u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
// Should stop at almost twice the requested dimensions:
- DownscaleInPlacePow2RGBA8888(pixels, 15, 127, 4, 32, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 15, 127, 15, 4, 32, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 63u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
// Test downscales to 1 in one or both dimensions:
// Parameters: input-x input-y, desired-x, desired-y, expected-x, expected-y
}
const uint32_t imageHash = HashPixels(image, numPixels);
unsigned char* const pixels = reinterpret_cast<unsigned char*>(image);
- unsigned int resultingWidth = -1, resultingHeight = -1;
+ unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
// Test downscales to the same size:
// The point is just to be sure the downscale is a NOP in this case:
- DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 600, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 600, 600, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 600u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 600u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 512, 128, 512, 128, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 512, 128, 512, 512, 128, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 512u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 128u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
- DownscaleInPlacePow2RGBA8888(pixels, 17, 1001, 17, 1001, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+ DownscaleInPlacePow2RGBA8888(pixels, 17, 1001, 17, 17, 1001, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
DALI_TEST_EQUALS(resultingWidth, 17u, TEST_LOCATION);
DALI_TEST_EQUALS(resultingHeight, 1001u, TEST_LOCATION);
+ DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
// Test downscales that request a larger size (we never upscale so these are NOPs too):
// Parameters: input-x input-y, desired-x, desired-y, expected-x, expected-y
int UtcDaliImageOperationsDownscaleInPlacePow2RGB565(void)
{
// Test that calling with null and zero parameters doesn't blow up:
- unsigned int outWidth, outHeight;
- DownscaleInPlacePow2RGB565(0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+ unsigned int outWidth, outHeight, outStride;
+ DownscaleInPlacePow2RGB565(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
uint16_t image[608 * 608];
for(unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i)
int UtcDaliImageOperationsDownscaleInPlacePow2ComponentPair(void)
{
// Simple test that a null pointer does not get dereferenced in the function:
- unsigned int outWidth, outHeight;
- DownscaleInPlacePow2ComponentPair(0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+ unsigned int outWidth, outHeight, outStride;
+ DownscaleInPlacePow2ComponentPair(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
// Simple tests of dimensions output:
int UtcDaliImageOperationsDownscaleInPlacePow2SingleBytePerPixel(void)
{
// Simple test that a null pointer does not get dereferenced in the function:
- unsigned int outWidth, outHeight;
- DownscaleInPlacePow2SingleBytePerPixel(0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+ unsigned int outWidth, outHeight, outStride;
+ DownscaleInPlacePow2SingleBytePerPixel(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
// Tests of output dimensions from downscaling:
uint8_t image[608 * 608];
uint32_t outputImage[desiredWidth * desiredHeight];
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)&image->GetVector()[0], 256, 256, (unsigned char*)outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)&image->GetVector()[0], 256, 256, 256, (unsigned char*)outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage[0], (uint32_t)0xff0000ff, TEST_LOCATION); // < Red corner pixel
DALI_TEST_EQUALS(outputImage[7], (uint32_t)0xff00ff00, TEST_LOCATION); // < Green corner pixel
buffer.resize(outputBufferSize);
uint32_t* outputImage = &buffer[0];
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, inputWidth, inputHeight, (unsigned char*)outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, inputWidth, inputHeight, inputWidth, (unsigned char*)outputImage, desiredWidth, desiredHeight);
// Check that all the output pixels are the right color:
const uint32_t reference = inputImage[inputWidth * inputHeight / 2];
// Try several different starting image sizes:
// 1x1 -> 1x1:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
outputImage = 0;
// Single-pixel wide tall stripe:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1024, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1024, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
outputImage = 0;
// Single-pixel tall, wide strip:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1024, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1024, 1, 1024, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
outputImage = 0;
// Square mid-size image:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, 103, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
outputImage = 0;
// Wide mid-size image:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, 313, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
outputImage = 0;
// Tall mid-size image:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 467, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 467, 53, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
outputImage = 0;
// 0 x 0 input image (make sure output not written to):
outputImage = 0xDEADBEEF;
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, 0, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
DALI_TEST_EQUALS(outputImage, (uint32_t)0xDEADBEEF, TEST_LOCATION);
outputImage = 0;
// Try several different starting image sizes:
// 1x1 -> 1x1:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, (unsigned char*)outputImage, 0, 0);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, 1, (unsigned char*)outputImage, 0, 0);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
// Single-pixel wide tall stripe:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 102, (unsigned char*)outputImage, 0, 33);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 102, 1, (unsigned char*)outputImage, 0, 33);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
// Single-pixel tall, wide strip:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 102, 1, (unsigned char*)outputImage, 0, 67);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 102, 1, 102, (unsigned char*)outputImage, 0, 67);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
// Square mid-size image:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, (unsigned char*)outputImage, 21, 0);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, 103, (unsigned char*)outputImage, 21, 0);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
// Wide mid-size image to 0 height
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, (unsigned char*)outputImage, 99, 0);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, 313, (unsigned char*)outputImage, 99, 0);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
// Tall mid-size image to 0 height, over width
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 46, (unsigned char*)outputImage, 9999, 0);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 46, 53, (unsigned char*)outputImage, 9999, 0);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
// 0 x 0 input image:
- Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, (unsigned char*)outputImage, 200, 99);
+ Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, 0, (unsigned char*)outputImage, 200, 99);
DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
END_TEST;
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
DALI_TEST_CHECK(pixelData);
DALI_TEST_EQUALS(pixelData.GetWidth(), 10, TEST_LOCATION);
DALI_TEST_EQUALS(pixelData.GetHeight(), 10, TEST_LOCATION);
+ DALI_TEST_EQUALS(pixelData.GetStride(), 10, TEST_LOCATION);
DALI_TEST_EQUALS(pixelData.GetPixelFormat(), Pixel::RGB565, TEST_LOCATION);
// Try drawing it
FillCheckerboard(pixbuf);
DALI_TEST_EQUALS(pixbuf.GetWidth(), 10, TEST_LOCATION);
+ DALI_TEST_EQUALS(pixbuf.GetStride(), 10, TEST_LOCATION);
END_TEST;
}
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
return GetImplementation(*this).GetHeight();
}
+unsigned int PixelBuffer::GetStride() const
+{
+ return GetImplementation(*this).GetStride();
+}
+
Pixel::Format PixelBuffer::GetPixelFormat() const
{
return GetImplementation(*this).GetPixelFormat();
#define DALI_PIXEL_BUFFER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
unsigned int GetHeight() const;
/**
+ * @brief Gets the stride of the buffer in pixels.
+ *
+ * @SINCE_2_1.17
+ * @return The stride of the buffer in pixels. 0 means the buffer is tightly packed.
+ */
+ unsigned int GetStride() const;
+
+ /**
* @brief Gets the pixel format.
*
* @SINCE_1_2.46
}
mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, info.srcStride);
+
mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
if(!isSubImage)
unsigned char* destBuffer = buffer.GetBuffer();
unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel(buffer.GetPixelFormat());
-
- int srcOffset = 0;
- int destOffset = 0;
+ unsigned int srcStrideBytes = mask.GetStride() * srcBytesPerPixel;
+ unsigned int destStrideBytes = buffer.GetStride() * destBytesPerPixel;
// if image is premultiplied, the other channels of the image need to multiply by alpha.
if(buffer.IsAlphaPreMultiplied())
{
for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
{
+ int srcOffset = 0;
+ int destOffset = 0;
+
for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
{
auto srcAlpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
srcOffset += srcBytesPerPixel;
destOffset += destBytesPerPixel;
}
+ srcBuffer += srcStrideBytes;
+ destBuffer += destStrideBytes;
}
}
}
{
for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
{
+ int srcOffset = 0;
+ int destOffset = 0;
+
for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
{
unsigned char srcAlpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
srcOffset += srcBytesPerPixel;
destOffset += destBytesPerPixel;
}
+ srcBuffer += srcStrideBytes;
+ destBuffer += destStrideBytes;
}
}
}
srcAlphaMask = 0xFF;
}
- unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
unsigned char* srcBuffer = mask.GetBuffer();
+ unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
+ unsigned int srcStrideBytes = mask.GetStride() * srcBytesPerPixel;
// Set up source color offsets
Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcColorPixelFormat);
+ unsigned int srcColorStrideBytes = buffer.GetStride() * srcColorBytesPerPixel;
// Setup destination offsets
Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
int destAlphaMask = 0;
Dali::Pixel::GetAlphaOffsetAndMask(destPixelFormat, destAlphaByteOffset, destAlphaMask);
- PixelBufferPtr newPixelBuffer = PixelBuffer::New(buffer.GetWidth(), buffer.GetHeight(), destPixelFormat);
- unsigned char* destBuffer = newPixelBuffer->GetBuffer();
- unsigned char* oldBuffer = buffer.GetBuffer();
+ PixelBufferPtr newPixelBuffer = PixelBuffer::New(buffer.GetWidth(), buffer.GetHeight(), destPixelFormat);
+ unsigned char* destBuffer = newPixelBuffer->GetBuffer();
+ unsigned char* oldBuffer = buffer.GetBuffer();
+ unsigned int destStrideBytes = newPixelBuffer->GetStride() * destBytesPerPixel;
- int srcAlphaOffset = 0;
- int srcColorOffset = 0;
- int destOffset = 0;
- bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
+ bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
unsigned char destAlpha = 0;
for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
{
+ int srcAlphaOffset = 0;
+ int srcColorOffset = 0;
+ int destOffset = 0;
for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
{
unsigned char srcAlpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
srcAlphaOffset += srcBytesPerPixel;
destOffset += destBytesPerPixel;
}
+ oldBuffer += srcColorStrideBytes;
+ srcBuffer += srcStrideBytes;
+ destBuffer += destStrideBytes;
}
return newPixelBuffer;
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
*/
// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include <memory.h>
#include <cmath>
unsigned char* outBuffer,
const unsigned int bufferWidth,
const unsigned int bufferHeight,
+ const unsigned int inBufferStride,
+ const unsigned int outBufferStride,
const float blurRadius)
{
// Calculate the weights for gaussian blur
for(unsigned int y = 0; y < bufferHeight; y++)
{
unsigned int targetPixelIndex = y;
- unsigned int ioffset = y * bufferWidth;
+ unsigned int ioffset = y * inBufferStride;
for(unsigned int x = 0; x < bufferWidth; x++)
{
float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f;
outBuffer[targetPixelIndex * 4 + 2] = std::max(0, std::min(static_cast<int>(b + 0.5f), 255));
outBuffer[targetPixelIndex * 4 + 3] = std::max(0, std::min(static_cast<int>(a + 0.5f), 255));
- targetPixelIndex += bufferHeight;
+ targetPixelIndex += outBufferStride;
}
}
{
unsigned int bufferWidth = buffer.GetWidth();
unsigned int bufferHeight = buffer.GetHeight();
+ unsigned int bufferStride = buffer.GetStride();
+
+ if(bufferWidth == 0 || bufferHeight == 0 || bufferStride == 0 || buffer.GetPixelFormat() != Pixel::RGBA8888)
+ {
+ DALI_LOG_ERROR("Invalid buffer!\n");
+ return;
+ }
// Create a temporary buffer for the two-pass blur
PixelBufferPtr softShadowImageBuffer = PixelBuffer::New(bufferWidth, bufferHeight, Pixel::RGBA8888);
- memcpy(softShadowImageBuffer->GetBuffer(), buffer.GetBuffer(), 4u * bufferWidth * bufferHeight);
// We perform the blur first but write its output image buffer transposed, so that we
// can just do it in two passes. The first pass blurs horizontally and transposes, the
// second pass does the same, but as the image is now transposed, it's really doing a
// vertical blur. The second transposition makes the image the right way up again. This
// is much faster than doing a 2D convolution.
- ConvoluteAndTranspose(buffer.GetBuffer(), softShadowImageBuffer->GetBuffer(), bufferWidth, bufferHeight, blurRadius);
- ConvoluteAndTranspose(softShadowImageBuffer->GetBuffer(), buffer.GetBuffer(), bufferHeight, bufferWidth, blurRadius);
+ ConvoluteAndTranspose(buffer.GetBuffer(), softShadowImageBuffer->GetBuffer(), bufferWidth, bufferHeight, bufferStride, bufferHeight, blurRadius);
+ ConvoluteAndTranspose(softShadowImageBuffer->GetBuffer(), buffer.GetBuffer(), bufferHeight, bufferWidth, bufferHeight, bufferStride, blurRadius);
// On leaving scope, softShadowImageBuffer will get destroyed.
}
using Integration::Bitmap;
using Integration::BitmapPtr;
-typedef unsigned char PixelBuffer;
+typedef uint8_t PixelBuffer;
/**
* @brief 4 byte pixel structure.
* @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] strideIn The stride of the input buffer.
* @param[in] pixelSize The size of the pixel.
* @param[out] pixelsOut The rotated output buffer.
* @param[out] widthOut The width of the output buffer.
bool Rotate90(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
uint8_t*& pixelsOut,
unsigned int& widthOut,
heightOut = widthIn;
// Allocate memory for the rotated buffer.
+ // Output buffer is tightly packed
pixelsOut = static_cast<uint8_t*>(malloc(widthOut * heightOut * pixelSize));
if(nullptr == pixelsOut)
{
// Rotate the buffer.
for(unsigned int y = 0u; y < heightIn; ++y)
{
- const unsigned int srcLineIndex = y * widthIn;
+ const unsigned int srcLineIndex = y * strideIn;
const unsigned int dstX = y;
for(unsigned int x = 0u; x < widthIn; ++x)
{
* @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] strideIn The stride of the input buffer.
* @param[in] pixelSize The size of the pixel.
* @param[out] pixelsOut The rotated output buffer.
*
bool Rotate180(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
uint8_t*& pixelsOut)
{
// Allocate memory for the rotated buffer.
+ // Output buffer is tightly packed
pixelsOut = static_cast<uint8_t*>(malloc(widthIn * heightIn * pixelSize));
if(nullptr == pixelsOut)
{
// Rotate the buffer.
for(unsigned int y = 0u; y < heightIn; ++y)
{
- const unsigned int srcLineIndex = y * widthIn;
+ const unsigned int srcLineIndex = y * strideIn;
const unsigned int dstY = heightIn - y - 1u;
for(unsigned int x = 0u; x < widthIn; ++x)
{
* @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] strideIn The stride of the input buffer.
* @param[in] pixelSize The size of the pixel.
* @param[out] pixelsOut The rotated output buffer.
* @param[out] widthOut The width of the output buffer.
bool Rotate270(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
uint8_t*& pixelsOut,
unsigned int& widthOut,
heightOut = widthIn;
// Allocate memory for the rotated buffer.
+ // Output buffer is tightly packed
pixelsOut = static_cast<uint8_t*>(malloc(widthOut * heightOut * pixelSize));
if(nullptr == pixelsOut)
{
// Rotate the buffer.
for(unsigned int y = 0u; y < heightIn; ++y)
{
- const unsigned int srcLineIndex = y * widthIn;
+ const unsigned int srcLineIndex = y * strideIn;
const unsigned int dstX = widthOut - y - 1u;
for(unsigned int x = 0u; x < widthIn; ++x)
{
*
* @param[in] srcBufferPtr Pointer to the input pixel buffer.
* @param[in] srcWidth The width of the input pixel buffer.
+ * @param[in] srcStride The stride of the input pixel buffer.
* @param[in] pixelSize The size of the pixel.
* @param[in,out] dstPixelBuffer Pointer to the output pixel buffer.
* @param[in] dstWidth The width of the output pixel buffer.
*/
void HorizontalSkew(const uint8_t* const srcBufferPtr,
int srcWidth,
+ int srcStride,
unsigned int pixelSize,
uint8_t*& dstBufferPtr,
int dstWidth,
for(i = 0u; i < srcWidth; ++i)
{
// Loop through row pixels
- const unsigned int srcIndex = pixelSize * (row * srcWidth + i);
+ const unsigned int srcIndex = pixelSize * (row * srcStride + i);
unsigned char src[4u] = {0u, 0u, 0u, 0u};
for(unsigned int channel = 0u; channel < pixelSize; ++channel)
* @param[in] srcBufferPtr Pointer to the input pixel buffer.
* @param[in] srcWidth The width of the input pixel buffer.
* @param[in] srcHeight The height of the input pixel buffer.
+ * @param[in] srcStride The stride of the input pixel buffer.
* @param[in] pixelSize The size of the pixel.
* @param[in,out] dstPixelBuffer Pointer to the output pixel buffer.
* @param[in] dstWidth The width of the output pixel buffer.
void VerticalSkew(const uint8_t* const srcBufferPtr,
int srcWidth,
int srcHeight,
+ int srcStride,
unsigned int pixelSize,
uint8_t*& dstBufferPtr,
int dstWidth,
for(i = 0; i < srcHeight; ++i)
{
// Loop through column pixels
- const unsigned int srcIndex = pixelSize * (i * srcWidth + column);
+ const unsigned int srcIndex = pixelSize * (i * srcStride + column);
unsigned char src[4u] = {0u, 0u, 0u, 0u};
for(unsigned int channel = 0u; channel < pixelSize; ++channel)
{
const unsigned int inputWidth = bitmap.GetWidth();
const unsigned int inputHeight = bitmap.GetHeight();
+ const unsigned int inputStride = bitmap.GetStride();
if(desiredDimensions.GetWidth() < 1u || desiredDimensions.GetHeight() < 1u)
{
// Add some pre-calculated offsets to the bitmap pointers so this is not done within a loop.
// The cropping is added to the source pointer, and the padding is added to the destination.
const auto bytesPerPixel = Pixel::GetBytesPerPixel(pixelFormat);
- const PixelBuffer* const sourcePixels = bitmap.GetBuffer() + ((((scanlinesToCrop / 2) * inputWidth) + (columnsToCrop / 2)) * bytesPerPixel);
+ const PixelBuffer* const sourcePixels = bitmap.GetBuffer() + ((((scanlinesToCrop / 2) * inputStride) + (columnsToCrop / 2)) * bytesPerPixel);
PixelBuffer* const targetPixels = croppedBitmap.GetBuffer();
PixelBuffer* const targetPixelsActive = targetPixels + ((((scanlinesToPad / 2) * desiredWidth) + (columnsToPad / 2)) * bytesPerPixel);
DALI_ASSERT_DEBUG(sourcePixels && targetPixels);
// Copy the image data to the new bitmap.
// Optimize to a single memcpy if the left and right edges don't need a crop or a pad.
unsigned int outputSpan(desiredWidth * bytesPerPixel);
- if(columnsToCrop == 0 && columnsToPad == 0)
+ if(columnsToCrop == 0 && columnsToPad == 0 && inputStride == inputWidth)
{
memcpy(targetPixelsActive, sourcePixels, (desiredHeight - scanlinesToPad) * outputSpan);
}
{
// The width needs to change (due to either a crop or a pad), so we copy a scanline at a time.
// Precalculate any constants to optimize the inner loop.
- const unsigned int inputSpan(inputWidth * bytesPerPixel);
+ const unsigned int inputSpan(inputStride * bytesPerPixel);
const unsigned int copySpan((desiredWidth - columnsToPad) * bytesPerPixel);
const unsigned int scanlinesToCopy(desiredHeight - scanlinesToPad);
// Source dimensions as loaded from resources (e.g. filesystem):
auto bitmapWidth = bitmap.GetWidth();
auto bitmapHeight = bitmap.GetHeight();
+ auto bitmapStride = bitmap.GetStride();
// Desired dimensions (the rectangle to fit the source image to):
auto desiredWidth = desired.GetWidth();
auto desiredHeight = desired.GetHeight();
auto pixelFormat = bitmap.GetPixelFormat();
// Do the fast power of 2 iterated box filter to get to roughly the right side if the filter mode requests that:
- unsigned int shrunkWidth = -1, shrunkHeight = -1;
- DownscaleInPlacePow2(bitmap.GetBuffer(), pixelFormat, bitmapWidth, bitmapHeight, desiredWidth, desiredHeight, fittingMode, samplingMode, shrunkWidth, shrunkHeight);
+ unsigned int shrunkWidth = -1, shrunkHeight = -1, outStride = -1;
+ DownscaleInPlacePow2(bitmap.GetBuffer(), pixelFormat, bitmapWidth, bitmapHeight, bitmapStride, desiredWidth, desiredHeight, fittingMode, samplingMode, shrunkWidth, shrunkHeight, outStride);
// Work out the dimensions of the downscaled bitmap, given the scaling mode and desired dimensions:
const ImageDimensions filteredDimensions = FitToScalingMode(ImageDimensions(desiredWidth, desiredHeight), ImageDimensions(shrunkWidth, shrunkHeight), fittingMode);
{
if(samplingMode == SamplingMode::LINEAR || samplingMode == SamplingMode::BOX_THEN_LINEAR)
{
- LinearSample(bitmap.GetBuffer(), ImageDimensions(shrunkWidth, shrunkHeight), pixelFormat, outputBitmap.GetBuffer(), filteredDimensions);
+ LinearSample(bitmap.GetBuffer(), ImageDimensions(shrunkWidth, shrunkHeight), outStride, pixelFormat, outputBitmap.GetBuffer(), filteredDimensions);
}
else
{
- PointSample(bitmap.GetBuffer(), shrunkWidth, shrunkHeight, pixelFormat, outputBitmap.GetBuffer(), filteredWidth, filteredHeight);
+ PointSample(bitmap.GetBuffer(), shrunkWidth, shrunkHeight, outStride, pixelFormat, outputBitmap.GetBuffer(), filteredWidth, filteredHeight);
}
filtered = true;
}
// Copy out the 2^x downscaled, box-filtered pixels if no secondary filter (point or linear) was applied:
if(filtered == false && (shrunkWidth < bitmapWidth || shrunkHeight < bitmapHeight))
{
+ // The buffer is downscaled and it is tightly packed. We don't need to set a stride.
outputBitmap = MakePixelBuffer(bitmap.GetBuffer(), pixelFormat, shrunkWidth, shrunkHeight);
}
}
void DownscaleInPlacePow2Generic(unsigned char* const pixels,
const unsigned int inputWidth,
const unsigned int inputHeight,
+ const unsigned int inputStride,
const unsigned int desiredWidth,
const unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned& outWidth,
- unsigned& outHeight)
+ unsigned& outHeight,
+ unsigned& outStride)
{
if(pixels == 0)
{
// Scale the image until it would be smaller than desired, stopping if the
// resulting height or width would be less than 1:
- unsigned int scaledWidth = inputWidth, scaledHeight = inputHeight;
+ unsigned int scaledWidth = inputWidth, scaledHeight = inputHeight, stride = inputStride;
while(ContinueScaling(dimensionTest, scaledWidth, scaledHeight, desiredWidth, desiredHeight))
{
- const unsigned int lastWidth = scaledWidth;
+ const unsigned int lastWidth = scaledWidth;
+ const unsigned int lastStride = stride;
scaledWidth >>= 1u;
scaledHeight >>= 1u;
+ stride = scaledWidth;
DALI_LOG_INFO(gImageOpsLogFilter, Dali::Integration::Log::Verbose, "Scaling to %u\t%u.\n", scaledWidth, scaledHeight);
for(unsigned int y = 0; y <= lastScanlinePair; ++y)
{
// Scale two scanlines horizontally:
- HalveScanlineInPlace(&pixels[y * 2 * lastWidth * BYTES_PER_PIXEL], lastWidth);
- HalveScanlineInPlace(&pixels[(y * 2 + 1) * lastWidth * BYTES_PER_PIXEL], lastWidth);
+ HalveScanlineInPlace(&pixels[y * 2 * lastStride * BYTES_PER_PIXEL], lastWidth);
+ HalveScanlineInPlace(&pixels[(y * 2 + 1) * lastStride * BYTES_PER_PIXEL], lastWidth);
// Scale vertical pairs of pixels while the last two scanlines are still warm in
// the CPU cache(s):
// images but even a 4k wide RGB888 image will use just 24kB of cache (4k pixels
// * 3 Bpp * 2 scanlines) for two scanlines on the first iteration.
AverageScanlines(
- &pixels[y * 2 * lastWidth * BYTES_PER_PIXEL],
- &pixels[(y * 2 + 1) * lastWidth * BYTES_PER_PIXEL],
+ &pixels[y * 2 * lastStride * BYTES_PER_PIXEL],
+ &pixels[(y * 2 + 1) * lastStride * BYTES_PER_PIXEL],
&pixels[y * scaledWidth * BYTES_PER_PIXEL],
scaledWidth);
}
///@note: we could finish off with one of two mutually exclusive passes, one squashing horizontally as far as possible, and the other vertically, if we knew a following cpu point or bilinear filter would restore the desired aspect ratio.
outWidth = scaledWidth;
outHeight = scaledHeight;
+ outStride = stride;
}
} // namespace
Pixel::Format pixelFormat,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
FittingMode::Type fittingMode,
SamplingMode::Type samplingMode,
unsigned& outWidth,
- unsigned& outHeight)
+ unsigned& outHeight,
+ unsigned& outStride)
{
outWidth = inputWidth;
outHeight = inputHeight;
+ outStride = inputStride;
// Perform power of 2 iterated 4:1 box filtering if the requested filter mode requires it:
if(samplingMode == SamplingMode::BOX || samplingMode == SamplingMode::BOX_THEN_NEAREST || samplingMode == SamplingMode::BOX_THEN_LINEAR)
{
{
case Pixel::RGBA8888:
{
- Internal::Platform::DownscaleInPlacePow2RGBA8888(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ Internal::Platform::DownscaleInPlacePow2RGBA8888(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
break;
}
case Pixel::RGB888:
{
- Internal::Platform::DownscaleInPlacePow2RGB888(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ Internal::Platform::DownscaleInPlacePow2RGB888(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
break;
}
case Pixel::RGB565:
{
- Internal::Platform::DownscaleInPlacePow2RGB565(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ Internal::Platform::DownscaleInPlacePow2RGB565(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
break;
}
case Pixel::LA88:
{
- Internal::Platform::DownscaleInPlacePow2ComponentPair(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ Internal::Platform::DownscaleInPlacePow2ComponentPair(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
break;
}
case Pixel::L8:
case Pixel::A8:
{
- Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
break;
}
default:
void DownscaleInPlacePow2RGB888(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned& outWidth,
- unsigned& outHeight)
+ unsigned& outHeight,
+ unsigned& outStride)
{
- DownscaleInPlacePow2Generic<3, HalveScanlineInPlaceRGB888, AverageScanlines3>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ DownscaleInPlacePow2Generic<3, HalveScanlineInPlaceRGB888, AverageScanlines3>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
}
void DownscaleInPlacePow2RGBA8888(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned& outWidth,
- unsigned& outHeight)
+ unsigned& outHeight,
+ unsigned& outStride)
{
DALI_ASSERT_DEBUG(((reinterpret_cast<ptrdiff_t>(pixels) & 3u) == 0u) && "Pointer should be 4-byte aligned for performance on some platforms.");
- DownscaleInPlacePow2Generic<4, HalveScanlineInPlaceRGBA8888, AverageScanlinesRGBA8888>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ DownscaleInPlacePow2Generic<4, HalveScanlineInPlaceRGBA8888, AverageScanlinesRGBA8888>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
}
void DownscaleInPlacePow2RGB565(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight)
+ unsigned int& outHeight,
+ unsigned int& outStride)
{
- DownscaleInPlacePow2Generic<2, HalveScanlineInPlaceRGB565, AverageScanlinesRGB565>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ DownscaleInPlacePow2Generic<2, HalveScanlineInPlaceRGB565, AverageScanlinesRGB565>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
}
/**
void DownscaleInPlacePow2ComponentPair(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned& outWidth,
- unsigned& outHeight)
+ unsigned& outHeight,
+ unsigned& outStride)
{
- DownscaleInPlacePow2Generic<2, HalveScanlineInPlace2Bytes, AverageScanlines2>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ DownscaleInPlacePow2Generic<2, HalveScanlineInPlace2Bytes, AverageScanlines2>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
}
void DownscaleInPlacePow2SingleBytePerPixel(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight)
+ unsigned int& outHeight,
+ unsigned int& outStride)
{
- DownscaleInPlacePow2Generic<1, HalveScanlineInPlace1Byte, AverageScanlines1>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+ DownscaleInPlacePow2Generic<1, HalveScanlineInPlace1Byte, AverageScanlines1>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
}
// Point sampling group below
inline void PointSampleAddressablePixels(const uint8_t* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
uint8_t* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight)
{
DALI_ASSERT_DEBUG(((desiredWidth <= inputWidth && desiredHeight <= inputHeight) ||
- outPixels >= inPixels + inputWidth * inputHeight * sizeof(PIXEL) || outPixels <= inPixels - desiredWidth * desiredHeight * sizeof(PIXEL)) &&
+ outPixels >= inPixels + inputStride * inputHeight * sizeof(PIXEL) || outPixels <= inPixels - desiredWidth * desiredHeight * sizeof(PIXEL)) &&
"The input and output buffers must not overlap for an upscaling.");
DALI_ASSERT_DEBUG(reinterpret_cast<uint64_t>(inPixels) % sizeof(PIXEL) == 0 && "Pixel pointers need to be aligned to the size of the pixels (E.g., 4 bytes for RGBA, 2 bytes for RGB565, ...).");
DALI_ASSERT_DEBUG(reinterpret_cast<uint64_t>(outPixels) % sizeof(PIXEL) == 0 && "Pixel pointers need to be aligned to the size of the pixels (E.g., 4 bytes for RGBA, 2 bytes for RGB565, ...).");
{
// Round fixed point y coordinate to nearest integer:
const unsigned int integerY = (inY + (1u << 15u)) >> 16u;
- const PIXEL* const inScanline = &inAligned[inputWidth * integerY];
+ const PIXEL* const inScanline = &inAligned[inputStride * integerY];
PIXEL* const outScanline = &outAligned[desiredWidth * outY];
DALI_ASSERT_DEBUG(integerY < inputHeight);
- DALI_ASSERT_DEBUG(reinterpret_cast<const uint8_t*>(inScanline) < (inPixels + inputWidth * inputHeight * sizeof(PIXEL)));
+ DALI_ASSERT_DEBUG(reinterpret_cast<const uint8_t*>(inScanline) < (inPixels + inputStride * inputHeight * sizeof(PIXEL)));
DALI_ASSERT_DEBUG(reinterpret_cast<uint8_t*>(outScanline) < (outPixels + desiredWidth * desiredHeight * sizeof(PIXEL)));
unsigned int inX = 0;
void PointSample4BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight)
{
- PointSampleAddressablePixels<uint32_t>(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSampleAddressablePixels<uint32_t>(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
}
// RGB565, LA88
void PointSample2BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight)
{
- PointSampleAddressablePixels<uint16_t>(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSampleAddressablePixels<uint16_t>(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
}
// L8, A8
void PointSample1BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight)
{
- PointSampleAddressablePixels<uint8_t>(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSampleAddressablePixels<uint8_t>(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
}
/* RGB888
void PointSample3BPP(const uint8_t* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
uint8_t* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight)
for(unsigned int outY = 0; outY < desiredHeight; ++outY)
{
const unsigned int integerY = (inY + (1u << 15u)) >> 16u;
- const uint8_t* const inScanline = &inPixels[inputWidth * integerY * BYTES_PER_PIXEL];
+ const uint8_t* const inScanline = &inPixels[inputStride * integerY * BYTES_PER_PIXEL];
uint8_t* const outScanline = &outPixels[desiredWidth * outY * BYTES_PER_PIXEL];
unsigned int inX = 0; //< 16.16 fixed-point input image x-coord.
void PointSample(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
Pixel::Format pixelFormat,
unsigned char* outPixels,
unsigned int desiredWidth,
{
case Pixel::RGB888:
{
- PointSample3BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSample3BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
break;
}
case Pixel::RGBA8888:
{
- PointSample4BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSample4BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
break;
}
case Pixel::RGB565:
case Pixel::LA88:
{
- PointSample2BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSample2BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
break;
}
case Pixel::L8:
case Pixel::A8:
{
- PointSample1BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+ PointSample1BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
break;
}
default:
bool DEBUG_ASSERT_ALIGNMENT>
inline void LinearSampleGeneric(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
const unsigned int desiredWidth = desiredDimensions.GetWidth();
const unsigned int desiredHeight = desiredDimensions.GetHeight();
- DALI_ASSERT_DEBUG(((outPixels >= inPixels + inputWidth * inputHeight * sizeof(PIXEL)) ||
+ DALI_ASSERT_DEBUG(((outPixels >= inPixels + inputStride * inputHeight * sizeof(PIXEL)) ||
(inPixels >= outPixels + desiredWidth * desiredHeight * sizeof(PIXEL))) &&
"Input and output buffers cannot overlap.");
if(DEBUG_ASSERT_ALIGNMENT)
DALI_ASSERT_DEBUG(integerY1 < inputHeight);
DALI_ASSERT_DEBUG(integerY2 < inputHeight);
- const PIXEL* const inScanline1 = &inAligned[inputWidth * integerY1];
- const PIXEL* const inScanline2 = &inAligned[inputWidth * integerY2];
+ const PIXEL* const inScanline1 = &inAligned[inputStride * integerY1];
+ const PIXEL* const inScanline2 = &inAligned[inputStride * integerY2];
unsigned int inX = 0;
for(unsigned int outX = 0; outX < desiredWidth; ++outX)
void LinearSample1BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
- LinearSampleGeneric<uint8_t, BilinearFilter1BPPByte, false>(inPixels, inputDimensions, outPixels, desiredDimensions);
+ LinearSampleGeneric<uint8_t, BilinearFilter1BPPByte, false>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
}
void LinearSample2BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
- LinearSampleGeneric<Pixel2Bytes, BilinearFilter2Bytes, true>(inPixels, inputDimensions, outPixels, desiredDimensions);
+ LinearSampleGeneric<Pixel2Bytes, BilinearFilter2Bytes, true>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
}
void LinearSampleRGB565(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
- LinearSampleGeneric<PixelRGB565, BilinearFilterRGB565, true>(inPixels, inputDimensions, outPixels, desiredDimensions);
+ LinearSampleGeneric<PixelRGB565, BilinearFilterRGB565, true>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
}
void LinearSample3BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
- LinearSampleGeneric<Pixel3Bytes, BilinearFilterRGB888, false>(inPixels, inputDimensions, outPixels, desiredDimensions);
+ LinearSampleGeneric<Pixel3Bytes, BilinearFilterRGB888, false>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
}
void LinearSample4BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
- LinearSampleGeneric<Pixel4Bytes, BilinearFilter4Bytes, true>(inPixels, inputDimensions, outPixels, desiredDimensions);
+ LinearSampleGeneric<Pixel4Bytes, BilinearFilter4Bytes, true>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
}
void Resample(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions,
Resampler::Filter filterType,
samples[i].ResizeUninitialized(srcWidth);
}
- const int srcPitch = srcWidth * numChannels;
+ const int srcPitch = inputStride * numChannels;
const int dstPitch = dstWidth * numChannels;
int dstY = 0;
void LanczosSample4BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
- Resample(inPixels, inputDimensions, outPixels, desiredDimensions, Resampler::LANCZOS4, 4, true);
+ Resample(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions, Resampler::LANCZOS4, 4, true);
}
void LanczosSample1BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions)
{
// For L8 images
- Resample(inPixels, inputDimensions, outPixels, desiredDimensions, Resampler::LANCZOS4, 1, false);
+ Resample(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions, Resampler::LANCZOS4, 1, false);
}
// Dispatch to a format-appropriate linear sampling function:
void LinearSample(const unsigned char* __restrict__ inPixels,
ImageDimensions inDimensions,
+ unsigned int inStride,
Pixel::Format pixelFormat,
unsigned char* __restrict__ outPixels,
ImageDimensions outDimensions)
{
case Pixel::RGB888:
{
- LinearSample3BPP(inPixels, inDimensions, outPixels, outDimensions);
+ LinearSample3BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
break;
}
case Pixel::RGBA8888:
{
- LinearSample4BPP(inPixels, inDimensions, outPixels, outDimensions);
+ LinearSample4BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
break;
}
case Pixel::L8:
case Pixel::A8:
{
- LinearSample1BPP(inPixels, inDimensions, outPixels, outDimensions);
+ LinearSample1BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
break;
}
case Pixel::LA88:
{
- LinearSample2BPP(inPixels, inDimensions, outPixels, outDimensions);
+ LinearSample2BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
break;
}
case Pixel::RGB565:
{
- LinearSampleRGB565(inPixels, inDimensions, outPixels, outDimensions);
+ LinearSampleRGB565(inPixels, inDimensions, inStride, outPixels, outDimensions);
break;
}
default:
void RotateByShear(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
float radians,
uint8_t*& pixelsOut,
fastRotationPerformed = Rotate90(pixelsIn,
widthIn,
heightIn,
+ strideIn,
pixelSize,
pixelsOut,
widthOut,
fastRotationPerformed = Rotate180(pixelsIn,
widthIn,
heightIn,
+ strideIn,
pixelSize,
pixelsOut);
fastRotationPerformed = Rotate270(pixelsIn,
widthIn,
heightIn,
+ strideIn,
pixelSize,
pixelsOut,
widthOut,
const uint8_t* const firstHorizontalSkewPixelsIn = fastRotationPerformed ? pixelsOut : pixelsIn;
std::unique_ptr<uint8_t, void (*)(void*)> tmpPixelsInPtr((fastRotationPerformed ? pixelsOut : nullptr), free);
+ unsigned int stride = fastRotationPerformed ? widthOut : strideIn;
+
// Reset the input/output
widthIn = widthOut;
heightIn = heightOut;
const float shear = angleTangent * ((angleTangent >= 0.f) ? (0.5f + static_cast<float>(y)) : (0.5f + static_cast<float>(y) - static_cast<float>(heightOut)));
const int intShear = static_cast<int>(floor(shear));
- HorizontalSkew(firstHorizontalSkewPixelsIn, widthIn, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
+ HorizontalSkew(firstHorizontalSkewPixelsIn, widthIn, stride, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
}
// Reset the 'pixel in' pointer with the output of the 'First Horizontal Skew' and free the memory allocated by the 'Fast Rotations'.
for(column = 0u; column < widthOut; ++column, offset -= angleSinus)
{
const int shear = static_cast<int>(floor(offset));
- VerticalSkew(tmpPixelsInPtr.get(), tmpWidthIn, tmpHeightIn, pixelSize, pixelsOut, widthOut, heightOut, column, shear, offset - static_cast<float>(shear));
+ VerticalSkew(tmpPixelsInPtr.get(), tmpWidthIn, tmpHeightIn, tmpWidthIn, pixelSize, pixelsOut, widthOut, heightOut, column, shear, offset - static_cast<float>(shear));
}
// Reset the 'pixel in' pointer with the output of the 'Vertical Skew' and free the memory allocated by the 'First Horizontal Skew'.
// Reset the input/output
for(unsigned int y = 0u; y < heightOut; ++y, offset += angleTangent)
{
const int shear = static_cast<int>(floor(offset));
- HorizontalSkew(tmpPixelsInPtr.get(), tmpWidthIn, pixelSize, pixelsOut, widthOut, y, shear, offset - static_cast<float>(shear));
+ HorizontalSkew(tmpPixelsInPtr.get(), tmpWidthIn, tmpWidthIn, pixelSize, pixelsOut, widthOut, y, shear, offset - static_cast<float>(shear));
}
// The deleter of the tmpPixelsInPtr unique pointer is called freeing the memory allocated by the 'Vertical Skew'.
void HorizontalShear(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
float radians,
uint8_t*& pixelsOut,
const float shear = radians * ((radians >= 0.f) ? (0.5f + static_cast<float>(y)) : (0.5f + static_cast<float>(y) - static_cast<float>(heightOut)));
const int intShear = static_cast<int>(floor(shear));
- HorizontalSkew(pixelsIn, widthIn, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
+ HorizontalSkew(pixelsIn, widthIn, strideIn, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
}
}
* @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] inputStride The stride 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.
+ * @param[out] outStride The resulting stride after downscaling.
*/
void DownscaleInPlacePow2(unsigned char* const pixels,
Pixel::Format pixelFormat,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
FittingMode::Type fittingMode,
SamplingMode::Type samplingMode,
unsigned& outWidth,
- unsigned& outHeight);
+ unsigned& outHeight,
+ unsigned& outStride);
/**
* @brief Destructive in-place downscaling by a power of 2 factor.
* @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] inputStride The stride 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.
+ * @param[out] outStride The resulting stride after downscaling.
*/
void DownscaleInPlacePow2RGB888(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight);
+ unsigned int& outHeight,
+ unsigned int& outStride);
/**
* @copydoc DownscaleInPlacePow2RGB888
void DownscaleInPlacePow2RGBA8888(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight);
+ unsigned int& outHeight,
+ unsigned int& outStride);
/**
* @copydoc DownscaleInPlacePow2RGB888
void DownscaleInPlacePow2RGB565(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight);
+ unsigned int& outHeight,
+ unsigned int& outStride);
/**
* @copydoc DownscaleInPlacePow2RGB888
void DownscaleInPlacePow2ComponentPair(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight);
+ unsigned int& outHeight,
+ unsigned int& outStride);
/**
* @copydoc DownscaleInPlacePow2RGB888
void DownscaleInPlacePow2SingleBytePerPixel(unsigned char* pixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned int desiredWidth,
unsigned int desiredHeight,
BoxDimensionTest dimensionTest,
unsigned int& outWidth,
- unsigned int& outHeight);
+ unsigned int& outHeight,
+ unsigned int& outStride);
/**
* @brief Rescales an input image into the exact output dimensions passed-in.
void PointSample(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
Pixel::Format pixelFormat,
unsigned char* outPixels,
unsigned int desiredWidth,
void PointSample4BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight);
void PointSample3BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight);
void PointSample2BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight);
void PointSample1BPP(const unsigned char* inPixels,
unsigned int inputWidth,
unsigned int inputHeight,
+ unsigned int inputStride,
unsigned char* outPixels,
unsigned int desiredWidth,
unsigned int desiredHeight);
*/
void LinearSample(const unsigned char* __restrict__ inPixels,
ImageDimensions inDimensions,
+ unsigned int inStride,
Pixel::Format pixelFormat,
unsigned char* __restrict__ outPixels,
ImageDimensions outDimensions);
*/
void LinearSample1BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*/
void LinearSample2BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*/
void LinearSampleRGB565(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*/
void LinearSample3BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*/
void LinearSample4BPP(const unsigned char* __restrict__ inPixels,
ImageDimensions inputDimensions,
+ unsigned int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*
* @param[in] inPixels Pointer to the input image buffer.
* @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride 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 int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*
* @param[in] inPixels Pointer to the input image buffer.
* @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride 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 int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions);
*
* @param[in] inPixels Pointer to the input image buffer.
* @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride 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 int inputStride,
unsigned char* __restrict__ outPixels,
ImageDimensions desiredDimensions,
Resampler::Filter filterType,
* @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] strideIn The stride 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.
void RotateByShear(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
float radians,
uint8_t*& pixelsOut,
* @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] strideIn The stride of the input buffer.
* @param[in] pixelSize The size of the pixel.
* @param[in] radians The shear angle in radians.
* @param[out] pixelsOut The rotated output buffer.
void HorizontalShear(const uint8_t* const pixelsIn,
unsigned int widthIn,
unsigned int heightIn,
+ unsigned int strideIn,
unsigned int pixelSize,
float radians,
uint8_t*& pixelsOut,
unsigned int bufferSize,
unsigned int width,
unsigned int height,
+ unsigned int stride,
Dali::Pixel::Format pixelFormat)
: mMetadata(),
mBuffer(buffer),
mBufferSize(bufferSize),
mWidth(width),
mHeight(height),
+ mStride(stride ? stride : width),
mPixelFormat(pixelFormat),
mPreMultiplied(false)
{
{
buffer = static_cast<unsigned char*>(malloc(bufferSize));
}
- return new PixelBuffer(buffer, bufferSize, width, height, pixelFormat);
+ return new PixelBuffer(buffer, bufferSize, width, height, width, pixelFormat);
}
PixelBufferPtr PixelBuffer::New(unsigned char* buffer,
unsigned int bufferSize,
unsigned int width,
unsigned int height,
+ unsigned int stride,
Dali::Pixel::Format pixelFormat)
{
- return new PixelBuffer(buffer, bufferSize, width, height, pixelFormat);
+ return new PixelBuffer(buffer, bufferSize, width, height, stride, pixelFormat);
}
Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer)
pixelBuffer.mBufferSize,
pixelBuffer.mWidth,
pixelBuffer.mHeight,
+ pixelBuffer.mStride,
pixelBuffer.mPixelFormat,
Dali::PixelData::FREE);
pixelBuffer.mBuffer = NULL;
pixelBuffer.mWidth = 0;
pixelBuffer.mHeight = 0;
pixelBuffer.mBufferSize = 0;
+ pixelBuffer.mStride = 0;
return pixelData;
}
return mHeight;
}
+uint32_t PixelBuffer::GetStride() const
+{
+ return mStride;
+}
+
Dali::Pixel::Format PixelBuffer::GetPixelFormat() const
{
return mPixelFormat;
memcpy(destBuffer, mBuffer, mBufferSize);
}
- Dali::PixelData pixelData = Dali::PixelData::New(destBuffer, mBufferSize, mWidth, mHeight, mPixelFormat, Dali::PixelData::FREE);
+ Dali::PixelData pixelData = Dali::PixelData::New(destBuffer, mBufferSize, mWidth, mHeight, mStride, mPixelFormat, Dali::PixelData::FREE);
return pixelData;
}
mBufferSize = pixelBuffer.mBufferSize;
mWidth = pixelBuffer.mWidth;
mHeight = pixelBuffer.mHeight;
+ mStride = pixelBuffer.mStride;
mPixelFormat = pixelBuffer.mPixelFormat;
}
Platform::RotateByShear(mBuffer,
mWidth,
mHeight,
+ mStride,
pixelSize,
radians,
pixelsOut,
mBuffer = pixelsOut;
pixelsOut = nullptr;
mBufferSize = mWidth * mHeight * pixelSize;
+ mStride = mWidth; // The buffer is tightly packed.
}
return success;
{
PixelBufferPtr outBuffer = PixelBuffer::New(cropDimensions.GetWidth(), cropDimensions.GetHeight(), inBuffer.GetPixelFormat());
int bytesPerPixel = Pixel::GetBytesPerPixel(inBuffer.mPixelFormat);
- int srcStride = inBuffer.mWidth * bytesPerPixel;
- int destStride = cropDimensions.GetWidth() * bytesPerPixel;
+ int srcStride = inBuffer.mStride * bytesPerPixel;
+ int destStride = cropDimensions.GetWidth() * bytesPerPixel; // The destination buffer is tightly packed
// Clamp crop to right edge
if(x + cropDimensions.GetWidth() > inBuffer.mWidth)
inBuffer.mPixelFormat == Pixel::RGBA8888 ||
inBuffer.mPixelFormat == Pixel::BGRA8888)
{
- Dali::Internal::Platform::Resample(inBuffer.mBuffer, inDimensions, outBuffer->GetBuffer(), outDimensions, filterType, bytesPerPixel, hasAlpha);
+ Dali::Internal::Platform::Resample(inBuffer.mBuffer, inDimensions, inBuffer.mStride, outBuffer->GetBuffer(), outDimensions, filterType, bytesPerPixel, hasAlpha);
}
else
{
// must be skipped in such case
if(Pixel::GetBytesPerPixel(mPixelFormat) && Pixel::HasAlpha(mPixelFormat))
{
- unsigned char* pixel = mBuffer;
- const unsigned int bufferSize = mWidth * mHeight;
+ unsigned char* pixel = mBuffer;
+ const unsigned int strideBytes = mStride * bytesPerPixel;
+ const unsigned int widthBytes = mWidth * bytesPerPixel;
// Collect all valid channel list before lookup whole buffer
std::vector<Channel> validChannelList;
if(DALI_LIKELY(!validChannelList.empty()))
{
- for(unsigned int i = 0; i < bufferSize; ++i)
+ for(unsigned int y = 0; y < mHeight; y++)
{
- unsigned int alpha = ReadChannel(pixel, mPixelFormat, Adaptor::ALPHA);
- if(alpha < 255)
+ for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
{
- // If alpha is 255, we don't need to change color. Skip current pixel
- // But if alpha is not 255, we should change color.
- if(alpha > 0)
+ unsigned int alpha = ReadChannel(&pixel[x], mPixelFormat, Adaptor::ALPHA);
+ if(alpha < 255)
{
- for(const Channel& channel : validChannelList)
+ // If alpha is 255, we don't need to change color. Skip current pixel
+ // But if alpha is not 255, we should change color.
+ if(alpha > 0)
{
- auto color = ReadChannel(pixel, mPixelFormat, channel);
- WriteChannel(pixel, mPixelFormat, channel, color * alpha / 255);
+ for(const Channel& channel : validChannelList)
+ {
+ auto color = ReadChannel(&pixel[x], mPixelFormat, channel);
+ WriteChannel(&pixel[x], mPixelFormat, channel, color * alpha / 255);
+ }
+ }
+ else
+ {
+ // If alpha is 0, just set all pixel as zero.
+ memset(&pixel[x], 0, bytesPerPixel);
}
- }
- else
- {
- // If alpha is 0, just set all pixel as zero.
- memset(pixel, 0, bytesPerPixel);
}
}
- pixel += bytesPerPixel;
+ pixel += strideBytes;
}
}
+ mPreMultiplied = true;
}
- mPreMultiplied = true;
}
bool PixelBuffer::IsAlphaPreMultiplied() const
uint32_t PixelBuffer::GetBrightness() const
{
- uint32_t brightness = 0;
-
+ uint32_t brightness = 0;
uint32_t bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
- if(bytesPerPixel)
+
+ if(bytesPerPixel && mWidth && mHeight)
{
- unsigned char* pixel = mBuffer;
- const uint32_t bufferSize = mWidth * mHeight;
+ unsigned char* pixel = mBuffer;
+ const uint32_t strideBytes = mStride * bytesPerPixel;
+ const uint32_t widthBytes = mWidth * bytesPerPixel;
+ const uint32_t bufferSize = mWidth * mHeight;
- if(bufferSize) // avoid division by zero to calculate brightness
- {
- uint64_t red = 0;
- uint64_t green = 0;
- uint64_t blue = 0;
+ uint64_t red = 0;
+ uint64_t green = 0;
+ uint64_t blue = 0;
- for(uint32_t i = 0; i < bufferSize; ++i)
+ for(unsigned int y = 0; y < mHeight; y++)
+ {
+ for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
{
- red += ReadChannel(pixel, mPixelFormat, Adaptor::RED);
- green += ReadChannel(pixel, mPixelFormat, Adaptor::GREEN);
- blue += ReadChannel(pixel, mPixelFormat, Adaptor::BLUE);
- pixel += bytesPerPixel;
+ red += ReadChannel(&pixel[x], mPixelFormat, Adaptor::RED);
+ green += ReadChannel(&pixel[x], mPixelFormat, Adaptor::GREEN);
+ blue += ReadChannel(&pixel[x], mPixelFormat, Adaptor::BLUE);
}
- // http://www.w3.org/TR/AERT#color-contrast
- brightness = (red * BRIGHTNESS_CONSTANT_R + green * BRIGHTNESS_CONSTANT_G + blue * BRIGHTNESS_CONSTANT_B) / (1000uLL * bufferSize);
+ pixel += strideBytes;
}
+
+ // http://www.w3.org/TR/AERT#color-contrast
+ brightness = (red * BRIGHTNESS_CONSTANT_R + green * BRIGHTNESS_CONSTANT_G + blue * BRIGHTNESS_CONSTANT_B) / (1000uLL * bufferSize);
}
return brightness;
#define DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
* @param [in] bufferSize The size of the buffer in bytes
* @param [in] width Buffer width in pixels
* @param [in] height Buffer height in pixels
+ * @param [in] stride Buffer stride in pixels, 0 means the buffer is tightly packed
* @param [in] pixelFormat The pixel format
- * @param [in] releaseFunction The function used to release the memory.
*/
static PixelBufferPtr New(unsigned char* buffer,
unsigned int bufferSize,
unsigned int width,
unsigned int height,
+ unsigned int stride,
Pixel::Format pixelFormat);
/**
* @param [in] bufferSize The size of the buffer in bytes
* @param [in] width Buffer width in pixels
* @param [in] height Buffer height in pixels
+ * @param [in] stride Buffer stride in pixels, 0 means the buffer is tightly packed
* @param [in] pixelFormat The pixel format
*/
PixelBuffer(unsigned char* buffer,
unsigned int bufferSize,
unsigned int width,
unsigned int height,
+ unsigned int stride,
Pixel::Format pixelFormat);
protected:
unsigned int GetHeight() const;
/**
+ * @brief Gets the stride of the buffer in pixels.
+ * @return The stride of the buffer in pixels. 0 means the buffer is tightly packed.
+ */
+ unsigned int GetStride() const;
+
+ /**
* Get the pixel format
* @return The pixel format
*/
private:
std::unique_ptr<Property::Map> mMetadata; ///< Metadata fields
- unsigned char* mBuffer; ///< The raw pixel data
- unsigned int mBufferSize; ///< Buffer sized in bytes
- unsigned int mWidth; ///< Buffer width in pixels
- unsigned int mHeight; ///< Buffer height in pixels
+ uint8_t* mBuffer; ///< The raw pixel data
+ uint32_t mBufferSize; ///< Buffer sized in bytes
+ uint32_t mWidth; ///< Buffer width in pixels
+ uint32_t mHeight; ///< Buffer height in pixels
+ uint32_t mStride; ///< Buffer stride in bytes, 0 means the buffer is tightly packed
Pixel::Format mPixelFormat; ///< Pixel format
bool mPreMultiplied; ///< PreMultiplied
};
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
Dali::Internal::Platform::RotateByShear(data.buffer,
data.width,
data.height,
+ data.width,
pixelSize,
radians,
pixelsOut,
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
{
Dali::Internal::Platform::LanczosSample4BPP(srcBuffer,
inputDimensions,
+ srcWidth,
data.buffer,
desiredDimensions);
}
Dali::Internal::Platform::HorizontalShear(pixelsIn,
width,
height,
+ width,
1u,
-TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE,
pixelsOut,