/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali/internal/imaging/common/pixel-buffer-impl.h>
// EXTERNAL INCLUDES
+#include <dali/integration-api/pixel-data-integ.h>
#include <stdlib.h>
#include <cstring>
// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include <dali/internal/imaging/common/alpha-mask.h>
#include <dali/internal/imaging/common/gaussian-blur.h>
#include <dali/internal/imaging/common/image-operations.h>
{
namespace
{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gPixelBufferFilter = Debug::Filter::New(Debug::NoLogging, false, "DALI_LOG_PIXEL_BUFFER_SIZE");
+#endif
+
const float TWO_PI = 2.f * Math::PI; ///< 360 degrees in radians
// based on W3C Recommendations (https://www.w3.org/TR/AERT/#color-contrast)
constexpr uint32_t BRIGHTNESS_CONSTANT_R = 299;
constexpr uint32_t BRIGHTNESS_CONSTANT_B = 114;
} // namespace
-PixelBuffer::PixelBuffer(unsigned char* buffer,
- unsigned int bufferSize,
- unsigned int width,
- unsigned int height,
- unsigned int stride,
+#if defined(DEBUG_ENABLED)
+uint32_t PixelBuffer::gPixelBufferAllocationTotal{0};
+#endif
+
+PixelBuffer::PixelBuffer(uint8_t* buffer,
+ uint32_t bufferSize,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
Dali::Pixel::Format pixelFormat)
: mMetadata(),
mBuffer(buffer),
ReleaseBuffer();
}
-PixelBufferPtr PixelBuffer::New(unsigned int width,
- unsigned int height,
+PixelBufferPtr PixelBuffer::New(uint32_t width,
+ uint32_t height,
Dali::Pixel::Format pixelFormat)
{
- unsigned int bufferSize = width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat);
- unsigned char* buffer = NULL;
+ uint32_t bufferSize = width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat);
+ uint8_t* buffer = NULL;
if(bufferSize > 0)
{
- buffer = static_cast<unsigned char*>(malloc(bufferSize));
+ buffer = static_cast<uint8_t*>(malloc(bufferSize));
+ if(DALI_UNLIKELY(!buffer))
+ {
+ DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", bufferSize);
+ }
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal += bufferSize;
+#endif
}
+ DALI_LOG_INFO(gPixelBufferFilter, Debug::Concise, "Allocated PixelBuffer of size %u\n", bufferSize);
+
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,
+PixelBufferPtr PixelBuffer::New(uint8_t* buffer,
+ uint32_t bufferSize,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
Dali::Pixel::Format pixelFormat)
{
return new PixelBuffer(buffer, bufferSize, width, height, stride, pixelFormat);
}
-Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer)
-{
- Dali::PixelData pixelData = Dali::PixelData::New(pixelBuffer.mBuffer,
- 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;
+Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer, bool releaseAfterUpload)
+{
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal -= pixelBuffer.mBufferSize;
+#endif
+ Dali::PixelData pixelData;
+ if(releaseAfterUpload)
+ {
+ pixelData = Dali::Integration::NewPixelDataWithReleaseAfterUpload(pixelBuffer.mBuffer,
+ pixelBuffer.mBufferSize,
+ pixelBuffer.mWidth,
+ pixelBuffer.mHeight,
+ pixelBuffer.mStride,
+ pixelBuffer.mPixelFormat,
+ Dali::PixelData::FREE);
+ }
+ else
+ {
+ pixelData = Dali::PixelData::New(pixelBuffer.mBuffer,
+ 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;
}
-unsigned int PixelBuffer::GetWidth() const
+uint32_t PixelBuffer::GetWidth() const
{
return mWidth;
}
-unsigned int PixelBuffer::GetHeight() const
+uint32_t PixelBuffer::GetHeight() const
{
return mHeight;
}
return mPixelFormat;
}
-unsigned char* PixelBuffer::GetBuffer() const
+uint8_t* PixelBuffer::GetBuffer() const
{
return mBuffer;
}
-const unsigned char* const PixelBuffer::GetConstBuffer() const
+const uint8_t* PixelBuffer::GetConstBuffer() const
{
return mBuffer;
}
-unsigned int PixelBuffer::GetBufferSize() const
+uint32_t PixelBuffer::GetBufferSize() const
{
return mBufferSize;
}
Dali::PixelData PixelBuffer::CreatePixelData() const
{
- unsigned char* destBuffer = NULL;
+ uint8_t* destBuffer = NULL;
if(mBufferSize > 0)
{
- destBuffer = static_cast<unsigned char*>(malloc(mBufferSize));
+ destBuffer = static_cast<uint8_t*>(malloc(mBufferSize));
+ if(DALI_UNLIKELY(!destBuffer))
+ {
+ DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", mBufferSize);
+ return Dali::PixelData();
+ }
memcpy(destBuffer, mBuffer, mBufferSize);
}
{
if(mBuffer)
{
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal -= mBufferSize;
+#endif
free(mBuffer);
+ mBuffer = nullptr;
}
}
ReleaseBuffer();
mBuffer = reinterpret_cast<unsigned char*>(malloc(size));
mBufferSize = size;
+ if(DALI_UNLIKELY(!mBuffer))
+ {
+ DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", mBufferSize);
+ }
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal += size;
+#endif
}
bool PixelBuffer::Rotate(Degree angle)
pixelsOut = nullptr;
mBufferSize = mWidth * mHeight * pixelSize;
mStride = mWidth; // The buffer is tightly packed.
+
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal += mBufferSize;
+#endif
}
return success;
destStride = (inBuffer.mWidth - x) * bytesPerPixel;
}
- int srcOffset = x * bytesPerPixel + y * srcStride;
- int destOffset = 0;
- unsigned char* destBuffer = outBuffer->mBuffer;
+ int srcOffset = x * bytesPerPixel + y * srcStride;
+ int destOffset = 0;
+ uint8_t* destBuffer = outBuffer->mBuffer;
// Clamp crop to last row
- unsigned int endRow = y + cropDimensions.GetHeight();
+ uint16_t endRow = y + cropDimensions.GetHeight();
if(endRow > inBuffer.mHeight)
{
endRow = inBuffer.mHeight - 1;
void PixelBuffer::MultiplyColorByAlpha()
{
- auto bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
-
// Compressed textures have unknown size of the pixel. Alpha premultiplication
// must be skipped in such case
- if(Pixel::GetBytesPerPixel(mPixelFormat) && Pixel::HasAlpha(mPixelFormat))
+ if(!Pixel::IsCompressed(mPixelFormat) && Pixel::HasAlpha(mPixelFormat))
{
- unsigned char* pixel = mBuffer;
- const unsigned int strideBytes = mStride * bytesPerPixel;
- const unsigned int widthBytes = mWidth * bytesPerPixel;
+ auto bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
+
+ uint8_t* pixel = mBuffer;
+ const uint32_t strideBytes = mStride * bytesPerPixel;
+ const uint32_t widthBytes = mWidth * bytesPerPixel;
// Collect all valid channel list before lookup whole buffer
std::vector<Channel> validChannelList;
if(DALI_LIKELY(!validChannelList.empty()))
{
- for(unsigned int y = 0; y < mHeight; y++)
+ for(uint32_t y = 0; y < mHeight; y++)
{
- for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
+ for(uint32_t x = 0; x < widthBytes; x += bytesPerPixel)
{
- unsigned int alpha = ReadChannel(&pixel[x], mPixelFormat, Adaptor::ALPHA);
+ uint32_t alpha = ReadChannel(&pixel[x], mPixelFormat, Adaptor::ALPHA);
if(alpha < 255)
{
// If alpha is 255, we don't need to change color. Skip current pixel
for(const Channel& channel : validChannelList)
{
auto color = ReadChannel(&pixel[x], mPixelFormat, channel);
- WriteChannel(&pixel[x], mPixelFormat, channel, color * alpha / 255);
+ WriteChannel(&pixel[x], mPixelFormat, channel, Platform::MultiplyAndNormalizeColor(color, alpha));
}
}
else
if(bytesPerPixel && mWidth && mHeight)
{
- unsigned char* pixel = mBuffer;
+ uint8_t* pixel = mBuffer;
const uint32_t strideBytes = mStride * bytesPerPixel;
const uint32_t widthBytes = mWidth * bytesPerPixel;
const uint32_t bufferSize = mWidth * mHeight;
uint64_t green = 0;
uint64_t blue = 0;
- for(unsigned int y = 0; y < mHeight; y++)
+ for(uint32_t y = 0; y < mHeight; y++)
{
- for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
+ for(uint32_t x = 0; x < widthBytes; x += bytesPerPixel)
{
red += ReadChannel(&pixel[x], mPixelFormat, Adaptor::RED);
green += ReadChannel(&pixel[x], mPixelFormat, Adaptor::GREEN);