From 3845a7bc86ee7d72da33e35a3534d6a471556e1c Mon Sep 17 00:00:00 2001 From: David Steele Date: Thu, 8 Jun 2017 19:13:03 +0100 Subject: [PATCH] Added PixelBuffer for image loading and operations. Moved alpha masking from PixelData in Core to stand-alone C methods in Adaptor. Change-Id: I7eede320fdbc00e067241a4228b7e99ad958fe04 --- adaptors/common/bitmap-loader-impl.cpp | 78 --- adaptors/common/bitmap-loader-impl.h | 120 ---- adaptors/common/file.list | 2 +- adaptors/common/pixel-buffer-impl.cpp | 173 +++++ adaptors/common/pixel-buffer-impl.h | 201 ++++++ .../devel-api/adaptor-framework/bitmap-loader.cpp | 83 --- .../devel-api/adaptor-framework/bitmap-loader.h | 127 ---- .../devel-api/adaptor-framework/image-loading.cpp | 60 +- .../devel-api/adaptor-framework/image-loading.h | 16 +- .../devel-api/adaptor-framework/pixel-buffer.cpp | 106 +++ .../devel-api/adaptor-framework/pixel-buffer.h | 179 ++++++ adaptors/devel-api/file.list | 5 +- automated-tests/execute.sh | 8 +- .../src/dali-adaptor-internal/CMakeLists.txt | 1 + .../utc-Dali-Internal-PixelBuffer.cpp | 186 ++++++ automated-tests/src/dali-adaptor/CMakeLists.txt | 2 +- .../src/dali-adaptor/utc-Dali-BitmapLoader.cpp | 140 ---- .../src/dali-adaptor/utc-Dali-ImageLoading.cpp | 50 +- .../src/dali-adaptor/utc-Dali-PixelBuffer.cpp | 405 ++++++++++++ platform-abstractions/portable/alpha-mask.cpp | 245 +++++++ platform-abstractions/portable/alpha-mask.h | 66 ++ .../portable/pixel-manipulation.cpp | 714 +++++++++++++++++++++ .../portable/pixel-manipulation.h | 101 +++ platform-abstractions/tizen/file.list | 5 +- 24 files changed, 2461 insertions(+), 612 deletions(-) delete mode 100644 adaptors/common/bitmap-loader-impl.cpp delete mode 100644 adaptors/common/bitmap-loader-impl.h create mode 100644 adaptors/common/pixel-buffer-impl.cpp create mode 100644 adaptors/common/pixel-buffer-impl.h delete mode 100644 adaptors/devel-api/adaptor-framework/bitmap-loader.cpp delete mode 100644 adaptors/devel-api/adaptor-framework/bitmap-loader.h create mode 100644 adaptors/devel-api/adaptor-framework/pixel-buffer.cpp create mode 100644 adaptors/devel-api/adaptor-framework/pixel-buffer.h create mode 100644 automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp delete mode 100644 automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp create mode 100644 automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp create mode 100644 platform-abstractions/portable/alpha-mask.cpp create mode 100644 platform-abstractions/portable/alpha-mask.h create mode 100644 platform-abstractions/portable/pixel-manipulation.cpp create mode 100644 platform-abstractions/portable/pixel-manipulation.h diff --git a/adaptors/common/bitmap-loader-impl.cpp b/adaptors/common/bitmap-loader-impl.cpp deleted file mode 100644 index 9cef7ee..0000000 --- a/adaptors/common/bitmap-loader-impl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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. - */ - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include "image-loading.h" -#include "bitmap-loader-impl.h" - -namespace Dali -{ -namespace Internal -{ - -IntrusivePtr BitmapLoader::New(const std::string& url, - ImageDimensions size, - FittingMode::Type fittingMode, - SamplingMode::Type samplingMode, - bool orientationCorrection) -{ - IntrusivePtr internal = new BitmapLoader( url, size, fittingMode, samplingMode, orientationCorrection ); - return internal; -} - -BitmapLoader::BitmapLoader(const std::string& url, - ImageDimensions size, - FittingMode::Type fittingMode, - SamplingMode::Type samplingMode, - bool orientationCorrection ) -: mPixelData(), - mUrl(url), - mSize( size ), - mFittingMode( fittingMode ), - mSamplingMode( samplingMode ), - mOrientationCorrection( orientationCorrection ) -{ -} - -BitmapLoader::~BitmapLoader() -{ -} - -void BitmapLoader::Load() -{ - mPixelData = Dali::LoadImageFromFile( mUrl, mSize, mFittingMode, mSamplingMode, mOrientationCorrection ); -} - -bool BitmapLoader::IsLoaded() -{ - return mPixelData ? true : false ; -} - -const std::string& BitmapLoader::GetUrl() const -{ - return mUrl; -} - -Dali::PixelData BitmapLoader::GetPixelData() const -{ - return mPixelData; -} - -} // namespace Internal -} // namespace Dali diff --git a/adaptors/common/bitmap-loader-impl.h b/adaptors/common/bitmap-loader-impl.h deleted file mode 100644 index f328889..0000000 --- a/adaptors/common/bitmap-loader-impl.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef __DALI_BITMAP_LOADER_IMPL_H__ -#define __DALI_BITMAP_LOADER_IMPL_H__ - -/* - * 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. - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ -namespace Internal -{ - -class BitmapLoader : public BaseObject -{ -public: - - /** - * @copydoc Dali::BitmapLoader::New - */ - static IntrusivePtr New( const std::string& url, - ImageDimensions size, - FittingMode::Type fittingMode, - SamplingMode::Type samplingMode, - bool orientationCorrection); - - /** - * Create the bitmap loader object. - */ - BitmapLoader(const std::string& url, - ImageDimensions size, - FittingMode::Type fittingMode, - SamplingMode::Type samplingMode, - bool orientationCorrection); - -protected: - /** - * Destructor - */ - ~BitmapLoader(); - -public: - - /** - * @copydoc Dali::BitmapLoader::Load - */ - void Load(); - - /** - * @copydoc Dali::BitmapLoader::IsLoaded - */ - bool IsLoaded(); - - /** - * @copydoc Dali::BitmapLoader::GetUrl() - */ - const std::string& GetUrl() const; - - /** - * @copydoc Dali::BitmapLoader::GetPixelData - */ - Dali::PixelData GetPixelData() const; - -private: - - Dali::PixelData mPixelData; - const std::string mUrl; - ImageDimensions mSize; - FittingMode::Type mFittingMode; - SamplingMode::Type mSamplingMode; - bool mOrientationCorrection; - -}; - -} // Internal - - -inline Internal::BitmapLoader& GetImplementation(Dali::BitmapLoader& handle) -{ - DALI_ASSERT_ALWAYS( handle && "handle is empty" ); - - BaseObject& object = handle.GetBaseObject(); - - return static_cast(object); -} - -inline const Internal::BitmapLoader& GetImplementation(const Dali::BitmapLoader& handle) -{ - DALI_ASSERT_ALWAYS( handle && "handle is empty" ); - - const BaseObject& object = handle.GetBaseObject(); - - return static_cast(object); -} - -} // Dali - -#endif // __DALI_BITMAP_LOADER_IMPL_H__ diff --git a/adaptors/common/file.list b/adaptors/common/file.list index af0bebe..af15d62 100644 --- a/adaptors/common/file.list +++ b/adaptors/common/file.list @@ -7,7 +7,6 @@ adaptor_common_internal_src_files = \ $(adaptor_common_dir)/adaptor.cpp \ $(adaptor_common_dir)/adaptor-impl.cpp \ $(adaptor_common_dir)/application-impl.cpp \ - $(adaptor_common_dir)/bitmap-loader-impl.cpp \ $(adaptor_common_dir)/clipboard-event-notifier-impl.cpp \ $(adaptor_common_dir)/command-line-options.cpp \ $(adaptor_common_dir)/drag-and-drop-detector-impl.cpp \ @@ -22,6 +21,7 @@ adaptor_common_internal_src_files = \ $(adaptor_common_dir)/orientation-impl.cpp \ $(adaptor_common_dir)/performance-logger-impl.cpp \ $(adaptor_common_dir)/physical-keyboard-impl.cpp \ + $(adaptor_common_dir)/pixel-buffer-impl.cpp \ $(adaptor_common_dir)/shared-file.cpp \ $(adaptor_common_dir)/singleton-service-impl.cpp \ $(adaptor_common_dir)/sound-player-impl.cpp \ diff --git a/adaptors/common/pixel-buffer-impl.cpp b/adaptors/common/pixel-buffer-impl.cpp new file mode 100644 index 0000000..a2b1610 --- /dev/null +++ b/adaptors/common/pixel-buffer-impl.cpp @@ -0,0 +1,173 @@ +/* + * 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 "pixel-buffer-impl.h" + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include "pixel-manipulation.h" +#include "alpha-mask.h" + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +PixelBuffer::PixelBuffer( unsigned char* buffer, + unsigned int bufferSize, + unsigned int width, + unsigned int height, + Dali::Pixel::Format pixelFormat ) +: mBuffer( buffer ), + mBufferSize( bufferSize ), + mWidth( width ), + mHeight( height ), + mPixelFormat( pixelFormat ) +{ +} + +PixelBuffer::~PixelBuffer() +{ + ReleaseBuffer(); +} + +PixelBufferPtr PixelBuffer::New( unsigned int width, + unsigned int height, + Dali::Pixel::Format pixelFormat ) +{ + unsigned int bufferSize = width * height * Dali::Pixel::GetBytesPerPixel( pixelFormat ); + unsigned char* buffer = NULL; + if( bufferSize > 0 ) + { + buffer = static_cast( malloc ( bufferSize ) ); + } + return new PixelBuffer( buffer, bufferSize, width, height, pixelFormat ); +} + +PixelBufferPtr PixelBuffer::New( unsigned char* buffer, + unsigned int bufferSize, + unsigned int width, + unsigned int height, + Dali::Pixel::Format pixelFormat ) +{ + return new PixelBuffer( buffer, bufferSize, width, height, pixelFormat ); +} + +Dali::PixelData PixelBuffer::Convert( PixelBuffer& pixelBuffer ) +{ + Dali::PixelData pixelData = Dali::PixelData::New( pixelBuffer.mBuffer, + pixelBuffer.mBufferSize, + pixelBuffer.mWidth, + pixelBuffer.mHeight, + pixelBuffer.mPixelFormat, + Dali::PixelData::FREE ); + pixelBuffer.mBuffer = NULL; + pixelBuffer.mWidth = 0; + pixelBuffer.mHeight = 0; + pixelBuffer.mBufferSize = 0; + + return pixelData; +} + +unsigned int PixelBuffer::GetWidth() const +{ + return mWidth; +} + +unsigned int PixelBuffer::GetHeight() const +{ + return mHeight; +} + +Dali::Pixel::Format PixelBuffer::GetPixelFormat() const +{ + return mPixelFormat; +} + +unsigned char* PixelBuffer::GetBuffer() const +{ + return mBuffer; +} + +unsigned int PixelBuffer::GetBufferSize() const +{ + return mBufferSize; +} + +Dali::PixelData PixelBuffer::CreatePixelData() const +{ + unsigned char* destBuffer = NULL; + + if( mBufferSize > 0 ) + { + destBuffer = static_cast( malloc( mBufferSize ) ); + memcpy( destBuffer, mBuffer, mBufferSize ); + } + + Dali::PixelData pixelData = Dali::PixelData::New( destBuffer, mBufferSize, + mWidth, mHeight, + mPixelFormat, + Dali::PixelData::FREE ); + return pixelData; +} + +void PixelBuffer::ApplyMask( const PixelBuffer& mask ) +{ + int byteOffset=0; + int bitMask=0; + + Dali::Pixel::GetAlphaOffsetAndMask(mPixelFormat, byteOffset, bitMask); + + if( Dali::Pixel::HasAlpha( mPixelFormat ) && bitMask == 255 ) + { + ApplyMaskToAlphaChannel( *this, mask ); + } + else + { + PixelBufferPtr newPixelBuffer = CreateNewMaskedBuffer( *this, mask ); + ReleaseBuffer(); + + // Take ownership of new buffer + mBuffer = newPixelBuffer->mBuffer; + newPixelBuffer->mBuffer = NULL; + mPixelFormat = newPixelBuffer->mPixelFormat; + mBufferSize = newPixelBuffer->mBufferSize; + + // On leaving scope, newPixelBuffer will get destroyed. + } +} + +void PixelBuffer::ReleaseBuffer() +{ + if( mBuffer ) + { + free( mBuffer ); + } +} + + +}// namespace Adaptor +}// namespace Internal +}// namespace Dali diff --git a/adaptors/common/pixel-buffer-impl.h b/adaptors/common/pixel-buffer-impl.h new file mode 100644 index 0000000..4853001 --- /dev/null +++ b/adaptors/common/pixel-buffer-impl.h @@ -0,0 +1,201 @@ +#ifndef DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H +#define DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +class PixelBuffer; +typedef IntrusivePtr PixelBufferPtr; + +class PixelBuffer : public BaseObject +{ +public: + + /** + * @brief Create a PixelBuffer object with a pre-allocated buffer. + * The PixelBuffer object owns this buffer, which may be retrieved + * and modified using GetBuffer(). + * + * @param [in] width Buffer width in pixels + * @param [in] height Buffer height in pixels + * @param [in] pixelFormat The pixel format + */ + static PixelBufferPtr New( unsigned int width, + unsigned int height, + Pixel::Format pixelFormat ); + + /** + * @brief Create a PixelBuffer object. For internal use only. + * + * @param [in] buffer The raw pixel data. + * @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] 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, + Pixel::Format pixelFormat ); + + /** + * Convert a pixelBuffer object into a PixelData object. + * The new object takes ownership of the buffer data, and the + * mBuffer pointer is reset to NULL. + * @param[in] pixelBuffer The buffer to convert + * @return the pixelData + */ + static Dali::PixelData Convert( PixelBuffer& pixelBuffer ); + + /** + * @brief Constructor. + * + * @param [in] buffer The raw pixel data. + * @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] pixelFormat The pixel format + */ + PixelBuffer( unsigned char* buffer, + unsigned int bufferSize, + unsigned int width, + unsigned int height, + Pixel::Format pixelFormat ); + +protected: + + /** + * @brief Destructor. + * + * Release the pixel buffer if exists. + */ + ~PixelBuffer(); + +public: + + /** + * Get the width of the buffer in pixels. + * @return The width of the buffer in pixels + */ + unsigned int GetWidth() const; + + /** + * Get the height of the buffer in pixels + * @return The height of the buffer in pixels + */ + unsigned int GetHeight() const; + + /** + * Get the pixel format + * @return The pixel format + */ + Pixel::Format GetPixelFormat() const; + + /** + * Get the pixel buffer if it's present. + * @return The buffer if exists, or NULL if there is no pixel buffer. + */ + unsigned char* GetBuffer() const; + + /** + * Get the size of the buffer in bytes + * @return The size of the buffer + */ + unsigned int GetBufferSize() const; + + /** + * Copy the buffer into a new PixelData + */ + Dali::PixelData CreatePixelData() const; + + /** + * Apply the mask to the current buffer. This method may update the + * internal object - e.g. the new buffer may have a different pixel + * format - as an alpha channel may be added. + * @param[in] mask The mask to apply to this pixel buffer + */ + void ApplyMask( const PixelBuffer& mask ); + +private: + /* + * Undefined copy constructor. + */ + PixelBuffer(const PixelBuffer& other); + + /* + * Undefined assignment operator. + */ + PixelBuffer& operator= (const PixelBuffer& other); + + /** + * Release the buffer + */ + void ReleaseBuffer(); + +private: + + 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 + Pixel::Format mPixelFormat; ///< Pixel format +}; + +} // namespace Adaptor + +} // namespace Internal + +/** + * Helper methods for public API + */ +inline Internal::Adaptor::PixelBuffer& GetImplementation( Devel::PixelBuffer& handle ) +{ + DALI_ASSERT_ALWAYS( handle && "handle is empty" ); + + BaseObject& object = handle.GetBaseObject(); + + return static_cast( object ); +} + +inline const Internal::Adaptor::PixelBuffer& GetImplementation( const Devel::PixelBuffer& handle ) +{ + DALI_ASSERT_ALWAYS( handle && "handle is empty" ); + + const BaseObject& object = handle.GetBaseObject(); + + return static_cast( object ); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H__ diff --git a/adaptors/devel-api/adaptor-framework/bitmap-loader.cpp b/adaptors/devel-api/adaptor-framework/bitmap-loader.cpp deleted file mode 100644 index 4aa2bd6..0000000 --- a/adaptors/devel-api/adaptor-framework/bitmap-loader.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2015 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 "bitmap-loader.h" - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -BitmapLoader BitmapLoader::New( const std::string& url, - ImageDimensions size, - FittingMode::Type fittingMode, - SamplingMode::Type samplingMode, - bool orientationCorrection) -{ - IntrusivePtr internal = Internal::BitmapLoader::New(url, size, fittingMode, samplingMode, orientationCorrection); - return BitmapLoader( internal.Get() ); -} - -BitmapLoader::BitmapLoader() -{ -} - -BitmapLoader::BitmapLoader(Internal::BitmapLoader* internal) -: BaseHandle( internal ) -{ -} - -BitmapLoader::~BitmapLoader() -{ -} - -BitmapLoader::BitmapLoader( const BitmapLoader& handle ) -: BaseHandle( handle ) -{ -} - -BitmapLoader& BitmapLoader::operator=(const BitmapLoader& rhs) -{ - BaseHandle::operator=(rhs); - return *this; -} - -void BitmapLoader::Load() -{ - GetImplementation(*this).Load(); -} - -bool BitmapLoader::IsLoaded() -{ - return GetImplementation(*this).IsLoaded(); -} - -std::string BitmapLoader::GetUrl() const -{ - return GetImplementation(*this).GetUrl(); -} - -PixelData BitmapLoader::GetPixelData() const -{ - return GetImplementation(*this).GetPixelData(); -} - -} // namespace Dali diff --git a/adaptors/devel-api/adaptor-framework/bitmap-loader.h b/adaptors/devel-api/adaptor-framework/bitmap-loader.h deleted file mode 100644 index 7849db4..0000000 --- a/adaptors/devel-api/adaptor-framework/bitmap-loader.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef DALI_BITMAP_LOADER_H -#define DALI_BITMAP_LOADER_H - -/* - * Copyright (c) 2015 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. - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -namespace Dali -{ -namespace Internal -{ -class BitmapLoader; -} - -/** - * @brief The BitmapLoader class is used to load bitmap from the URL synchronously. - * - * As the loading is synchronous, it will block the loop whilst executing. - * Therefore, it should be used sparingly in the main event thread, and better to be called in the worker thread. - * The Load() API is thread safe, it can be called from any thread without changing the state of DALI. - */ -class DALI_IMPORT_API BitmapLoader : public BaseHandle -{ -public: - - /** - * @brief Create an initialized bitmap loader. - * - * By calling Load(), the synchronous loading is started immediately. - * - * @param [in] url The URL of the image file to load. - * @param [in] size The width and height to fit the loaded image to. - * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter. - * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size. - * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header. - */ - static BitmapLoader New( const std::string& url, - ImageDimensions size = ImageDimensions( 0, 0 ), - FittingMode::Type fittingMode = FittingMode::DEFAULT, - SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR, - bool orientationCorrection = true); - - /** - * @brief Create an empty handle. - * - * Use BitmapLoader::New() to create an initialized object. - */ - BitmapLoader(); - - /** - * Destructor - */ - ~BitmapLoader(); - - /** - * @brief This copy constructor is required for (smart) pointer semantics. - * - * @param [in] handle A reference to the copied handle - */ - BitmapLoader(const BitmapLoader& handle); - - /** - * @brief This assignment operator is required for (smart) pointer semantics. - * - * @param [in] rhs A reference to the copied handle - * @return A reference to this - */ - BitmapLoader& operator=(const BitmapLoader& rhs); - -public: - - /** - * @brief Start the synchronous loading. - */ - void Load(); - - /** - * @brief Query whether the image is loaded. - * - * @return true if the image is loaded, false otherwise. - */ - bool IsLoaded(); - - /** - * @brief Returns the URL of the image. - * - * @return The URL of the image file. - */ - std::string GetUrl() const; - - /** - * @brief Get the pixel data. - * - * The returned pixel data is still valid after the BitmapLoader been destroyed. - * - * @return The pixel data. - */ - PixelData GetPixelData() const; - -public: // Not intended for application developers - - explicit DALI_INTERNAL BitmapLoader(Internal::BitmapLoader*); -}; - -} // Dali - -#endif // DALI_BITMAP_LOADER_H diff --git a/adaptors/devel-api/adaptor-framework/image-loading.cpp b/adaptors/devel-api/adaptor-framework/image-loading.cpp index 701ccc7..d8f8adf 100644 --- a/adaptors/devel-api/adaptor-framework/image-loading.cpp +++ b/adaptors/devel-api/adaptor-framework/image-loading.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * 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. @@ -21,6 +21,7 @@ #include "image-loaders/image-loader.h" #include #include +#include "pixel-buffer-impl.h" namespace Dali { @@ -31,25 +32,34 @@ namespace const size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE = 50 * 1024 * 1024 ; } -PixelData LoadImageFromFile( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection ) +Devel::PixelBuffer LoadImageFromFile( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection ) { Integration::BitmapResourceType resourceType( size, fittingMode, samplingMode, orientationCorrection ); - IntrusivePtr resource = TizenPlatform::ImageLoader::LoadImageSynchronously( resourceType, url ); - if( resource ) + Internal::Platform::FileCloser fc( url.c_str(), "rb"); + FILE * const fp = fc.GetFile(); + if( fp != NULL ) { - Integration::Bitmap* bitmap = static_cast( resource.Get() ); - - // Use bitmap->GetBufferOwnership() to transfer the buffer ownership to pixelData. - // The destroy of bitmap will not release the buffer, instead, the pixelData is responsible for releasing when its reference count falls to zero. - return Dali::PixelData::New( bitmap->GetBufferOwnership(), - bitmap->GetBufferSize(), - bitmap->GetImageWidth(), - bitmap->GetImageHeight(), - bitmap->GetPixelFormat(), - Dali::PixelData::FREE ); + Integration::BitmapPtr bitmap; + bool success = TizenPlatform::ImageLoader::ConvertStreamToBitmap( resourceType, url, fp, bitmap ); + if( success && bitmap ) + { + // Use bitmap->GetBufferOwnership() to transfer the buffer ownership + // to pixelData. The destroy of bitmap will not release the buffer, + // instead, the pixelBuffer is responsible for releasing when its + // reference count falls to zero. + Internal::Adaptor::PixelBufferPtr pixelBufferImpl = + Internal::Adaptor::PixelBuffer::New( bitmap->GetBufferOwnership(), + bitmap->GetBufferSize(), + bitmap->GetImageWidth(), + bitmap->GetImageHeight(), + bitmap->GetPixelFormat() ); + + Dali::Devel::PixelBuffer pixelBuffer( pixelBufferImpl.Get() ); + return pixelBuffer; + } } - return Dali::PixelData(); + return Dali::Devel::PixelBuffer(); } ImageDimensions GetClosestImageSize( const std::string& filename, @@ -62,7 +72,7 @@ ImageDimensions GetClosestImageSize( const std::string& filename, } -PixelData DownloadImageSynchronously( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection ) +Devel::PixelBuffer DownloadImageSynchronously( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection ) { Integration::BitmapResourceType resourceType( size, fittingMode, samplingMode, orientationCorrection ); @@ -96,12 +106,15 @@ PixelData DownloadImageSynchronously( const std::string& url, ImageDimensions si if ( result && bitmap ) { - return Dali::PixelData::New( bitmap->GetBufferOwnership(), - bitmap->GetBufferSize(), - bitmap->GetImageWidth(), - bitmap->GetImageHeight(), - bitmap->GetPixelFormat(), - Dali::PixelData::FREE ); + Internal::Adaptor::PixelBufferPtr pixelBufferImpl = + Internal::Adaptor::PixelBuffer::New( bitmap->GetBufferOwnership(), + bitmap->GetBufferSize(), + bitmap->GetImageWidth(), + bitmap->GetImageHeight(), + bitmap->GetPixelFormat() ); + + Dali::Devel::PixelBuffer pixelBuffer( pixelBufferImpl.Get() ); + return pixelBuffer; } else { @@ -109,9 +122,8 @@ PixelData DownloadImageSynchronously( const std::string& url, ImageDimensions si } } } - } - return Dali::PixelData(); + return Dali::Devel::PixelBuffer(); } diff --git a/adaptors/devel-api/adaptor-framework/image-loading.h b/adaptors/devel-api/adaptor-framework/image-loading.h index 124b27b..00a6a45 100644 --- a/adaptors/devel-api/adaptor-framework/image-loading.h +++ b/adaptors/devel-api/adaptor-framework/image-loading.h @@ -21,7 +21,13 @@ #include #include #include -#include + +#ifdef DALI_ADAPTOR_COMPILATION // full path doesn't exist until adaptor is installed so we have to use relative +// @todo Make dali-adaptor code folder structure mirror the folder structure installed to dali-env +#include +#else +#include +#endif namespace Dali { @@ -36,9 +42,9 @@ namespace Dali * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter. * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size. * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header. - * @return handle to the loaded PixelData object or an empty handle in case loading failed. + * @return handle to the loaded PixelBuffer object or an empty handle in case loading failed. */ -DALI_IMPORT_API PixelData LoadImageFromFile( +DALI_IMPORT_API Devel::PixelBuffer LoadImageFromFile( const std::string& url, ImageDimensions size = ImageDimensions( 0, 0 ), FittingMode::Type fittingMode = FittingMode::DEFAULT, @@ -77,9 +83,9 @@ DALI_IMPORT_API ImageDimensions GetClosestImageSize( * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size. * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header. * - * @return handle to the loaded PixelData object or an empty handle in case downloading or decoding failed. + * @return handle to the loaded PixelBuffer object or an empty handle in case downloading or decoding failed. */ -DALI_IMPORT_API PixelData DownloadImageSynchronously( +DALI_IMPORT_API Devel::PixelBuffer DownloadImageSynchronously( const std::string& url, ImageDimensions size = ImageDimensions( 0, 0 ), FittingMode::Type fittingMode = FittingMode::DEFAULT, diff --git a/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp b/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp new file mode 100644 index 0000000..52d8b8f --- /dev/null +++ b/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp @@ -0,0 +1,106 @@ +/* + * 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 "pixel-buffer.h" + +// EXTERNAL INLCUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Devel +{ + +PixelBuffer PixelBuffer::New( unsigned int width, + unsigned int height, + Dali::Pixel::Format pixelFormat ) +{ + Internal::Adaptor::PixelBufferPtr internal = + Internal::Adaptor::PixelBuffer::New( width, height, pixelFormat ); + return Devel::PixelBuffer( internal.Get() ); +} + +Dali::PixelData PixelBuffer::Convert( PixelBuffer& pixelBuffer ) +{ + Dali::PixelData pixelData = + Internal::Adaptor::PixelBuffer::Convert( GetImplementation(pixelBuffer) ); + pixelBuffer.Reset(); + return pixelData; +} + +Dali::PixelData PixelBuffer::CreatePixelData() const +{ + return GetImplementation(*this).CreatePixelData(); +} + + +PixelBuffer::PixelBuffer() +{ +} + +PixelBuffer::~PixelBuffer() +{ +} + +PixelBuffer::PixelBuffer( Internal::Adaptor::PixelBuffer* internal ) +: BaseHandle( internal ) +{ +} + +PixelBuffer::PixelBuffer(const PixelBuffer& handle) +: BaseHandle( handle ) +{ +} + +PixelBuffer& PixelBuffer::operator=(const PixelBuffer& rhs) +{ + BaseHandle::operator=(rhs); + return *this; +} + +unsigned int PixelBuffer::GetWidth() const +{ + return GetImplementation(*this).GetWidth(); +} + +unsigned int PixelBuffer::GetHeight() const +{ + return GetImplementation(*this).GetHeight(); +} + +Pixel::Format PixelBuffer::GetPixelFormat() const +{ + return GetImplementation(*this).GetPixelFormat(); +} + +unsigned char* PixelBuffer::GetBuffer() +{ + return GetImplementation(*this).GetBuffer(); +} + +void PixelBuffer::ApplyMask( PixelBuffer mask ) +{ + GetImplementation(*this).ApplyMask( GetImplementation( mask ) ); +} + +} // namespace Devel + +} // namespace Dali diff --git a/adaptors/devel-api/adaptor-framework/pixel-buffer.h b/adaptors/devel-api/adaptor-framework/pixel-buffer.h new file mode 100644 index 0000000..deb7823 --- /dev/null +++ b/adaptors/devel-api/adaptor-framework/pixel-buffer.h @@ -0,0 +1,179 @@ +#ifndef DALI_PIXEL_BUFFER_H +#define DALI_PIXEL_BUFFER_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 +#include +#include + +namespace Dali +{ + +namespace Internal +{ +namespace Adaptor +{ +class PixelBuffer; +} +} + +// Use namespace to separate from PixelBuffer typedef in buffer-image.h +namespace Devel +{ + +/** + * @brief The PixelBuffer object holds a pixel buffer. + * + * The PixelBuffer keeps ownership of it's initial buffer however, the + * user is free to modify the pixel data, either directly, or via + * image operations. + * + * In order to upload the pixel data to texture memory, there are two + * possibilities - either convert it back to a PixelData object, which + * releases the PixelBuffer object, leaving the user with an empty handle + * (ideal for one-time indirect image manipulation), or create a new + * PixelData object from this object, leaving the buffer intact (ideal + * for continuous manipulation) + * + * @SINCE_1_2.46 + */ +class DALI_IMPORT_API PixelBuffer : public BaseHandle +{ +public: + + /** + * Create a PixelBuffer with it's own data buffer. + */ + static PixelBuffer New( unsigned int width, + unsigned int height, + Dali::Pixel::Format pixelFormat ); + + /** + * @brief Creates an empty handle. + * Use PixelBuffer::New() to create an initialized object. + * + * @SINCE_1_2.46 + */ + PixelBuffer(); + + /** + * @brief Destructor. + * + * @SINCE_1_2.46 + */ + ~PixelBuffer(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @SINCE_1_2.46 + * @param[in] handle A reference to the copied handle + */ + PixelBuffer(const PixelBuffer& handle); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @SINCE_1_2.46 + * @param[in] rhs A reference to the copied handle + * @return A reference to this object + */ + PixelBuffer& operator=(const PixelBuffer& rhs); + + /** + * Convert to a pixel data and release the pixelBuffer's object. + * This handle is left empty. + * + * @warning Any other handles that keep a reference to this object + * will be left with no buffer, trying to access it will return NULL. + * + * @SINCE_1_2.46 + * @param[in,out] pixelBuffer + * @return a new PixelData which takes ownership of the PixelBuffer's buffer. + */ + static PixelData Convert( PixelBuffer& pixelBuffer ); + + /** + * Copy the data from this object into a new PixelData object, which could be + * used for uploading to a texture. + * @return a new PixelData object containing a copy of this pixel buffer's data. + */ + Dali::PixelData CreatePixelData() const; + + /** + * @brief Gets the pixel buffer. This is a pointer to the internal + * pixel buffer. + * + * @warning If there is no pixel buffer (e.g. this object has been + * converted to a PixelData), this method will return NULL. + * + * @SINCE_1_2.46 + * @return The pixel buffer, or NULL. + */ + unsigned char* GetBuffer(); + + /** + * @brief Gets the width of the buffer in pixels. + * + * @SINCE_1_2.46 + * @return The width of the buffer in pixels + */ + unsigned int GetWidth() const; + + /** + * @brief Gets the height of the buffer in pixels. + * + * @SINCE_1_2.46 + * @return The height of the buffer in pixels + */ + unsigned int GetHeight() const; + + /** + * @brief Gets the pixel format. + * + * @SINCE_1_2.46 + * @return The pixel format + */ + Pixel::Format GetPixelFormat() const; + + /** + * Apply the mask to this pixel data, and return a new pixel data + * containing the masked image. If this PixelBuffer doesn't have an alpha channel, + * then the resultant PixelBuffer will be converted to a format that + * supports at least the width of the color channels and the alpha channel + * from the mask. + * @param[in] mask The mask to apply. + */ + void ApplyMask( PixelBuffer mask ); + +public: + + /** + * @brief The constructor. + * @note Not intended for application developers. + * @SINCE_1_2.46 + * @param[in] pointer A pointer to a newly allocated PixelBuffer + */ + explicit DALI_INTERNAL PixelBuffer( Internal::Adaptor::PixelBuffer* pointer ); +}; + +} // namespace Devel +} // namespace Dali + +#endif // DALI_PIXEL_BUFFER_H diff --git a/adaptors/devel-api/file.list b/adaptors/devel-api/file.list index 6cdeb53..0ce6e62 100644 --- a/adaptors/devel-api/file.list +++ b/adaptors/devel-api/file.list @@ -2,7 +2,6 @@ devel_api_src_files = \ $(adaptor_devel_api_dir)/adaptor-framework/accessibility-adaptor.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/application-devel.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/application-extensions.cpp \ - $(adaptor_devel_api_dir)/adaptor-framework/bitmap-loader.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/bitmap-saver.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/clipboard.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/clipboard-event-notifier.cpp \ @@ -20,6 +19,7 @@ devel_api_src_files = \ $(adaptor_devel_api_dir)/adaptor-framework/orientation.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/performance-logger.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/physical-keyboard.cpp \ + $(adaptor_devel_api_dir)/adaptor-framework/pixel-buffer.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/singleton-service.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/sound-player.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/style-monitor.cpp \ @@ -36,7 +36,6 @@ devel_api_adaptor_framework_header_files = \ $(adaptor_devel_api_dir)/adaptor-framework/accessibility-gesture-handler.h \ $(adaptor_devel_api_dir)/adaptor-framework/application-devel.h \ $(adaptor_devel_api_dir)/adaptor-framework/application-extensions.h \ - $(adaptor_devel_api_dir)/adaptor-framework/bitmap-loader.h \ $(adaptor_devel_api_dir)/adaptor-framework/bitmap-saver.h \ $(adaptor_devel_api_dir)/adaptor-framework/clipboard-event-notifier.h \ $(adaptor_devel_api_dir)/adaptor-framework/clipboard.h \ @@ -56,6 +55,7 @@ devel_api_adaptor_framework_header_files = \ $(adaptor_devel_api_dir)/adaptor-framework/lifecycle-controller.h \ $(adaptor_devel_api_dir)/adaptor-framework/orientation.h \ $(adaptor_devel_api_dir)/adaptor-framework/performance-logger.h \ + $(adaptor_devel_api_dir)/adaptor-framework/pixel-buffer.h \ $(adaptor_devel_api_dir)/adaptor-framework/render-surface.h \ $(adaptor_devel_api_dir)/adaptor-framework/singleton-service.h \ $(adaptor_devel_api_dir)/adaptor-framework/sound-player.h \ @@ -67,4 +67,3 @@ devel_api_adaptor_framework_header_files = \ $(adaptor_devel_api_dir)/adaptor-framework/virtual-keyboard.h \ $(adaptor_devel_api_dir)/adaptor-framework/physical-keyboard.h \ $(adaptor_devel_api_dir)/adaptor-framework/window-devel.h - diff --git a/automated-tests/execute.sh b/automated-tests/execute.sh index bc108fa..bc51cfb 100755 --- a/automated-tests/execute.sh +++ b/automated-tests/execute.sh @@ -75,7 +75,7 @@ rm -f tct*core-tests.xml # Clean up old coverage data if [ -d ../build/tizen ] ; then - rm -f ../build/tizen/dali-toolkit/.libs/*.gcda + rm -f ../build/tizen/dali/.libs/*.gcda fi find build \( -name "*.gcda" \) -exec rm '{}' \; @@ -138,9 +138,9 @@ else ret=$? if [ $ret -ne 6 ] ; then if [ $opt_debug -ne 0 ] ; then - if [ $ret -eq 0 ] ; then - gdb --args build/src/$mod/tct-$mod-core $1 - fi + echo DEBUGGING: + gdb --args build/src/$mod/tct-$mod-core $1 + else echo $output if [ $ret -eq 0 ] ; then echo -e "\nPassed" ; fi diff --git a/automated-tests/src/dali-adaptor-internal/CMakeLists.txt b/automated-tests/src/dali-adaptor-internal/CMakeLists.txt index af08fd1..c41bc4d 100644 --- a/automated-tests/src/dali-adaptor-internal/CMakeLists.txt +++ b/automated-tests/src/dali-adaptor-internal/CMakeLists.txt @@ -12,6 +12,7 @@ SET(TC_SOURCES utc-Dali-GifLoader.cpp utc-Dali-IcoLoader.cpp utc-Dali-ImageOperations.cpp + utc-Dali-Internal-PixelBuffer.cpp utc-Dali-Lifecycle-Controller.cpp utc-Dali-TiltSensor.cpp ) diff --git a/automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp b/automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp new file mode 100644 index 0000000..710e52c --- /dev/null +++ b/automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp @@ -0,0 +1,186 @@ +/* + * 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 + +#include +#include + +#include + +// Internal headers are allowed here + +#include + +using namespace Dali; +using namespace Dali::Internal::Adaptor; +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::Adaptor::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::AdaptorManipulation HasChannel"); + + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::A8, Dali::Internal::Adaptor::ALPHA ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::A8, Dali::Internal::Adaptor::LUMINANCE ), false, TEST_LOCATION ); + + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::L8, Dali::Internal::Adaptor::LUMINANCE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::L8, Dali::Internal::Adaptor::ALPHA ), false, TEST_LOCATION ); + + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::LA88, Dali::Internal::Adaptor::LUMINANCE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::LA88, Dali::Internal::Adaptor::ALPHA ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::LA88, Dali::Internal::Adaptor::RED ), false, TEST_LOCATION ); + + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::RED ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::GREEN ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::BLUE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::LUMINANCE ), false, TEST_LOCATION ); + + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::RED ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::GREEN ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::BLUE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::ALPHA ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::LUMINANCE ), false, TEST_LOCATION ); + + DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR, Dali::Internal::Adaptor::BLUE ), false, TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliPixelManipulation02(void) +{ + tet_infoline("Testing Dali::Internal::AdaptorManipulation Read/WriteChannel"); + + unsigned char pixel[4] = {0,0,0,0}; + + for( int formatIdx=1; formatIdx(formatIdx); + Dali::Internal::Adaptor::Channel channel = static_cast(channelIdx); + if( Dali::Internal::Adaptor::HasChannel( format, channel ) ) + { + Dali::Internal::Adaptor::WriteChannel( &pixel[0], format, channel, 0x15); + unsigned int value = Dali::Internal::Adaptor::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::Adaptor::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::AdaptorManipulation Read/WriteChannel"); + + unsigned char pixel[4] = {0,0,0,0}; + + for( int formatIdx=1; formatIdx(formatIdx); + Dali::Internal::Adaptor::Channel channel = static_cast(channelIdx); + if( ! Dali::Internal::Adaptor::HasChannel( format, channel ) ) + { + unsigned int value = Dali::Internal::Adaptor::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; +} diff --git a/automated-tests/src/dali-adaptor/CMakeLists.txt b/automated-tests/src/dali-adaptor/CMakeLists.txt index 04311e0..4ae66c4 100644 --- a/automated-tests/src/dali-adaptor/CMakeLists.txt +++ b/automated-tests/src/dali-adaptor/CMakeLists.txt @@ -6,12 +6,12 @@ SET(RPM_NAME "core-${PKG_NAME}-tests") SET(CAPI_LIB "dali-adaptor") SET(TC_SOURCES utc-Dali-Application.cpp - utc-Dali-BitmapLoader.cpp utc-Dali-FileLoader.cpp utc-Dali-GifLoading.cpp utc-Dali-ImageLoading.cpp utc-Dali-Key.cpp utc-Dali-NativeImageSource.cpp + utc-Dali-PixelBuffer.cpp utc-Dali-SingletonService.cpp utc-Dali-Timer.cpp utc-Dali-TtsPlayer.cpp diff --git a/automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp b/automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp deleted file mode 100644 index 1490ea4..0000000 --- a/automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2015 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 -#include -#include -#include - -using namespace Dali; - -namespace -{ -// resolution: 34*34, pixel format: RGBA8888 -static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png"; -// resolution: 128*128, pixel format: RGB888 -static const char* gImage_128_RGB = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; - -// this is image is not exist, for negative test -static const char* gImageNonExist = "non-exist.jpg"; -} - -void utc_dali_bitmap_loader_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void utc_dali_bitmap_loader_cleanup(void) -{ - test_return_value = TET_PASS; -} - -int UtcDaliBitmapLoaderNew(void) -{ - TestApplication application; - - // invoke default handle constructor - BitmapLoader loader; - - DALI_TEST_CHECK( !loader ); - - // initialise handle - loader = BitmapLoader::New( gImage_34_RGBA ); - - DALI_TEST_CHECK( loader ); - END_TEST; -} - -int UtcDaliBitmapLoaderCopyConstructor(void) -{ - TestApplication application; - - BitmapLoader loader = BitmapLoader::New( gImage_34_RGBA); - BitmapLoader loaderCopy(loader); - - DALI_TEST_EQUALS( (bool)loaderCopy, true, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliBitmapLoaderAssignmentOperator(void) -{ - TestApplication application; - - BitmapLoader loader = BitmapLoader::New( gImage_34_RGBA ); - - BitmapLoader loader2; - DALI_TEST_EQUALS( (bool)loader2, false, TEST_LOCATION ); - - loader2 = loader; - DALI_TEST_EQUALS( (bool)loader2, true, TEST_LOCATION ); - - END_TEST; -} - -int UtcDaliBitmapLoaderGetUrl(void) -{ - TestApplication application; - - BitmapLoader loader = BitmapLoader::New( gImage_34_RGBA ); - DALI_TEST_CHECK( loader.GetUrl() == gImage_34_RGBA ); - - END_TEST; -} - - -int UtcDaliBitmapLoaderLoadP(void) -{ - TestApplication application; - - BitmapLoader loader1 = BitmapLoader::New( gImage_34_RGBA ); - DALI_TEST_CHECK( ! loader1.IsLoaded() ); - loader1.Load(); - DALI_TEST_CHECK( loader1.IsLoaded() ); - PixelData pixelData1 = loader1.GetPixelData(); - DALI_TEST_CHECK( pixelData1 ); - DALI_TEST_CHECK( pixelData1.GetWidth() == 34u ); - DALI_TEST_CHECK( pixelData1.GetHeight() == 34u ); - DALI_TEST_CHECK( pixelData1.GetPixelFormat() == Pixel::RGBA8888 ); - - BitmapLoader loader2 = BitmapLoader::New( gImage_128_RGB ); - DALI_TEST_CHECK( ! loader2.IsLoaded() ); - loader2.Load(); - DALI_TEST_CHECK( loader2.IsLoaded() ); - PixelData pixelData2 = loader2.GetPixelData(); - DALI_TEST_CHECK( pixelData2 ); - DALI_TEST_CHECK( pixelData2.GetWidth() == 128u ); - DALI_TEST_CHECK( pixelData2.GetHeight() == 128u ); - DALI_TEST_CHECK( pixelData2.GetPixelFormat() == Pixel::RGB888 ); - - END_TEST; -} - -int UtcDaliBitmapLoaderLoadN(void) -{ - TestApplication application; - - BitmapLoader loader = BitmapLoader::New( gImageNonExist ); - DALI_TEST_CHECK( ! loader.IsLoaded() ); - loader.Load(); - - // cannot load image that is not exist - DALI_TEST_CHECK( ! loader.IsLoaded() ); - PixelData pixelData = loader.GetPixelData(); - DALI_TEST_CHECK( !pixelData); - - END_TEST; -} diff --git a/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp b/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp index a4682bc..b05ffed 100644 --- a/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp +++ b/automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp @@ -45,25 +45,25 @@ void utc_dali_load_image_cleanup(void) int UtcDaliLoadImageP(void) { - PixelData pixelData = Dali::LoadImageFromFile( gImage_34_RGBA ); - DALI_TEST_CHECK( pixelData ); - DALI_TEST_EQUALS( pixelData.GetWidth(), 34u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData.GetHeight(), 34u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); - - PixelData pixelData2 = Dali::LoadImageFromFile( gImage_128_RGB ); - DALI_TEST_CHECK( pixelData2 ); - DALI_TEST_EQUALS( pixelData2.GetWidth(), 128u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData2.GetHeight(), 128u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION ); + Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile( gImage_34_RGBA ); + DALI_TEST_CHECK( pixelBuffer ); + DALI_TEST_EQUALS( pixelBuffer.GetWidth(), 34u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer.GetHeight(), 34u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + + Devel::PixelBuffer pixelBuffer2 = Dali::LoadImageFromFile( gImage_128_RGB ); + DALI_TEST_CHECK( pixelBuffer2 ); + DALI_TEST_EQUALS( pixelBuffer2.GetWidth(), 128u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer2.GetHeight(), 128u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION ); END_TEST; } int UtcDaliLoadImageN(void) { - PixelData pixelData = Dali::LoadImageFromFile( gImageNonExist ); - DALI_TEST_CHECK( !pixelData ); + Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile( gImageNonExist ); + DALI_TEST_CHECK( !pixelBuffer ); END_TEST; } @@ -77,25 +77,25 @@ int UtcDaliDownloadImageP(void) std::string url2("file://"); url2.append( gImage_128_RGB ); - PixelData pixelData = Dali::DownloadImageSynchronously( url ); - DALI_TEST_CHECK( pixelData ); - DALI_TEST_EQUALS( pixelData.GetWidth(), 34u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData.GetHeight(), 34u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + Devel::PixelBuffer pixelBuffer = Dali::DownloadImageSynchronously( url ); + DALI_TEST_CHECK( pixelBuffer ); + DALI_TEST_EQUALS( pixelBuffer.GetWidth(), 34u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer.GetHeight(), 34u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); - PixelData pixelData2 = Dali::DownloadImageSynchronously( url2 ); - DALI_TEST_CHECK( pixelData2 ); - DALI_TEST_EQUALS( pixelData2.GetWidth(), 128u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData2.GetHeight(), 128u, TEST_LOCATION ); - DALI_TEST_EQUALS( pixelData2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION ); + Devel::PixelBuffer pixelBuffer2 = Dali::DownloadImageSynchronously( url2 ); + DALI_TEST_CHECK( pixelBuffer2 ); + DALI_TEST_EQUALS( pixelBuffer2.GetWidth(), 128u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer2.GetHeight(), 128u, TEST_LOCATION ); + DALI_TEST_EQUALS( pixelBuffer2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION ); END_TEST; } int UtcDaliDownloadImageN(void) { - PixelData pixelData = Dali::DownloadImageSynchronously( gImageNonExist ); - DALI_TEST_CHECK( !pixelData ); + Devel::PixelBuffer pixelBuffer = Dali::DownloadImageSynchronously( gImageNonExist ); + DALI_TEST_CHECK( !pixelBuffer ); END_TEST; } diff --git a/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp b/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp new file mode 100644 index 0000000..4a83d8f --- /dev/null +++ b/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp @@ -0,0 +1,405 @@ +/* + * 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 +#include +#include +#include "mesh-builder.h" +using namespace Dali; + +void utc_dali_pixelbuffer_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_pixelbuffer_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliPixelBufferCreatePixelData(void) +{ + TestApplication application; + + unsigned int width = 20u; + unsigned int height = 20u; + Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, Pixel::RGB888 ); + + PixelData pixelData = imageData.CreatePixelData(); + + DALI_TEST_EQUALS( true, (bool)pixelData, TEST_LOCATION ); + + END_TEST; +} + + +void Mask1stQuadrant( Devel::PixelBuffer maskData ) +{ + int width = maskData.GetWidth(); + int height = maskData.GetHeight(); + Pixel::Format pixelFormat = maskData.GetPixelFormat(); + int bpp = Pixel::GetBytesPerPixel(pixelFormat); + + unsigned char* maskBuffer = maskData.GetBuffer(); + memset( maskBuffer, 0, width*height*bpp ); + int offset=0; + for( int x=0; x=width/2 || y>=height/2) + { + for(int b=0;b buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() ) + { + numSamples = 4; + } + + int srcAlphaByteOffset=0; + int srcAlphaMask=0; + Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat(); + + Channel alphaChannel = ALPHA; + if( Pixel::HasAlpha(srcPixelFormat) ) + { + Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask ); + } + else if( srcPixelFormat == Pixel::L8 ) + { + srcAlphaMask=0xFF; + alphaChannel = LUMINANCE; + } + + int destAlphaByteOffset=0; + int destAlphaMask=0; + Dali::Pixel::GetAlphaOffsetAndMask( buffer.GetPixelFormat(), destAlphaByteOffset, destAlphaMask ); + + unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat ); + int srcStride = mask.GetWidth() * srcBytesPerPixel; + unsigned char* srcBuffer = mask.GetBuffer(); + unsigned char* destBuffer = buffer.GetBuffer(); + + unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() ); + + int srcOffset=0; + int destOffset=0; + + float srcAlphaValue = 1.0f; + + for( unsigned int row = 0; row < buffer.GetHeight(); ++row ) + { + for( unsigned int col = 0; col < buffer.GetWidth(); ++col ) + { + if( numSamples == 1 ) + { + srcOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel; + unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask; + srcAlphaValue = float(alpha)/255.0f; + } + else + { + srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel ); + } + + unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask; + float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f); + destAlpha = destAlphaValue; + destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask; + destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask ); + + destOffset += destBytesPerPixel; + } + } +} + +PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask ) +{ + const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight()); + const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ; + + int numSamples = 1; + if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() ) + { + numSamples = 4; + } + + // Set up source alpha offsets + int srcAlphaByteOffset=0; + int srcAlphaMask=0; + Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat(); + Channel alphaChannel = ALPHA; + if( Pixel::HasAlpha(srcPixelFormat) ) + { + Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask ); + } + else if( srcPixelFormat == Pixel::L8 ) + { + srcAlphaMask=0xFF; + alphaChannel = LUMINANCE; + } + + unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat ); + int srcStride = mask.GetWidth() * srcBytesPerPixel; + unsigned char* srcBuffer = mask.GetBuffer(); + + // Set up source color offsets + Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat(); + unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcColorPixelFormat ); + + // 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 ); + + PixelBufferPtr newPixelBuffer = PixelBuffer::New( buffer.GetWidth(), buffer.GetHeight(), + destPixelFormat ); + unsigned char* destBuffer = newPixelBuffer->GetBuffer(); + + unsigned char* oldBuffer = buffer.GetBuffer(); + + int srcAlphaOffset=0; + int srcColorOffset=0; + int destOffset=0; + bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat()); + + float srcAlphaValue = 1.0f; + unsigned char destAlpha = 0; + + for( unsigned int row = 0; row < buffer.GetHeight(); ++row ) + { + for( unsigned int col = 0; col < buffer.GetWidth(); ++col ) + { + if( numSamples == 1 ) + { + srcAlphaOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel; + unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask; + srcAlphaValue = float(alpha)/255.0f; + } + else + { + srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel ); + } + + ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset ); + + if( hasAlpha ) + { + destAlpha = ConvertAlphaChannelToA8( oldBuffer, srcColorOffset, srcColorPixelFormat ); + 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; + } + } + + return newPixelBuffer; +} + + +float ReadWeightedSample( unsigned char* buffer, Pixel::Format pixelFormat, int stride, float x, float y, int width, int height, Channel alphaChannel ) +{ + int srcRow = floorf( y ); + int srcCol = floorf( x ); + + int bytesPerPixel = Dali::Pixel::GetBytesPerPixel( pixelFormat ); + int srcOffset = srcRow * stride + srcCol * bytesPerPixel; + float samples[4]; + + samples[0] = ReadChannel( buffer + srcOffset, pixelFormat, alphaChannel ); + + if( srcCol < width-1 ) + { + samples[1] = ReadChannel( buffer + srcOffset+bytesPerPixel, pixelFormat, alphaChannel ); + } + else + { + samples[1] = samples[0]; + } + + if( srcRow < height-1 ) + { + samples[2] = ReadChannel( buffer + stride + srcOffset, pixelFormat, alphaChannel ); + } + else + { + samples[2] = samples[0]; + } + + if( srcRow < height-1 && srcCol < width-1 ) + { + samples[3] = ReadChannel( buffer + stride + srcOffset + bytesPerPixel, pixelFormat, alphaChannel ); + } + 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]) ) / 255.0f; +} + +} //namespace Adaptor + +}// namespace Internal + +}// namespace Dali diff --git a/platform-abstractions/portable/alpha-mask.h b/platform-abstractions/portable/alpha-mask.h new file mode 100644 index 0000000..192b9f5 --- /dev/null +++ b/platform-abstractions/portable/alpha-mask.h @@ -0,0 +1,66 @@ +#ifndef DALI_INTERNAL_ADAPTOR_ALPHA_MASK_H +#define DALI_INTERNAL_ADAPTOR_ALPHA_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 "pixel-buffer-impl.h" + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ + + +/** + * Apply the mask to a buffer's alpha channel + * @param[in] buffer The buffer to apply the mask to + * @param[in] mask The mask to apply + */ +void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask ); + +/** + * Create a new PixelBuffer with an alpha channel large enough to handle the alpha from + * the mask, converting the color values to the new size, and either multiplying the mask's + * alpha into the existing alpha value, or writing the mask's alpha value directly into + * the new buffer's alpha channel. + * + * @param[in] buffer The buffer to apply the mask to + * @param[in] mask The mask to apply + * @return A new pixel buffer containing the masked image + */ +PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask ); + +/** + * Read a weighted sample from the given channel for a given coordinate + * @param[in] buffer The buffer to read from + * @param[in] pixelFormat The pixel format of the buffer + * @param[in] stride The stride across the buffer + * @param[in] x The x coordinate to sample from + * @param[in] y The y coordinate to sample from + * @param[in] width The width of the buffer in pixels + * @param[in] height The height of the buffer in pixels + * @param[in] channel The channel to read from + * @return An averaged value from the 4 pixels around the given coordinate + */ +float ReadWeightedSample( unsigned char* buffer, Pixel::Format pixelFormat, int stride, float x, float y, int width, int height, Channel channel ); + +} //namespace Adaptor +} //namespace Internal +} //namespace Dali + +#endif // DALI_INTERNAL_ADAPTOR_ALPHA_MASK_H diff --git a/platform-abstractions/portable/pixel-manipulation.cpp b/platform-abstractions/portable/pixel-manipulation.cpp new file mode 100644 index 0000000..ef2defc --- /dev/null +++ b/platform-abstractions/portable/pixel-manipulation.cpp @@ -0,0 +1,714 @@ +/* + * 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 "pixel-manipulation.h" + +// INTERNAL HEADERS +#include +#include + +namespace Dali +{ +namespace Internal +{ +namespace Adaptor +{ + +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(*pixelData); + } + else return 0u; + } + case Dali::Pixel::L8: + { + if( channel == LUMINANCE ) + { + return static_cast(*pixelData); + } + else return 0u; + } + case Dali::Pixel::LA88: + { + if( channel == LUMINANCE ) + { + return static_cast(*pixelData); + } + else if( channel == ALPHA ) + { + return static_cast(*(pixelData+1)); + } + else return 0u; + } + case Dali::Pixel::RGB565: + { + if( channel == RED ) + { + return (static_cast(*pixelData) & 0xF8) >> 3; + } + else if( channel == GREEN ) + { + return ((static_cast(*pixelData) & 0x07) << 3) | + ((static_cast(*(pixelData+1)) & 0xE0) >> 5); + } + else if( channel == BLUE ) + { + return static_cast(*(pixelData+1)) & 0x1F; + } + else return 0u; + } + + case Dali::Pixel::BGR565: + { + if( channel == BLUE ) + { + return (static_cast(*pixelData) & 0xF8) >> 3; + } + else if( channel == GREEN ) + { + return ((static_cast(*pixelData) & 0x07) << 3) | + ((static_cast(*(pixelData+1)) & 0xE0) >> 5); + } + else if( channel == RED ) + { + return (static_cast(*(pixelData+1) & 0x1F) ); + } + else return 0u; + } + + case Dali::Pixel::RGB888: + case Dali::Pixel::RGB8888: + { + if( channel == RED ) + { + return static_cast(*pixelData); + } + else if( channel == GREEN ) + { + return static_cast(*(pixelData+1)); + } + else if( channel == BLUE ) + { + return static_cast(*(pixelData+2)); + } + else return 0u; + } + + case Dali::Pixel::BGR8888: + { + if( channel == BLUE ) + { + return static_cast(*pixelData); + } + else if( channel == GREEN ) + { + return static_cast(*(pixelData+1)); + } + else if( channel == RED ) + { + return static_cast(*(pixelData+2)); + } + else return 0u; + } + + case Dali::Pixel::RGBA8888: + { + if( channel == RED ) + { + return static_cast(*pixelData); + } + else if( channel == GREEN ) + { + return static_cast(*(pixelData+1)); + } + else if( channel == BLUE ) + { + return static_cast(*(pixelData+2)); + } + else if( channel == ALPHA ) + { + return static_cast(*(pixelData+3)); + } + else return 0u; + } + + case Dali::Pixel::BGRA8888: + { + if( channel == BLUE ) + { + return static_cast(*pixelData); + } + else if( channel == GREEN ) + { + return static_cast(*(pixelData+1)); + } + else if( channel == RED ) + { + return static_cast(*(pixelData+2)); + } + else if( channel == ALPHA ) + { + return static_cast(*(pixelData+3)); + } + else return 0u; + } + + case Dali::Pixel::RGBA4444: + { + if( channel == RED ) + { + return (static_cast(*pixelData) & 0xF0) >> 4; + } + else if( channel == GREEN ) + { + return (static_cast(*pixelData) & 0x0F); + } + else if( channel == BLUE ) + { + return (static_cast(*(pixelData+1)) & 0xF0) >> 4; + } + else if( channel == ALPHA ) + { + return (static_cast(*(pixelData+1)) & 0x0F); + } + else return 0u; + } + + case Dali::Pixel::BGRA4444: + { + if( channel == BLUE ) + { + return (static_cast(*pixelData) & 0xF0) >> 4; + } + else if( channel == GREEN ) + { + return (static_cast(*pixelData) & 0x0F); + } + else if( channel == RED ) + { + return (static_cast(*(pixelData+1)) & 0xF0) >> 4; + } + else if( channel == ALPHA ) + { + return (static_cast(*(pixelData+1)) & 0x0F); + } + else return 0u; + } + + case Dali::Pixel::RGBA5551: + { + if( channel == RED ) + { + return (static_cast(*pixelData) & 0xF8) >> 3; + } + else if( channel == GREEN ) + { + return ((static_cast(*pixelData) & 0x07) << 2) | + ((static_cast(*(pixelData+1)) & 0xC0) >> 6); + } + else if( channel == BLUE ) + { + return (static_cast(*(pixelData+1)) & 0x3E) >> 1; + } + else if( channel == ALPHA ) + { + return static_cast(*(pixelData+1)) & 0x01; + } + + else return 0u; + } + + case Dali::Pixel::BGRA5551: + { + if( channel == BLUE ) + { + return (static_cast(*pixelData) & 0xF8) >> 3; + } + else if( channel == GREEN ) + { + return ((static_cast(*pixelData) & 0x07) << 2) | + ((static_cast(*(pixelData+1)) & 0xC0) >> 6); + } + else if( channel == RED ) + { + return ( static_cast(*(pixelData+1)) & 0x3E) >> 1; + } + else if( channel == ALPHA ) + { + return static_cast(*(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( channelValue & 0xFF ); + } + break; + } + case Dali::Pixel::L8: + { + if( channel == LUMINANCE ) + { + *pixelData = static_cast( channelValue & 0xFF ); + } + break; + } + case Dali::Pixel::LA88: + { + if( channel == LUMINANCE ) + { + *pixelData = static_cast( channelValue & 0xFF ); + } + else if( channel == ALPHA ) + { + *(pixelData+1) = static_cast( channelValue & 0xFF ); + } + break; + } + case Dali::Pixel::RGB565: + { + if( channel == RED ) + { + *pixelData &= ~0xF8; + *pixelData |= static_cast( (channelValue << 3) & 0xF8 ); + } + else if( channel == GREEN ) + { + *pixelData &= ~0x07; + *pixelData |= static_cast( (channelValue >> 3) & 0x07 ); + + *(pixelData+1) &= ~0xE0; + *(pixelData+1) |= static_cast( (channelValue << 5) & 0xE0 ); + } + else if( channel == BLUE ) + { + *(pixelData+1) &= ~0x1F; + *(pixelData+1) |= static_cast( channelValue & 0x1F ); + } + break; + } + + case Dali::Pixel::BGR565: + { + if( channel == BLUE ) + { + *pixelData &= ~0xF8; + *pixelData |= static_cast( (channelValue << 3) & 0xF8 ); + } + else if( channel == GREEN ) + { + *pixelData &= ~0x07; + *pixelData |= static_cast( (channelValue >> 3) & 0x07 ); + + *(pixelData+1) &= ~0xE0; + *(pixelData+1) |= static_cast( (channelValue << 5) & 0xE0 ); + } + else if( channel == RED ) + { + *(pixelData+1) &= ~0x1F; + *(pixelData+1) |= static_cast( channelValue & 0x1F ); + } + break; + } + + case Dali::Pixel::RGB888: + case Dali::Pixel::RGB8888: + { + if( channel == RED ) + { + *pixelData = static_cast( channelValue & 0xFF ); + } + else if( channel == GREEN ) + { + *(pixelData+1) = static_cast( channelValue & 0xFF ); + } + else if( channel == BLUE ) + { + *(pixelData+2) = static_cast( channelValue & 0xFF ); + } + break; + } + + case Dali::Pixel::BGR8888: + { + if( channel == BLUE ) + { + *pixelData = static_cast( channelValue & 0xFF ); + } + else if( channel == GREEN ) + { + *(pixelData+1) = static_cast( channelValue & 0xFF ); + } + else if( channel == RED ) + { + *(pixelData+2) = static_cast( channelValue & 0xFF ); + } + break; + } + + case Dali::Pixel::RGBA8888: + { + if( channel == RED ) + { + *pixelData = static_cast( channelValue & 0xFF ); + } + else if( channel == GREEN ) + { + *(pixelData+1) = static_cast( channelValue & 0xFF ); + } + else if( channel == BLUE ) + { + *(pixelData+2) = static_cast( channelValue & 0xFF ); + } + else if( channel == ALPHA ) + { + *(pixelData+3) = static_cast( channelValue & 0xFF ); + } + break; + } + + case Dali::Pixel::BGRA8888: + { + if( channel == BLUE ) + { + *pixelData = static_cast( channelValue & 0xFF ); + } + else if( channel == GREEN ) + { + *(pixelData+1) = static_cast( channelValue & 0xFF ); + } + else if( channel == RED ) + { + *(pixelData+2) = static_cast( channelValue & 0xFF ); + } + else if( channel == ALPHA ) + { + *(pixelData+3) = static_cast( channelValue & 0xFF ); + } + break; + } + + case Dali::Pixel::RGBA4444: + { + if( channel == RED ) + { + *pixelData &= ~0xF0; + *pixelData |= static_cast( (channelValue << 4) & 0xF0 ); + } + else if( channel == GREEN ) + { + *pixelData &= ~0x0F; + *pixelData |= static_cast( channelValue & 0x0F ); + } + else if( channel == BLUE ) + { + *(pixelData+1) &= ~0xF0; + *(pixelData+1) |= static_cast( (channelValue << 4) & 0xF0 ); + } + else if( channel == ALPHA ) + { + *(pixelData+1) &= ~0x0F; + *(pixelData+1) |= static_cast( channelValue & 0x0F ); + } + break; + } + + case Dali::Pixel::BGRA4444: + { + if( channel == BLUE ) + { + *pixelData &= ~0xF0; + *pixelData |= static_cast( (channelValue << 4) & 0xF0 ); + } + else if( channel == GREEN ) + { + *pixelData &= ~0x0F; + *pixelData |= static_cast( channelValue & 0x0F ); + } + else if( channel == RED ) + { + *(pixelData+1) &= ~0xF0; + *(pixelData+1) |= static_cast( (channelValue << 4) & 0xF0 ); + } + else if( channel == ALPHA ) + { + *(pixelData+1) &= ~0x0F; + *(pixelData+1) |= static_cast( channelValue & 0x0F ); + } + break; + } + + case Dali::Pixel::RGBA5551: + { + // rrrrrggg ggbbbbba + // F8 7 C0 3E 1 + if( channel == RED ) + { + *pixelData &= ~0xF8; + *pixelData |= static_cast( (channelValue << 3) & 0xF8 ); + } + else if( channel == GREEN ) + { + *pixelData &= ~0x07; + *pixelData |= static_cast( (channelValue >> 2) & 0x07 ); + + *(pixelData+1) &= ~0xC0; + *(pixelData+1) |= static_cast( (channelValue << 6) & 0xC0 ); + } + else if( channel == BLUE ) + { + *(pixelData+1) &= ~0x3E; + *(pixelData+1) |= static_cast( (channelValue << 1) & 0x3E ); + } + else if( channel == ALPHA ) + { + *(pixelData+1) &= ~0x01; + *(pixelData+1) |= static_cast( channelValue & 0x01 ); + } + break; + } + + case Dali::Pixel::BGRA5551: + { + if( channel == BLUE ) + { + *pixelData &= ~0xF8; + *pixelData |= static_cast( (channelValue << 3) & 0xF8 ); + } + else if( channel == GREEN ) + { + *pixelData &= ~0x07; + *pixelData |= static_cast( (channelValue >> 2) & 0x07 ); + + *(pixelData+1) &= ~0xC0; + *(pixelData+1) |= static_cast( (channelValue << 6) & 0xC0 ); + } + else if( channel == RED ) + { + *(pixelData+1) &= ~0x3E; + *(pixelData+1) |= static_cast( (channelValue << 1 ) & 0x3E ); + } + else if( channel == ALPHA ) + { + *(pixelData+1) &= ~0x01; + *(pixelData+1) |= static_cast( 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 = (red<<3) | (red & 0x07); + green = (green << 2) | (green & 0x03); + blue = (blue<<3) | (blue & 0x07); + break; + } + case Dali::Pixel::RGBA4444: + case Dali::Pixel::BGRA4444: + { + red = (red<<4) | (red&0x0F); + green = (green<<4) | (green&0x0F); + blue = (blue<<4) | (blue&0x0F); + break; + } + case Dali::Pixel::RGBA5551: + case Dali::Pixel::BGRA5551: + { + red = (red<<3) | (red&0x07); + green = (green<<3) | (green&0x07); + blue = (blue<<3) | (blue&0x07); + 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); +} + + +int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat ) +{ + int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA ); + int destAlpha = alpha; + switch( srcFormat ) + { + case Pixel::RGBA5551: + case Pixel::BGRA5551: + { + destAlpha = (alpha==0)?0:255; + break; + } + case Pixel::RGBA4444: + case Pixel::BGRA4444: + { + destAlpha = (alpha<<4) | (alpha&0x0F); + break; + } + default: + break; + } + return destAlpha; +} + +} // Adaptor +} // Internal +} // Dali diff --git a/platform-abstractions/portable/pixel-manipulation.h b/platform-abstractions/portable/pixel-manipulation.h new file mode 100644 index 0000000..611b5a6 --- /dev/null +++ b/platform-abstractions/portable/pixel-manipulation.h @@ -0,0 +1,101 @@ +#ifndef DALI_INTERNAL_ADAPTOR_PIXEL_MANIPULATION_H +#define DALI_INTERNAL_ADAPTOR_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 + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +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 ); + +/** + * Convert the colors in the source pixel from their natural format to RGBA8888. + * @param[in] srcBuffer The source buffer to read from + * @param[in] srcOffset The offset of the pixel to convert + * @param[in] srcFormat The pixel format of the source pixel + * @param[in] destBuffer The destination buffer to write to + * @param[in] destOffset The offset of the pixel to write + */ +void ConvertColorChannelsToRGBA8888( + unsigned char* srcBuffer, int srcOffset, Dali::Pixel::Format srcFormat, + unsigned char* destBuffer, int destOffset ); + +/** + * Convert the alpha in the source pixel to A8. + * @param[in] srcBuffer The source buffer to read from + * @param[in] srcOffset The offset of the pixel to convert + * @param[in] srcFormat The pixel format of the source pixel + * @return the alpha value in the range 0-255 + */ +int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat ); + + +} // Adaptor +} // Internal +} // Dali + + +#endif // DALI_INTERNAL_ADAPTOR_PIXEL_MANIPULATION_H diff --git a/platform-abstractions/tizen/file.list b/platform-abstractions/tizen/file.list index be5f212..bb4e908 100755 --- a/platform-abstractions/tizen/file.list +++ b/platform-abstractions/tizen/file.list @@ -16,7 +16,10 @@ tizen_platform_abstraction_src_files = \ $(tizen_platform_abstraction_src_dir)/image-loaders/loader-png.cpp \ $(tizen_platform_abstraction_src_dir)/image-loaders/loader-wbmp.cpp \ $(tizen_platform_abstraction_src_dir)/image-loaders/image-loader.cpp \ - $(portable_platform_abstraction_src_dir)/image-operations.cpp + \ + $(portable_platform_abstraction_src_dir)/image-operations.cpp \ + $(portable_platform_abstraction_src_dir)/pixel-manipulation.cpp \ + $(portable_platform_abstraction_src_dir)/alpha-mask.cpp # Add public headers here: -- 2.7.4