utc-Dali-Internal-MemoryPoolObjectAllocator.cpp
utc-Dali-Internal-FrustumCulling.cpp
utc-Dali-Internal-ActorDepth.cpp
+ utc-Dali-Internal-PixelData.cpp
)
LIST(APPEND TC_SOURCES
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+
+#include <dali/internal/event/images/pixel-manipulation.h>
+
+using namespace Dali;
+using namespace Dali::Internal::Pixel;
+void utc_dali_internal_pixel_data_startup()
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_pixel_data_cleanup()
+{
+ test_return_value = TET_PASS;
+}
+
+const char* ChannelToString( Dali::Internal::Pixel::Channel channel )
+{
+ switch(channel)
+ {
+ case LUMINANCE: return "Luminance";
+ case RED: return "Red";
+ case GREEN: return "Green";
+ case BLUE: return "Blue";
+ case ALPHA: return "Alpha";
+ default:
+ return "Unknown";
+ }
+}
+
+const char* FormatToString( Dali::Pixel::Format format )
+{
+ switch(format)
+ {
+ case Dali::Pixel::A8: return "A8";
+ case Dali::Pixel::L8: return "L8";
+ case Dali::Pixel::LA88: return "LA88";
+ case Dali::Pixel::RGB565: return "RGB565";
+ case Dali::Pixel::BGR565: return "BGR565";
+ case Dali::Pixel::RGBA4444: return "RGBA4444";
+ case Dali::Pixel::BGRA4444: return "BGRA4444";
+ case Dali::Pixel::RGBA5551: return "RGBA5551";
+ case Dali::Pixel::BGRA5551: return "BGRA5551";
+
+ case Dali::Pixel::RGB888: return "RGB888";
+ case Dali::Pixel::RGBA8888: return "RGBA8888";
+ case Dali::Pixel::BGRA8888: return "BGRA8888";
+
+ default:
+ return "Unknown";
+ }
+}
+
+
+int UtcDaliPixelManipulation01(void)
+{
+ tet_infoline("Testing Dali::Internal::PixelManipulation HasChannel");
+
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::A8, Dali::Internal::Pixel::ALPHA ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::A8, Dali::Internal::Pixel::LUMINANCE ), false, TEST_LOCATION );
+
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::L8, Dali::Internal::Pixel::LUMINANCE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::L8, Dali::Internal::Pixel::ALPHA ), false, TEST_LOCATION );
+
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::LA88, Dali::Internal::Pixel::LUMINANCE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::LA88, Dali::Internal::Pixel::ALPHA ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::LA88, Dali::Internal::Pixel::RED ), false, TEST_LOCATION );
+
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Pixel::RED ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Pixel::GREEN ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Pixel::BLUE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Pixel::LUMINANCE ), false, TEST_LOCATION );
+
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Pixel::RED ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Pixel::GREEN ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Pixel::BLUE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Pixel::ALPHA ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Pixel::LUMINANCE ), false, TEST_LOCATION );
+
+ DALI_TEST_EQUALS( Dali::Internal::Pixel::HasChannel( Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR, Dali::Internal::Pixel::BLUE ), false, TEST_LOCATION );
+
+ END_TEST;
+}
+
+
+
+int UtcDaliPixelManipulation02(void)
+{
+ tet_infoline("Testing Dali::Internal::PixelManipulation Read/WriteChannel");
+
+ unsigned char pixel[4] = {0,0,0,0};
+
+ for( int formatIdx=1; formatIdx<Dali::Pixel::COMPRESSED_R11_EAC; ++formatIdx)
+ {
+ pixel[0] = 0xFF;
+ pixel[1] = 0xFF;
+ pixel[2] = 0xFF;
+ pixel[3] = 0xFF;
+
+ for( int channelIdx=0; channelIdx < Dali::Internal::Pixel::MAX_NUMBER_OF_CHANNELS; ++channelIdx )
+ {
+ Dali::Pixel::Format format = static_cast<Dali::Pixel::Format>(formatIdx);
+ Dali::Internal::Pixel::Channel channel = static_cast<Dali::Internal::Pixel::Channel>(channelIdx);
+ if( Dali::Internal::Pixel::HasChannel( format, channel ) )
+ {
+ Dali::Internal::Pixel::WriteChannel( &pixel[0], format, channel, 0x15);
+ unsigned int value = Dali::Internal::Pixel::ReadChannel( &pixel[0], format, channel );
+
+ tet_printf( "Testing writing and reading to %s channel in %s format:\n",
+ ChannelToString(channel), FormatToString(format) );
+
+ if( channel == Dali::Internal::Pixel::ALPHA && (format == Dali::Pixel::RGBA5551 || format == Dali::Pixel::BGRA5551 ) )
+ {
+ DALI_TEST_EQUALS( value, 0x1, TEST_LOCATION );
+ }
+ else if( format == Dali::Pixel::RGBA4444 || format == Dali::Pixel::BGRA4444 )
+ {
+ DALI_TEST_EQUALS( value, 0x05, TEST_LOCATION );
+ }
+ else
+ {
+ DALI_TEST_EQUALS( value, 0x15, TEST_LOCATION );
+ }
+ }
+ }
+ }
+
+ END_TEST;
+}
+
+
+int UtcDaliPixelManipulation03N(void)
+{
+ tet_infoline("Testing Dali::Internal::PixelManipulation Read/WriteChannel");
+
+ unsigned char pixel[4] = {0,0,0,0};
+
+ for( int formatIdx=1; formatIdx<Dali::Pixel::COMPRESSED_R11_EAC; ++formatIdx)
+ {
+ pixel[0] = 0xFF;
+ pixel[1] = 0xFF;
+ pixel[2] = 0xFF;
+ pixel[3] = 0xFF;
+
+ for( int channelIdx=0; channelIdx < Dali::Internal::Pixel::MAX_NUMBER_OF_CHANNELS; ++channelIdx )
+ {
+ Dali::Pixel::Format format = static_cast<Dali::Pixel::Format>(formatIdx);
+ Dali::Internal::Pixel::Channel channel = static_cast<Dali::Internal::Pixel::Channel>(channelIdx);
+ if( ! Dali::Internal::Pixel::HasChannel( format, channel ) )
+ {
+ unsigned int value = Dali::Internal::Pixel::ReadChannel( &pixel[0], format, channel );
+
+ tet_printf( "Testing reading from %s channel in %s format:\n",
+ ChannelToString(channel), FormatToString(format) );
+
+ DALI_TEST_EQUALS( value, 0x00, TEST_LOCATION );
+ }
+ }
+ }
+
+ END_TEST;
+}
result = CompareType<Quaternion>(a, b, epsilon);
break;
}
+ case Property::STRING:
+ {
+ std::string a, b;
+ q1.Get(a);
+ q2.Get(b);
+ result = (a.compare(b) == 0);
+ break;
+ }
case Property::MATRIX:
case Property::MATRIX3:
- case Property::STRING:
case Property::ARRAY:
case Property::MAP:
{
#include <dali/public-api/images/pixel.h>
#include <dali/public-api/images/pixel-data.h>
+#include <dali/devel-api/images/pixel-data-mask.h>
#include <dali/public-api/common/dali-vector.h>
using namespace Dali;
END_TEST;
}
+
+int UtcDaliPixelDataMask01(void)
+{
+ TestApplication application;
+
+ unsigned int width = 10u;
+ unsigned int height = 10u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+ PixelData maskData = PixelData::New( buffer, bufferSize, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+ width = 20u;
+ height = 20u;
+ Pixel::Format pixelFormat = Pixel::RGBA5551;
+ bufferSize = width*height*Pixel::GetBytesPerPixel( pixelFormat );
+ buffer = new unsigned char [ bufferSize ];
+ PixelData imageData = PixelData::New( buffer, bufferSize, width, height, pixelFormat, PixelData::DELETE_ARRAY );
+
+ Dali::ApplyMask( imageData, maskData );
+
+ // Test that the pixel format has been promoted to RGBA8888
+ DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliPixelDataMask02(void)
+{
+ TestApplication application;
+
+ unsigned int width = 10u;
+ unsigned int height = 10u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+ PixelData maskData = PixelData::New( buffer, bufferSize, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+ width = 20u;
+ height = 20u;
+ Pixel::Format pixelFormat = Pixel::RGBA4444;
+ bufferSize = width*height*Pixel::GetBytesPerPixel( pixelFormat );
+ buffer = new unsigned char [ bufferSize ];
+ PixelData imageData = PixelData::New( buffer, bufferSize, width, height, pixelFormat, PixelData::DELETE_ARRAY );
+
+ Dali::ApplyMask( imageData, maskData );
+
+ // Test that the pixel format has been promoted to RGBA8888
+ DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliPixelDataMask03(void)
+{
+ TestApplication application;
+
+ unsigned int width = 20u;
+ unsigned int height = 20u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+ PixelData maskData = PixelData::New( buffer, bufferSize, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+ width = 10u;
+ height = 10u;
+ Pixel::Format format = Pixel::RGB565;
+ bufferSize = width*height*Pixel::GetBytesPerPixel( format );
+ buffer = new unsigned char [ bufferSize ];
+ PixelData imageData = PixelData::New( buffer, bufferSize, width, height, format, PixelData::DELETE_ARRAY );
+
+ Dali::ApplyMask( imageData, maskData );
+
+ // Test that the pixel format has been promoted to RGBA8888
+ DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ // Can't test the final image directly...
+
+ END_TEST;
+}
+
+
+int UtcDaliPixelDataMask04(void)
+{
+ TestApplication application;
+
+ unsigned int width = 10u;
+ unsigned int height = 10u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+ PixelData maskData = PixelData::New( buffer, bufferSize, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+ width = 20u;
+ height = 20u;
+ bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::RGBA8888 );
+ buffer = new unsigned char [ bufferSize ];
+ PixelData imageData = PixelData::New( buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::DELETE_ARRAY );
+
+ Dali::ApplyMask( imageData, maskData );
+
+ // Test that the pixel format hasn't changed
+ DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ // Can't test the final image directly...
+
+ END_TEST;
+}
+
+int UtcDaliPixelDataMask05(void)
+{
+ TestApplication application;
+
+ unsigned int width = 20u;
+ unsigned int height = 20u;
+ unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+ unsigned char* buffer = new unsigned char [ bufferSize ];
+ PixelData maskData = PixelData::New( buffer, bufferSize, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+ width = 10u;
+ height = 10u;
+ bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::RGBA8888 );
+ buffer = new unsigned char [ bufferSize ];
+ PixelData imageData = PixelData::New( buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::DELETE_ARRAY );
+
+ Dali::ApplyMask( imageData, maskData );
+
+ // Test that the pixel format hasn't changed
+ DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ // Can't test the final image directly...
+
+ END_TEST;
+}
$(devel_api_src_dir)/images/distance-field.cpp \
$(devel_api_src_dir)/images/texture-set-image.cpp \
$(devel_api_src_dir)/images/nine-patch-image.cpp \
+ $(devel_api_src_dir)/images/pixel-data-mask.cpp \
$(devel_api_src_dir)/object/handle-devel.cpp \
$(devel_api_src_dir)/object/weak-handle.cpp \
$(devel_api_src_dir)/object/csharp-type-registry.cpp \
$(devel_api_src_dir)/images/distance-field.h \
$(devel_api_src_dir)/images/native-image-interface-extension.h \
$(devel_api_src_dir)/images/texture-set-image.h \
- $(devel_api_src_dir)/images/nine-patch-image.h
+ $(devel_api_src_dir)/images/nine-patch-image.h \
+ $(devel_api_src_dir)/images/pixel-data-mask.h
devel_api_core_object_header_files = \
$(devel_api_src_dir)/object/csharp-type-info.h \
--- /dev/null
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/images/pixel-data-mask.h>
+#include <dali/internal/event/images/pixel-data-impl.h>
+
+namespace Dali
+{
+
+void ApplyMask( PixelData image, PixelData mask )
+{
+ if( image && mask )
+ {
+ GetImplementation(image).ApplyMask( GetImplementation(mask) );
+ }
+}
+
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_DEVEL_API_IMAGES_PIXEL_DATA_MASK_H
+#define DALI_DEVEL_API_IMAGES_PIXEL_DATA_MASK_H
+
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/images/pixel-data.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Apply the mask to this pixel data.
+ * If the mask image size is larger, then this will sample from
+ * the mask using bilinear filtering.
+ * @param[in] image The pixel data of the image
+ * @param[in] mask The pixel data of the mask
+ */
+DALI_IMPORT_API void ApplyMask( PixelData image, PixelData mask );
+
+} // namespace Dali
+
+#endif // DALI_DEVEL_API_IMAGES_PIXEL_DATA_MASK_H
// EXTERNAL INCLUDES
#include <stdlib.h>
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/pixel-manipulation.h>
+
namespace Dali
{
unsigned int bufferSize,
unsigned int width,
unsigned int height,
- Pixel::Format pixelFormat,
+ Dali::Pixel::Format pixelFormat,
Dali::PixelData::ReleaseFunction releaseFunction )
: mBuffer( buffer ),
mBufferSize( bufferSize ),
{
if( mBuffer )
{
- if( mReleaseFunction == Dali::PixelData::FREE)
- {
- free( mBuffer );
- }
- else
- {
- delete[] mBuffer;
- }
+ ReleaseBuffer();
}
- }
+}
PixelDataPtr PixelData::New(unsigned char* buffer,
unsigned int bufferSize,
unsigned int width,
unsigned int height,
- Pixel::Format pixelFormat,
+ Dali::Pixel::Format pixelFormat,
Dali::PixelData::ReleaseFunction releaseFunction)
{
return new PixelData( buffer, bufferSize, width, height, pixelFormat, releaseFunction );
return mHeight;
}
-Pixel::Format PixelData::GetPixelFormat() const
+Dali::Pixel::Format PixelData::GetPixelFormat() const
{
return mPixelFormat;
}
return mBufferSize;
}
+void PixelData::ReleaseBuffer()
+{
+ if( mReleaseFunction == Dali::PixelData::FREE)
+ {
+ free( mBuffer );
+ }
+ else
+ {
+ delete[] mBuffer;
+ }
+}
+
+void PixelData::ApplyMask( const PixelData& mask )
+{
+ int byteOffset=0;
+ int bitMask=0;
+ Dali::Pixel::GetAlphaOffsetAndMask(mPixelFormat, byteOffset, bitMask);
+
+ if( Dali::Pixel::HasAlpha( mPixelFormat ) && bitMask == 255 )
+ {
+ ApplyMaskToAlphaChannel( mask );
+ }
+ else
+ {
+ AddAlphaChannel(mask);
+ }
+}
+
+void PixelData::ApplyMaskToAlphaChannel( const PixelData& mask )
+{
+ const float rowFactor = float(mask.mHeight) / (1.0f * mHeight);
+ const float colFactor = float(mask.mWidth) / (1.0f * mWidth) ;
+
+ int numSamples = 1;
+ if( mask.mHeight > mHeight || mask.mWidth > mWidth )
+ {
+ numSamples = 4;
+ }
+
+ int srcAlphaByteOffset=0;
+ int srcAlphaMask=0;
+ Dali::Pixel::GetAlphaOffsetAndMask( mask.mPixelFormat, srcAlphaByteOffset, srcAlphaMask );
+
+ int destAlphaByteOffset=0;
+ int destAlphaMask=0;
+ Dali::Pixel::GetAlphaOffsetAndMask( mPixelFormat, destAlphaByteOffset, destAlphaMask );
+
+ unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mask.mPixelFormat );
+ unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
+ int srcStride = mask.mWidth * srcBytesPerPixel;
+
+ int srcOffset=0;
+ int destOffset=0;
+
+ float srcAlphaValue = 1.0f;
+
+ for( unsigned int row = 0; row < mHeight; ++row )
+ {
+ for( unsigned int col = 0; col < mWidth; ++col )
+ {
+ if( numSamples == 1 )
+ {
+ srcOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
+ unsigned char alpha = mask.mBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
+ srcAlphaValue = float(alpha)/255.0f;
+ }
+ else
+ {
+ srcAlphaValue = mask.ReadWeightedSample( col*colFactor, row*rowFactor );
+ }
+
+ unsigned char destAlpha = mBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
+ float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
+ destAlpha = destAlphaValue;
+ mBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
+ mBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
+
+ destOffset += destBytesPerPixel;
+ }
+ }
+}
+
+void PixelData::AddAlphaChannel( const PixelData& mask )
+{
+ const float rowFactor = float(mask.mHeight) / (1.0f * mHeight);
+ const float colFactor = float(mask.mWidth) / (1.0f * mWidth) ;
+
+ int numSamples = 1;
+ if( mask.mHeight > mHeight || mask.mWidth > mWidth )
+ {
+ numSamples = 4;
+ }
+
+ // Set up source alpha offsets
+ int srcAlphaByteOffset=0;
+ int srcAlphaMask=0;
+ Dali::Pixel::GetAlphaOffsetAndMask( mask.mPixelFormat, srcAlphaByteOffset, srcAlphaMask );
+
+ unsigned int srcAlphaBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mask.mPixelFormat );
+ int srcAlphaStride = mask.mWidth * srcAlphaBytesPerPixel;
+
+ // Set up source color offsets
+ unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
+
+ // Setup destination offsets
+ Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
+ unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( destPixelFormat );
+ int destAlphaByteOffset=0;
+ int destAlphaMask=0;
+ Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
+
+ int destBufferSize = mWidth * mHeight * destBytesPerPixel;
+ unsigned char* destBuffer = static_cast<unsigned char*>( malloc( destBufferSize ) );
+
+ int srcAlphaOffset=0;
+ int srcColorOffset=0;
+ int destOffset=0;
+ bool hasAlpha = Dali::Pixel::HasAlpha(mPixelFormat);
+
+ float srcAlphaValue = 1.0f;
+ unsigned char destAlpha = 0;
+
+ for( unsigned int row = 0; row < mHeight; ++row )
+ {
+ for( unsigned int col = 0; col < mWidth; ++col )
+ {
+ if( numSamples == 1 )
+ {
+ srcAlphaOffset = floorf(row * rowFactor) * srcAlphaStride + floorf(col * colFactor) * srcAlphaBytesPerPixel;
+ unsigned char alpha = mask.mBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
+ srcAlphaValue = float(alpha)/255.0f;
+ }
+ else
+ {
+ srcAlphaValue = mask.ReadWeightedSample( col*colFactor, row*rowFactor );
+ }
+
+ Pixel::ConvertColorChannelsToRGBA8888(mBuffer, srcColorOffset, mPixelFormat, destBuffer, destOffset );
+
+ if( hasAlpha )
+ {
+ destAlpha = mBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
+ float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
+ destAlpha = destAlphaValue;
+ }
+ else
+ {
+ destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
+ }
+
+ destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
+ destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
+
+ srcColorOffset += srcColorBytesPerPixel;
+ destOffset += destBytesPerPixel;
+ }
+ }
+
+ ReleaseBuffer();
+
+ mBuffer = destBuffer;
+ mBufferSize = destBufferSize;
+ mPixelFormat = Dali::Pixel::RGBA8888;
+ mReleaseFunction = Dali::PixelData::FREE;
+}
+
+float PixelData::ReadWeightedSample( float x, float y ) const
+{
+ unsigned int srcRow = floorf( y );
+ unsigned int srcCol = floorf( x );
+
+ int bytesPerPixel = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
+ int stride = mWidth * bytesPerPixel;
+ int srcOffset = srcRow * stride + srcCol * bytesPerPixel;
+ float samples[4];
+
+ samples[0] = ReadChannel( mBuffer + srcOffset, mPixelFormat, Pixel::ALPHA );
+
+ if( srcCol < mWidth-1 )
+ {
+ samples[1] = ReadChannel( mBuffer + srcOffset+bytesPerPixel, mPixelFormat, Pixel::ALPHA );
+ }
+ else
+ {
+ samples[1] = samples[0];
+ }
+
+ if( srcRow < mHeight-1 )
+ {
+ samples[2] = ReadChannel( mBuffer + stride + srcOffset, mPixelFormat, Pixel::ALPHA );
+ }
+ else
+ {
+ samples[2] = samples[0];
+ }
+
+ if( srcRow < mHeight-1 && srcCol < mWidth-1 )
+ {
+ samples[3] = ReadChannel( mBuffer + stride + srcOffset + bytesPerPixel, mPixelFormat, Pixel::ALPHA );
+ }
+ else
+ {
+ samples[3] = samples[2];
+ }
+
+ // Bilinear interpolation:
+ float weight[4];
+ weight[0] = float(srcRow+1.0f) - y;
+ weight[1] = y - float(srcRow);
+ weight[2] = float(srcCol+1.0f) - x;
+ weight[3] = x - float(srcCol);
+
+ return ( weight[2] * (samples[0] * weight[0] + samples[1] * weight[1]) +
+ weight[3] * (samples[2] * weight[0] + samples[3] * weight[1]) ) / 256.0f;
+}
+
+
}// namespace Internal
}// namespace Dali
*/
unsigned int GetBufferSize() const;
+ /**
+ * Apply the mask to this data
+ * @param[in] mask The mask to apply
+ */
+ void ApplyMask( const PixelData& mask );
+
private:
+ /**
+ * Release the buffer
+ */
+ void ReleaseBuffer();
- /*
+ /**
+ * Apply the mask to this data's alpha channel
+ * @param[in] mask The mask to apply
+ */
+ void ApplyMaskToAlphaChannel( const PixelData& mask );
+
+ /**
+ * Convert to RGBA8888 and apply the mask's alpha channel
+ * to this data's alpha channel
+ * @param[in] mask The mask to apply
+ */
+ void AddAlphaChannel( const PixelData& mask );
+
+ /**
+ * Apply the mask to this data's color channels (e.g. to apply vignette)
+ * @param[in] mask The mask to apply
+ */
+ void ApplyMaskToColorChannels( const PixelData& mask );
+
+ /**
+ * Read a weighted sample from a pixel (of unknown size)
+ * @param[in] x The x coordinate to sample from
+ * @param[in] y The y coordinate to sample from
+ */
+ float ReadWeightedSample( float x, float y ) const;
+
+ /*
* Undefined copy constructor.
*/
PixelData(const PixelData& other);
/*
* Undefined assignment operator.
*/
- PixelData& operator = (const PixelData& other);
+ PixelData& operator= (const PixelData& other);
private:
--- /dev/null
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/pixel-manipulation.h>
+
+// INTERNAL HEADERS
+#include <dali/public-api/images/pixel.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Pixel
+{
+
+struct Location
+{
+ unsigned int bitShift;
+ unsigned int bitMask;
+ bool available;
+};
+
+struct Locations
+{
+ Location luminance;
+ Location alpha;
+ Location red;
+ Location green;
+ Location blue;
+};
+
+
+bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel )
+{
+ switch (pixelFormat)
+ {
+ case Dali::Pixel::A8:
+ {
+ return (channel == ALPHA);
+ }
+ case Dali::Pixel::L8:
+ {
+ return (channel == LUMINANCE);
+ }
+ case Dali::Pixel::LA88:
+ {
+ return ( channel == LUMINANCE || channel == ALPHA );
+ }
+ case Dali::Pixel::RGB565:
+ case Dali::Pixel::BGR565:
+ case Dali::Pixel::RGB888:
+ case Dali::Pixel::RGB8888:
+ case Dali::Pixel::BGR8888:
+ {
+ return ( channel == RED || channel == GREEN || channel == BLUE );
+ }
+
+ case Dali::Pixel::RGBA8888:
+ case Dali::Pixel::BGRA8888:
+ case Dali::Pixel::RGBA4444:
+ case Dali::Pixel::BGRA4444:
+ case Dali::Pixel::RGBA5551:
+ case Dali::Pixel::BGRA5551:
+ {
+ return ( channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA );
+ }
+
+ case Dali::Pixel::INVALID:
+ case Dali::Pixel::COMPRESSED_R11_EAC:
+ case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
+ case Dali::Pixel::COMPRESSED_RG11_EAC:
+ case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
+ case Dali::Pixel::COMPRESSED_RGB8_ETC2:
+ case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
+ case Dali::Pixel::COMPRESSED_RGB8_ETC1:
+ case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
+ case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ {
+ DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
+ break;
+ }
+ }
+
+ return false;
+}
+
+unsigned int ReadChannel( unsigned char* pixelData,
+ Dali::Pixel::Format pixelFormat,
+ Channel channel )
+{
+ switch (pixelFormat)
+ {
+ case Dali::Pixel::A8:
+ {
+ if( channel == ALPHA )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else return 0u;
+ }
+ case Dali::Pixel::L8:
+ {
+ if( channel == LUMINANCE )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else return 0u;
+ }
+ case Dali::Pixel::LA88:
+ {
+ if( channel == LUMINANCE )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else if( channel == ALPHA )
+ {
+ return static_cast<unsigned int>(*(pixelData+1));
+ }
+ else return 0u;
+ }
+ case Dali::Pixel::RGB565:
+ {
+ if( channel == RED )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+ }
+ else if( channel == GREEN )
+ {
+ return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
+ ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
+ }
+ else if( channel == BLUE )
+ {
+ return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::BGR565:
+ {
+ if( channel == BLUE )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+ }
+ else if( channel == GREEN )
+ {
+ return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
+ ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
+ }
+ else if( channel == RED )
+ {
+ return (static_cast<unsigned int>(*(pixelData+1) & 0x1F) );
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::RGB888:
+ case Dali::Pixel::RGB8888:
+ {
+ if( channel == RED )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else if( channel == GREEN )
+ {
+ return static_cast<unsigned int>(*(pixelData+1));
+ }
+ else if( channel == BLUE )
+ {
+ return static_cast<unsigned int>(*(pixelData+2));
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::BGR8888:
+ {
+ if( channel == BLUE )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else if( channel == GREEN )
+ {
+ return static_cast<unsigned int>(*(pixelData+1));
+ }
+ else if( channel == RED )
+ {
+ return static_cast<unsigned int>(*(pixelData+2));
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::RGBA8888:
+ {
+ if( channel == RED )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else if( channel == GREEN )
+ {
+ return static_cast<unsigned int>(*(pixelData+1));
+ }
+ else if( channel == BLUE )
+ {
+ return static_cast<unsigned int>(*(pixelData+2));
+ }
+ else if( channel == ALPHA )
+ {
+ return static_cast<unsigned int>(*(pixelData+3));
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::BGRA8888:
+ {
+ if( channel == BLUE )
+ {
+ return static_cast<unsigned int>(*pixelData);
+ }
+ else if( channel == GREEN )
+ {
+ return static_cast<unsigned int>(*(pixelData+1));
+ }
+ else if( channel == RED )
+ {
+ return static_cast<unsigned int>(*(pixelData+2));
+ }
+ else if( channel == ALPHA )
+ {
+ return static_cast<unsigned int>(*(pixelData+3));
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::RGBA4444:
+ {
+ if( channel == RED )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
+ }
+ else if( channel == GREEN )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0x0F);
+ }
+ else if( channel == BLUE )
+ {
+ return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
+ }
+ else if( channel == ALPHA )
+ {
+ return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::BGRA4444:
+ {
+ if( channel == BLUE )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
+ }
+ else if( channel == GREEN )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0x0F);
+ }
+ else if( channel == RED )
+ {
+ return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
+ }
+ else if( channel == ALPHA )
+ {
+ return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
+ }
+ else return 0u;
+ }
+
+ case Dali::Pixel::RGBA5551:
+ {
+ if( channel == RED )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+ }
+ else if( channel == GREEN )
+ {
+ return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
+ ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
+ }
+ else if( channel == BLUE )
+ {
+ return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
+ }
+ else if( channel == ALPHA )
+ {
+ return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
+ }
+
+ else return 0u;
+ }
+
+ case Dali::Pixel::BGRA5551:
+ {
+ if( channel == BLUE )
+ {
+ return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+ }
+ else if( channel == GREEN )
+ {
+ return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
+ ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
+ }
+ else if( channel == RED )
+ {
+ return ( static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
+ }
+ else if( channel == ALPHA )
+ {
+ return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
+ }
+
+ else return 0u;
+ }
+
+ default:
+ {
+ return 0u;
+ }
+ }
+}
+
+void WriteChannel( unsigned char* pixelData,
+ Dali::Pixel::Format pixelFormat,
+ Channel channel,
+ unsigned int channelValue )
+{
+ switch (pixelFormat)
+ {
+ case Dali::Pixel::A8:
+ {
+ if( channel == ALPHA )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+ case Dali::Pixel::L8:
+ {
+ if( channel == LUMINANCE )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+ case Dali::Pixel::LA88:
+ {
+ if( channel == LUMINANCE )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+ case Dali::Pixel::RGB565:
+ {
+ if( channel == RED )
+ {
+ *pixelData &= ~0xF8;
+ *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+ }
+ else if( channel == GREEN )
+ {
+ *pixelData &= ~0x07;
+ *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
+
+ *(pixelData+1) &= ~0xE0;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
+ }
+ else if( channel == BLUE )
+ {
+ *(pixelData+1) &= ~0x1F;
+ *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
+ }
+ break;
+ }
+
+ case Dali::Pixel::BGR565:
+ {
+ if( channel == BLUE )
+ {
+ *pixelData &= ~0xF8;
+ *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+ }
+ else if( channel == GREEN )
+ {
+ *pixelData &= ~0x07;
+ *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
+
+ *(pixelData+1) &= ~0xE0;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
+ }
+ else if( channel == RED )
+ {
+ *(pixelData+1) &= ~0x1F;
+ *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
+ }
+ break;
+ }
+
+ case Dali::Pixel::RGB888:
+ case Dali::Pixel::RGB8888:
+ {
+ if( channel == RED )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == GREEN )
+ {
+ *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == BLUE )
+ {
+ *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+
+ case Dali::Pixel::BGR8888:
+ {
+ if( channel == BLUE )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == GREEN )
+ {
+ *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == RED )
+ {
+ *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+
+ case Dali::Pixel::RGBA8888:
+ {
+ if( channel == RED )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == GREEN )
+ {
+ *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == BLUE )
+ {
+ *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+
+ case Dali::Pixel::BGRA8888:
+ {
+ if( channel == BLUE )
+ {
+ *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == GREEN )
+ {
+ *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == RED )
+ {
+ *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
+ }
+ break;
+ }
+
+ case Dali::Pixel::RGBA4444:
+ {
+ if( channel == RED )
+ {
+ *pixelData &= ~0xF0;
+ *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+ }
+ else if( channel == GREEN )
+ {
+ *pixelData &= ~0x0F;
+ *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
+ }
+ else if( channel == BLUE )
+ {
+ *(pixelData+1) &= ~0xF0;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+1) &= ~0x0F;
+ *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
+ }
+ break;
+ }
+
+ case Dali::Pixel::BGRA4444:
+ {
+ if( channel == BLUE )
+ {
+ *pixelData &= ~0xF0;
+ *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+ }
+ else if( channel == GREEN )
+ {
+ *pixelData &= ~0x0F;
+ *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
+ }
+ else if( channel == RED )
+ {
+ *(pixelData+1) &= ~0xF0;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+1) &= ~0x0F;
+ *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
+ }
+ break;
+ }
+
+ case Dali::Pixel::RGBA5551:
+ {
+ // rrrrrggg ggbbbbba
+ // F8 7 C0 3E 1
+ if( channel == RED )
+ {
+ *pixelData &= ~0xF8;
+ *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+ }
+ else if( channel == GREEN )
+ {
+ *pixelData &= ~0x07;
+ *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
+
+ *(pixelData+1) &= ~0xC0;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
+ }
+ else if( channel == BLUE )
+ {
+ *(pixelData+1) &= ~0x3E;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+1) &= ~0x01;
+ *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
+ }
+ break;
+ }
+
+ case Dali::Pixel::BGRA5551:
+ {
+ if( channel == BLUE )
+ {
+ *pixelData &= ~0xF8;
+ *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+ }
+ else if( channel == GREEN )
+ {
+ *pixelData &= ~0x07;
+ *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
+
+ *(pixelData+1) &= ~0xC0;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
+ }
+ else if( channel == RED )
+ {
+ *(pixelData+1) &= ~0x3E;
+ *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1 ) & 0x3E );
+ }
+ else if( channel == ALPHA )
+ {
+ *(pixelData+1) &= ~0x01;
+ *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void ConvertColorChannelsToRGBA8888(
+ unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat,
+ unsigned char* destPixel, int destOffset )
+{
+ int red = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
+ int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
+ int blue = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
+ switch( srcFormat )
+ {
+ case Dali::Pixel::RGB565:
+ case Dali::Pixel::BGR565:
+ {
+ red<<=3;
+ green<<=2;
+ blue<<=3;
+ break;
+ }
+ case Dali::Pixel::RGBA4444:
+ case Dali::Pixel::BGRA4444:
+ {
+ red<<=4;
+ green<<=4;
+ blue<<=4;
+ break;
+ }
+ case Dali::Pixel::RGBA5551:
+ case Dali::Pixel::BGRA5551:
+ {
+ red<<=3;
+ green<<=3;
+ blue<<=3;
+ break;
+ }
+ default:
+ break;
+ }
+ WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, RED, red);
+ WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, GREEN, green);
+ WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
+}
+
+
+
+} // Pixel
+} // Internal
+} // Dali
--- /dev/null
+#ifndef DALI_EVENT_IMAGES_PIXEL_MANIPULATION_H
+#define DALI_EVENT_IMAGES_PIXEL_MANIPULATION_H
+
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/images/pixel.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Pixel
+{
+
+enum Channel
+{
+ LUMINANCE,
+ RED,
+ GREEN,
+ BLUE,
+ ALPHA,
+ MAX_NUMBER_OF_CHANNELS
+};
+
+/**
+ * Return true if the channel exists in the pixel format
+ * @param[in] pixelFormat The pixelFormat
+ * @param[in] channel The channel to test for
+ * @return true if the channel exists
+ */
+bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel );
+
+
+/**
+ * Read a colour channel from the pixel with the given pixel format.
+ * Returns zero if the format does not support the channel
+ * @param[in] pixelData Location of the pixel
+ * @param[in] pixelFormat The format of the pixel
+ * @param[in] channel The channel to read
+ * @return the channel value
+ */
+unsigned int ReadChannel( unsigned char* pixelData,
+ Dali::Pixel::Format pixelFormat,
+ Channel channel );
+
+/**
+ * Write a colour channel to the pixel with the given pixel format.
+ * @param[in] pixelData Location of the pixel
+ * @param[in] pixelFormat The format of the pixel
+ * @param[in] channel The channel to write
+ * @param[in] channelValue the value to write to the channel
+ */
+void WriteChannel( unsigned char* pixelData,
+ Dali::Pixel::Format pixelFormat,
+ Channel channel,
+ unsigned int channelValue );
+
+void ConvertColorChannelsToRGBA8888(
+ unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat,
+ unsigned char* destPixel, int destOffset );
+
+} // Pixel
+} // Internal
+} // Dali
+
+
+#endif // DALI_EVENT_IMAGES_PIXEL_MANIPULATION_H
$(internal_src_dir)/event/images/resource-image-impl.cpp \
$(internal_src_dir)/event/images/native-image-impl.cpp \
$(internal_src_dir)/event/images/pixel-data-impl.cpp \
+ $(internal_src_dir)/event/images/pixel-manipulation.cpp \
$(internal_src_dir)/event/object/custom-object-internal.cpp \
$(internal_src_dir)/event/render-tasks/render-task-impl.cpp \
$(internal_src_dir)/event/render-tasks/render-task-list-impl.cpp \