/*
- * Copyright (c) 2017 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.
// INTERNAL INCLUDES
#include "pixel-manipulation.h"
#include "alpha-mask.h"
+#include "gaussian-blur.h"
#include <platform-abstractions/portable/image-operations.h>
+#include <platform-abstractions/portable/pixel-manipulation.h>
namespace Dali
{
namespace Adaptor
{
+namespace
+{
+const float TWO_PI = 2.f * Math::PI; ///< 360 degrees in radians
+} // namespace
+
PixelBuffer::PixelBuffer( unsigned char* buffer,
unsigned int bufferSize,
unsigned int width,
unsigned int height,
Dali::Pixel::Format pixelFormat )
-: mBuffer( buffer ),
+: mMetadata(),
+ mBuffer( buffer ),
mBufferSize( bufferSize ),
mWidth( width ),
mHeight( height ),
}
}
+void PixelBuffer::AllocateFixedSize( uint32_t size )
+{
+ ReleaseBuffer();
+ mBuffer = reinterpret_cast<unsigned char*>(malloc( size ));
+ mBufferSize = size;
+}
+
+void PixelBuffer::Rotate( Degree angle )
+{
+ // Check first if Rotate() can perform the operation in the current pixel buffer.
+
+ bool validPixelFormat = false;
+ switch( mPixelFormat )
+ {
+ case Pixel::A8:
+ case Pixel::L8:
+ case Pixel::LA88:
+ case Pixel::RGB888:
+ case Pixel::RGB8888:
+ case Pixel::BGR8888:
+ case Pixel::RGBA8888:
+ case Pixel::BGRA8888: // FALL THROUGH
+ {
+ validPixelFormat = true;
+ break;
+ }
+ default:
+ {
+ // This pixel format is not supported for this operation.
+ validPixelFormat = false;
+ break;
+ }
+ }
+
+ if( !validPixelFormat )
+ {
+ // Can't rotate the pixel buffer with the current pixel format.
+ DALI_LOG_ERROR( "Can't rotate the pixel buffer with the current pixel format\n" );
+ return;
+ }
+
+ float radians = Radian( angle ).radian;
+
+ // Transform the input angle into the range [0..2PI]
+ radians = fmod( radians, TWO_PI );
+ radians += ( radians < 0.f ) ? TWO_PI : 0.f;
+
+ if( radians < Dali::Math::MACHINE_EPSILON_10 )
+ {
+ // Nothing to do if the angle is zero.
+ return;
+ }
+
+ const unsigned int pixelSize = Pixel::GetBytesPerPixel( mPixelFormat );
+
+ uint8_t* pixelsOut = nullptr;
+ Platform::RotateByShear( mBuffer,
+ mWidth,
+ mHeight,
+ pixelSize,
+ radians,
+ pixelsOut,
+ mWidth,
+ mHeight );
+
+ // Release the memory of the current pixel buffer.
+ ReleaseBuffer();
+
+ // Set the new pixel buffer.
+ mBuffer = pixelsOut;
+ pixelsOut = nullptr;
+ mBufferSize = mWidth * mHeight * pixelSize;
+}
+
void PixelBuffer::ScaleAndCrop( float scaleFactor, ImageDimensions cropDimensions )
{
ImageDimensions outDimensions( float(mWidth) * scaleFactor,
}
+void PixelBuffer::SetMetadata( const Property::Map& map )
+{
+ mMetadata.reset(new Property::Map(map));
+}
+
+bool PixelBuffer::GetMetadata(Property::Map& outMetadata) const
+{
+ if( !mMetadata )
+ {
+ return false;
+ }
+ outMetadata = *mMetadata;
+ return true;
+}
+
+void PixelBuffer::SetMetadata(std::unique_ptr<Property::Map> metadata)
+{
+ mMetadata = std::move(metadata);
+}
+
void PixelBuffer::Resize( ImageDimensions outDimensions )
{
if( mWidth != outDimensions.GetWidth() || mHeight != outDimensions.GetHeight() )
return outBuffer;
}
+void PixelBuffer::ApplyGaussianBlur( const float blurRadius )
+{
+ // This method only works for pixel buffer in RGBA format.
+ if( mWidth > 0 && mHeight > 0 && mPixelFormat == Pixel::RGBA8888 )
+ {
+ if ( blurRadius > Math::MACHINE_EPSILON_1 )
+ {
+ PerformGaussianBlurRGBA( *this, blurRadius );
+ }
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Trying to apply gaussian blur to an empty pixel buffer or a pixel buffer not in RGBA format" );
+ }
+}
+
+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) )
+ {
+ unsigned char* pixel = mBuffer;
+ const unsigned int bufferSize = mWidth * mHeight;
+
+ for( unsigned int i=0; i<bufferSize; ++i )
+ {
+ unsigned int alpha = ReadChannel( pixel, mPixelFormat, Adaptor::ALPHA );
+ {
+ auto red = ReadChannel( pixel, mPixelFormat, Adaptor::RED);
+ auto green = ReadChannel( pixel, mPixelFormat, Adaptor::GREEN);
+ auto blue = ReadChannel( pixel, mPixelFormat, Adaptor::BLUE);
+ auto luminance = ReadChannel( pixel, mPixelFormat, Adaptor::LUMINANCE);
+ WriteChannel( pixel, mPixelFormat, Adaptor::RED, red*alpha / 255 );
+ WriteChannel( pixel, mPixelFormat, Adaptor::GREEN, green*alpha/255 );
+ WriteChannel( pixel, mPixelFormat, Adaptor::BLUE, blue*alpha/255 );
+ WriteChannel( pixel, mPixelFormat, Adaptor::LUMINANCE, luminance*alpha/255 );
+ }
+ pixel += bytesPerPixel;
+ }
+ }
+}
+
+
+
+
}// namespace Adaptor
}// namespace Internal
}// namespace Dali