- Make animated-image-loading interface for gif and webp.
- Animated WebP requires WEBP_DEMUX_ABI_VERSION 0x0107 or later
Change-Id: I5331163e2b0d68a6ef7cb5a06d6e59a5140ffca9
Signed-off-by: Seungho, Baek <sbsh.baek@samsung.com>
#include <stdlib.h>
#include <dali/dali.h>
#include <dali-test-suite-utils.h>
-#include <dali/devel-api/adaptor-framework/gif-loading.h>
+#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
using namespace Dali;
}
}
-void utc_dali_gif_loader_startup(void)
+void utc_dali_animated_image_loader_startup(void)
{
test_return_value = TET_UNDEF;
}
-void utc_dali_gif_loader_cleanup(void)
+void utc_dali_animated_image_loader_cleanup(void)
{
test_return_value = TET_PASS;
}
-int UtcDaliGifLoadingP(void)
+int UtcDaliAnimatedImageLoadingP(void)
{
std::vector<Dali::PixelData> pixelDataList;
Dali::Vector<uint32_t> frameDelayList;
- std::unique_ptr<Dali::GifLoading> gifLoading = GifLoading::New( gGif_100_None, true );
- bool succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList );
+ Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_None, true );
+ bool succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList );
+ frameDelayList.Clear();
+ frameDelayList.Resize( animatedImageLoading.GetImageCount(), 0 );
+ for( uint32_t i = 0; i < animatedImageLoading.GetImageCount(); ++i )
+ {
+ frameDelayList[i] = animatedImageLoading.GetFrameInterval( i );
+ }
// Check that the loading succeed
DALI_TEST_CHECK( succeed );
VerifyLoad( pixelDataList, frameDelayList, 5u, 100u, 100u, 1000u );
pixelDataList.clear();
- gifLoading = GifLoading::New( gGif_100_Prev, true );
- succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList );
+ animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_Prev, true );
+ succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList );
+ frameDelayList.Clear();
+ frameDelayList.Resize( animatedImageLoading.GetImageCount(), 0 );
+ for( uint32_t i = 0; i < animatedImageLoading.GetImageCount(); ++i )
+ {
+ frameDelayList[i] = animatedImageLoading.GetFrameInterval( i );
+ }
+
// Check that the loading succeed
DALI_TEST_CHECK( succeed );
VerifyLoad( pixelDataList, frameDelayList, 5u, 100u, 100u, 1000u );
pixelDataList.clear();
- gifLoading = GifLoading::New( gGif_100_Bgnd, true );
- succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList );
+ animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_Bgnd, true );
+ succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList );
+ frameDelayList.Clear();
+ frameDelayList.Resize( animatedImageLoading.GetImageCount(), 0 );
+ for( uint32_t i = 0; i < animatedImageLoading.GetImageCount(); ++i )
+ {
+ frameDelayList[i] = animatedImageLoading.GetFrameInterval( i );
+ }
// Check that the loading succeed
DALI_TEST_CHECK( succeed );
END_TEST;
}
-int UtcDaliGifLoadingN(void)
+int UtcDaliAnimatedImageLoadingN(void)
{
std::vector<Dali::PixelData> pixelDataList;
Dali::Vector<uint32_t> frameDelayList;
- std::unique_ptr<Dali::GifLoading> gifLoading = GifLoading::New( gGifNonExist, true );
- bool succeed = gifLoading->LoadAllFrames( pixelDataList, frameDelayList );
+ Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGifNonExist, true );
+ bool succeed = animatedImageLoading.LoadNextNFrames( 0u, animatedImageLoading.GetImageCount(), pixelDataList );
// Check that the loading failed
DALI_TEST_CHECK( !succeed );
// Check that both pixelDataList and frameDelayList are empty
DALI_TEST_EQUALS( pixelDataList.size(), 0u, TEST_LOCATION );
- DALI_TEST_EQUALS( frameDelayList.Size(), 0u, TEST_LOCATION );
END_TEST;
}
-int UtcDaliGifLoadingGetImageSizeP(void)
+int UtcDaliAnimatedImageLoadingGetImageSizeP(void)
{
- std::unique_ptr<Dali::GifLoading> gifLoading = GifLoading::New( gGif_100_None, true );
- ImageDimensions imageSize = gifLoading->GetImageSize();
+ Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGif_100_None, true );
+ ImageDimensions imageSize = animatedImageLoading.GetImageSize();
// Check that the image size is [100, 100]
DALI_TEST_EQUALS( imageSize.GetWidth(), 100u, TEST_LOCATION );
END_TEST;
}
-int UtcDaliGifLoadingGetImageSizeN(void)
+int UtcDaliAnimatedImageLoadingGetImageSizeN(void)
{
- std::unique_ptr<Dali::GifLoading> gifLoading = GifLoading::New( gGifNonExist, true );
- ImageDimensions imageSize = gifLoading->GetImageSize();
+ Dali::AnimatedImageLoading animatedImageLoading = Dali::AnimatedImageLoading::New( gGifNonExist, true );
+ ImageDimensions imageSize = animatedImageLoading.GetImageSize();
- // Check that it returns zero size when the gif is not valid
+ // Check that it returns zero size when the animated image is not valid
DALI_TEST_EQUALS( imageSize.GetWidth(), 0u, TEST_LOCATION );
DALI_TEST_EQUALS( imageSize.GetHeight(), 0u, TEST_LOCATION );
ENDIF()
ENDIF()
+SET( REQUIRED_LIBS ${REQUIRED_LIBS} webp webpdemux )
+
TARGET_LINK_LIBRARIES( ${name}
${DALI_LDFLAGS}
- ${REQUIRED_LIBS}
- ${OPTIONAL_LIBS}
- ${COVERAGE}
+ ${REQUIRED_LIBS}
+ ${OPTIONAL_LIBS}
+ ${COVERAGE}
)
SET_TARGET_PROPERTIES( ${name}
--- /dev/null
+/*
+ * Copyright (c) 2020 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/devel-api/adaptor-framework/animated-image-loading.h>
+
+// INTERNAL HEADER
+#include <dali/internal/imaging/common/animated-image-loading-impl.h>
+#include <dali/internal/imaging/common/gif-loading.h>
+#include <dali/internal/imaging/common/webp-loading.h>
+
+namespace Dali
+{
+
+AnimatedImageLoading::AnimatedImageLoading()
+{
+}
+
+AnimatedImageLoading AnimatedImageLoading::New( const std::string& url, bool isLocalResource )
+{
+
+ const std::size_t urlSize = url.length();
+
+ Internal::Adaptor::AnimatedImageLoadingPtr internal = NULL;
+ if(urlSize >= 4){ // Avoid throwing out_of_range or failing silently if exceptions are turned-off on the compare(). (http://www.cplusplus.com/reference/string/string/compare/)
+ if( !url.compare( urlSize - 4, 4, ".gif" )
+ || !url.compare( urlSize - 4, 4, ".GIF" ) )
+ {
+ internal = Internal::Adaptor::GifLoading::New( url, isLocalResource );
+ }
+ }
+ if(urlSize >= 5){ // Avoid throwing out_of_range or failing silently if exceptions are turned-off on the compare(). (http://www.cplusplus.com/reference/string/string/compare/)
+ if( !url.compare( urlSize - 5, 5, ".webp" )
+ || !url.compare( urlSize - 5, 5, ".WEBP" ) )
+ {
+ internal = Internal::Adaptor::WebPLoading::New( url, isLocalResource );
+ }
+ }
+
+ return AnimatedImageLoading( internal.Get() );
+}
+
+AnimatedImageLoading AnimatedImageLoading::DownCast( BaseHandle handle )
+{
+ return AnimatedImageLoading( dynamic_cast< Internal::Adaptor::AnimatedImageLoading* >( handle.GetObjectPtr() ) );
+}
+
+AnimatedImageLoading::~AnimatedImageLoading()
+{
+}
+
+bool AnimatedImageLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData )
+{
+ return GetImplementation( *this ).LoadNextNFrames( frameStartIndex, count, pixelData );
+}
+
+ImageDimensions AnimatedImageLoading::GetImageSize() const
+{
+ return GetImplementation( *this ).GetImageSize();
+}
+
+uint32_t AnimatedImageLoading::GetImageCount() const
+{
+ return GetImplementation( *this ).GetImageCount();
+}
+
+uint32_t AnimatedImageLoading::GetFrameInterval( uint32_t frameIndex ) const
+{
+ return GetImplementation( *this ).GetFrameInterval( frameIndex );
+}
+
+AnimatedImageLoading::AnimatedImageLoading( Internal::Adaptor::AnimatedImageLoading* internal )
+: BaseHandle( internal )
+{
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_ANIMATED_IMAGE_LOADING_H
+#define DALI_ANIMATED_IMAGE_LOADING_H
+
+/*
+ * Copyright (c) 2020 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 <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/uint-16-pair.h>
+#include <dali/public-api/object/base-handle.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-adaptor-common.h>
+
+namespace Dali
+{
+
+class PixelData;
+typedef Dali::Uint16Pair ImageDimensions;
+
+/**
+ * @addtogroup dali_adaptor_framework
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+namespace Adaptor
+{
+class AnimatedImageLoading;
+}
+}
+
+/**
+ * Class to manage loading frames of an animated image in small chunks. Lazy initializes only when
+ * data is actually needed.
+ * Note, once the Animated Image has loaded, the undecoded data will reside in memory until this object
+ * is released. (This is to speed up frame loads, which would otherwise have to re-acquire the
+ * data from disk)
+ */
+class DALI_ADAPTOR_API AnimatedImageLoading : public BaseHandle
+{
+public:
+
+ /**
+ * Create a GifLoading with the given url and resourceType.
+ * @param[in] url The url of the animated image to load
+ * @param[in] isLocalResource The true or false whether this is a local resource.
+ * @return A newly created GifLoading.
+ */
+ static AnimatedImageLoading New( const std::string& url, bool isLocalResource );
+
+ /**
+ * @brief Constructor
+ */
+ AnimatedImageLoading();
+
+ /**
+ * @brief Downcast an Object handle to Capture handle.
+ *
+ * If handle points to a Capture object the downcast produces valid
+ * handle. If not the returned handle is left uninitialized.
+ *
+ * @param[in] handle to An object.
+ * @return handle to a Capture object or an uninitialized handle.
+ */
+ static AnimatedImageLoading DownCast( BaseHandle handle );
+
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @param[in] copy The AnimatedImageLoading to copy
+ */
+ AnimatedImageLoading(const AnimatedImageLoading& copy) = default;
+
+ /**
+ * @brief Assignment operator
+ *
+ * @param[in] rhs The AnimatedImageLoading to copy
+ * @return A reference to this
+ */
+ AnimatedImageLoading& operator=(const AnimatedImageLoading& rhs) = default;
+
+ /**
+ * @brief Destructor
+ */
+ ~AnimatedImageLoading();
+
+ /**
+ * @brief Load the next N Frames of the animated image.
+ *
+ * @note This function will load the entire animated image into memory if not already loaded.
+ * @param[in] frameStartIndex The frame counter to start from. Will usually be the next frame
+ * after the previous invocation of this method, or 0 to start.
+ * @param[in] count The number of frames to load
+ * @param[out] pixelData The vector in which to return the frame data
+ * @return True if the frame data was successfully loaded
+ */
+ bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData );
+
+ /**
+ * @brief Get the size of a animated image.
+ *
+ * @return The width and height in pixels of the animated image.
+ */
+ ImageDimensions GetImageSize() const;
+
+ /**
+ * @brief Get the number of frames in this animated image.
+ */
+ uint32_t GetImageCount() const;
+
+ /**
+ * @brief Get the frame interval of the frame index
+ *
+ * @note The frame is needed to be loaded before this function is called.
+ *
+ * @return The time interval of the frame(microsecond).
+ */
+ uint32_t GetFrameInterval( uint32_t frameIndex ) const;
+
+public: // Not intended for application developers
+ /// @cond internal
+ /**
+ * @brief This constructor is used by New() methods.
+ *
+ * @param[in] internal A pointer to a newly allocated Dali resource.
+ */
+ explicit DALI_INTERNAL AnimatedImageLoading( Internal::Adaptor::AnimatedImageLoading* internal );
+ /// @endcond
+};
+
+} // namespace Dali
+
+#endif // DALI_ANIMATED_IMAGE_LOADING_H
SET( devel_api_src_files
${adaptor_devel_api_dir}/adaptor-framework/accessibility-adaptor.cpp
+ ${adaptor_devel_api_dir}/adaptor-framework/animated-image-loading.cpp
${adaptor_devel_api_dir}/adaptor-framework/application-devel.cpp
${adaptor_devel_api_dir}/adaptor-framework/bitmap-saver.cpp
${adaptor_devel_api_dir}/adaptor-framework/clipboard.cpp
${adaptor_devel_api_dir}/adaptor-framework/file-loader.cpp
${adaptor_devel_api_dir}/adaptor-framework/file-stream.cpp
${adaptor_devel_api_dir}/adaptor-framework/image-loading.cpp
- ${adaptor_devel_api_dir}/adaptor-framework/gif-loading.cpp
${adaptor_devel_api_dir}/adaptor-framework/input-method-context.cpp
${adaptor_devel_api_dir}/adaptor-framework/input-method-options.cpp
${adaptor_devel_api_dir}/adaptor-framework/native-image-source-devel.cpp
${adaptor_devel_api_dir}/adaptor-framework/accessibility-action-handler.h
${adaptor_devel_api_dir}/adaptor-framework/accessibility-gesture-handler.h
${adaptor_devel_api_dir}/adaptor-framework/accessibility-gesture-event.h
+ ${adaptor_devel_api_dir}/adaptor-framework/animated-image-loading.h
${adaptor_devel_api_dir}/adaptor-framework/application-devel.h
${adaptor_devel_api_dir}/adaptor-framework/atspi-accessibility.h
${adaptor_devel_api_dir}/adaptor-framework/bitmap-saver.h
${adaptor_devel_api_dir}/adaptor-framework/image-loader-input.h
${adaptor_devel_api_dir}/adaptor-framework/image-loader-plugin.h
${adaptor_devel_api_dir}/adaptor-framework/image-loading.h
- ${adaptor_devel_api_dir}/adaptor-framework/gif-loading.h
${adaptor_devel_api_dir}/adaptor-framework/input-method-context.h
${adaptor_devel_api_dir}/adaptor-framework/input-method-options.h
${adaptor_devel_api_dir}/adaptor-framework/keyboard.h
--- /dev/null
+#ifndef DALI_INTERNAL_ANIMATED_IMAGE_LOADING_IMPL_H
+#define DALI_INTERNAL_ANIMATED_IMAGE_LOADING_IMPL_H
+
+/*
+ * Copyright (c) 2020 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 <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/uint-16-pair.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-adaptor-common.h>
+#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
+
+namespace Dali
+{
+class PixelData;
+typedef Dali::Uint16Pair ImageDimensions;
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+class AnimatedImageLoading;
+typedef IntrusivePtr<AnimatedImageLoading> AnimatedImageLoadingPtr;
+
+/**
+ * Class interface for animated image loading.
+ * Each loading classes for animated image file format(e.g., gif and webp) needs to inherit this interface
+ */
+class AnimatedImageLoading : public BaseObject
+{
+public:
+
+ /**
+ * @copydoc Dali::AnimatedImageLoading::New()
+ */
+ static AnimatedImageLoadingPtr New( const std::string& url, bool isLocalResource );
+
+ AnimatedImageLoading() = default;
+
+ // Moveable but not copyable
+ AnimatedImageLoading( const AnimatedImageLoading& );
+ AnimatedImageLoading& operator=( const AnimatedImageLoading& );
+ AnimatedImageLoading( AnimatedImageLoading&& ) = default;
+ AnimatedImageLoading& operator=( AnimatedImageLoading&& ) = default;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~AnimatedImageLoading() = default;
+
+ /**
+ * @copydoc Dali::AnimatedImageLoading::LoadNextNFrames()
+ */
+ virtual bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData ) = 0;
+
+ /**
+ * @copydoc Dali::AnimatedImageLoading::GetImageSize()
+ */
+ virtual ImageDimensions GetImageSize() const = 0;
+
+ /**
+ * @copydoc Dali::AnimatedImageLoading::GetImageCount()
+ */
+ virtual uint32_t GetImageCount() const = 0;
+
+ /**
+ * @copydoc Dali::AnimatedImageLoading::LoadFrameDelays()
+ */
+ virtual uint32_t GetFrameInterval( uint32_t frameIndex ) const = 0;
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+// Helpers for api forwarding methods
+
+inline Internal::Adaptor::AnimatedImageLoading& GetImplementation( Dali::AnimatedImageLoading& handle)
+{
+ DALI_ASSERT_ALWAYS( handle && "AnimatedImageLoading handle is empty" );
+
+ BaseObject& object = handle.GetBaseObject();
+
+ return static_cast< Internal::Adaptor::AnimatedImageLoading& >( object );
+}
+
+inline const Internal::Adaptor::AnimatedImageLoading& GetImplementation( const Dali::AnimatedImageLoading& handle )
+{
+ DALI_ASSERT_ALWAYS( handle && "AnimatedImageLoading handle is empty" );
+
+ const BaseObject& object = handle.GetBaseObject();
+
+ return static_cast< const Internal::Adaptor::AnimatedImageLoading& >( object );
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_ANIMATED_IMAGE_LOADING_IMPL_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
*/
// CLASS HEADER
-#include <dali/devel-api/adaptor-framework/gif-loading.h>
+#include <dali/internal/imaging/common/gif-loading.h>
// EXTERNAL INCLUDES
#include <sys/types.h>
namespace Dali
{
+namespace Internal
+{
+
+namespace Adaptor
+{
+
namespace
{
#if defined(DEBUG_ENABLED)
ImageProperties imageProperties;
};
-std::unique_ptr<GifLoading> GifLoading::New( const std::string &url, bool isLocalResource )
+AnimatedImageLoadingPtr GifLoading::New( const std::string &url, bool isLocalResource )
{
- return std::unique_ptr<GifLoading>( new GifLoading( url, isLocalResource ) );
+ return AnimatedImageLoadingPtr( new GifLoading( url, isLocalResource ) );
}
GifLoading::GifLoading( const std::string &url, bool isLocalResource )
delete mImpl;
}
-bool GifLoading::LoadNextNFrames( int frameStartIndex, int count, std::vector<Dali::PixelData> &pixelData )
+bool GifLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData> &pixelData )
{
int error;
bool ret = false;
return ret;
}
-bool GifLoading::LoadAllFrames( std::vector<Dali::PixelData> &pixelData, Dali::Vector<uint32_t> &frameDelays )
-{
- if( LoadFrameDelays( frameDelays ) )
- {
- return LoadNextNFrames( 0, mImpl->loaderInfo.animated.frameCount, pixelData );
- }
- return false;
-}
-
-ImageDimensions GifLoading::GetImageSize()
+ImageDimensions GifLoading::GetImageSize() const
{
return ImageDimensions( mImpl->imageProperties.w, mImpl->imageProperties.h );
}
-int GifLoading::GetImageCount()
+uint32_t GifLoading::GetImageCount() const
{
return mImpl->loaderInfo.animated.frameCount;
}
-bool GifLoading::LoadFrameDelays( Dali::Vector<uint32_t> &frameDelays )
+uint32_t GifLoading::GetFrameInterval( uint32_t frameIndex ) const
{
- frameDelays.Clear();
+ return mImpl->loaderInfo.animated.frames[frameIndex].info.delay * 10;
+}
- for( auto &&elem : mImpl->loaderInfo.animated.frames )
- {
- // Read frame delay time, multiply 10 to change time unit to milliseconds
- frameDelays.PushBack( elem.info.delay * 10 );
- }
+} // namespace Adaptor
- return true;
-}
+} // namespace Internal
-} // namespace Dali
+} // namespace Dali
\ No newline at end of file
#define DALI_INTERNAL_GIF_LOADING_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// INTERNAL INCLUDES
#include <dali/public-api/dali-adaptor-common.h>
+#include <dali/internal/imaging/common/animated-image-loading-impl.h>
namespace Dali
{
-class PixelData;
-typedef Dali::Uint16Pair ImageDimensions;
+
+namespace Internal
+{
+
+namespace Adaptor
+{
/**
* Class to manage loading frames of an animated gif in small chunks. Lazy initializes only when
* is released. (This is to speed up frame loads, which would otherwise have to re-acquire the
* data from disk)
*/
-class DALI_ADAPTOR_API GifLoading
+class GifLoading: public Internal::Adaptor::AnimatedImageLoading
{
public:
* @param[in] isLocalResource The true or false whether this is a local resource.
* @return A newly created GifLoading.
*/
- static std::unique_ptr<GifLoading> New( const std::string& url, bool isLocalResource );
+ static AnimatedImageLoadingPtr New( const std::string& url, bool isLocalResource );
/**
* @brief Constructor
*/
GifLoading( const std::string& url, bool isLocalResource );
- // Moveable but not copyable
-
- GifLoading( const GifLoading& ) = delete;
- GifLoading& operator=( const GifLoading& ) = delete;
- GifLoading( GifLoading&& ) = default;
- GifLoading& operator=( GifLoading&& ) = default;
-
/**
* @brief Destructor
*/
- ~GifLoading();
+ ~GifLoading() override;
/**
* @brief Load the next N Frames of the gif.
* @param[out] pixelData The vector in which to return the frame data
* @return True if the frame data was successfully loaded
*/
- bool LoadNextNFrames( int frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData );
-
- /**
- * @brief Load all frames of an animated gif file.
- *
- * @note This function will load the entire gif into memory if not already loaded.
- *
- * @param[out] pixelData The loaded pixel data for each frame.
- * @param[out] frameDelays The loaded delay time for each frame.
- *
- * @return True if the loading succeeded, false otherwise.
- */
- bool LoadAllFrames( std::vector<Dali::PixelData>& pixelData, Dali::Vector<uint32_t>& frameDelays );
+ bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData ) override;
/**
* @brief Get the size of a gif image.
*
- * @note This function will load the entire gif into memory if not already loaded.
- *
* @return The width and height in pixels of the gif image.
*/
- ImageDimensions GetImageSize();
+ ImageDimensions GetImageSize() const override;
/**
* @brief Get the number of frames in this gif.
- *
- * @note This function will load the entire gif into memory if not already loaded.
*/
- int GetImageCount();
+ uint32_t GetImageCount() const override;
/**
- * @brief Load the frame delay counts into the provided array.
+ * @brief Get the frame interval of the frame index
*
- * @note This function will load the entire gif into memory if not already loaded.
- * @param[in] frameDelays a vector to write the frame delays into
- * @return true if the frame delays were successfully loaded
+ * @note The frame is needed to be loaded before this function is called.
+ *
+ * @return The time interval of the frame(microsecond).
*/
- bool LoadFrameDelays( Dali::Vector<uint32_t>& frameDelays );
+ uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
private:
struct Impl;
Impl* mImpl;
};
+} // namespace Adaptor
+
+} // namespace Internal
+
} // namespace Dali
#endif // DALI_INTERNAL_GIF_LOADING_H
--- /dev/null
+/*
+ * Copyright (c) 2020 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/imaging/common/webp-loading.h>
+
+// EXTERNAL INCLUDES
+#include <webp/decode.h>
+#include <webp/demux.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/images/pixel-data.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <cstring>
+#include <dali/internal/imaging/common/file-download.h>
+#include <dali/internal/system/common/file-reader.h>
+
+typedef unsigned char WebPByteType;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter *gWebPLoadingLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_GIF_LOADING" );
+#endif
+
+constexpr size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE = 50 * 1024 * 1024;
+
+}
+
+struct WebPLoading::Impl
+{
+public:
+ Impl( const std::string& url, bool isLocalResource )
+ : mUrl( url ),
+ mLoadingFrame( 0 )
+ {
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ if( ReadWebPInformation( isLocalResource ) )
+ {
+ WebPAnimDecoderOptions webPAnimDecoderOptions;
+ WebPAnimDecoderOptionsInit( &webPAnimDecoderOptions );
+ webPAnimDecoderOptions.color_mode = MODE_RGBA;
+ mWebPAnimDecoder = WebPAnimDecoderNew( &mWebPData, &webPAnimDecoderOptions );
+ WebPAnimDecoderGetInfo( mWebPAnimDecoder, &mWebPAnimInfo );
+ mTimeStamp.assign( mWebPAnimInfo.frame_count, 0 );
+ }
+#endif
+ }
+
+ bool ReadWebPInformation( bool isLocalResource )
+ {
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ WebPDataInit( &mWebPData );
+ if( isLocalResource )
+ {
+ Internal::Platform::FileReader fileReader( mUrl );
+ FILE *fp = fileReader.GetFile();
+ if( fp == NULL )
+ {
+ return false;
+ }
+
+ if( fseek( fp, 0, SEEK_END ) <= -1 )
+ {
+ return false;
+ }
+
+ mWebPData.size = ftell( fp );
+ if( ( ! fseek( fp, 0, SEEK_SET ) ) )
+ {
+ unsigned char *WebPDataBuffer;
+ WebPDataBuffer = reinterpret_cast<WebPByteType*>( malloc(sizeof( WebPByteType ) * mWebPData.size ) );
+ mWebPData.size = fread( WebPDataBuffer, sizeof( WebPByteType ), mWebPData.size, fp );
+ mWebPData.bytes = WebPDataBuffer;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // remote file
+ bool succeeded;
+ Dali::Vector<uint8_t> dataBuffer;
+ size_t dataSize;
+
+ succeeded = TizenPlatform::Network::DownloadRemoteFileIntoMemory( mUrl, dataBuffer, dataSize, MAXIMUM_DOWNLOAD_IMAGE_SIZE );
+ if( succeeded )
+ {
+ size_t blobSize = dataBuffer.Size();
+ if( blobSize > 0U )
+ {
+ // Open a file handle on the memory buffer:
+ Dali::Internal::Platform::FileReader fileReader( dataBuffer, blobSize );
+ FILE * const fp = fileReader.GetFile();
+ if ( NULL != fp )
+ {
+ if( ( ! fseek( fp, 0, SEEK_SET ) ) )
+ {
+ unsigned char *WebPDataBuffer;
+ WebPDataBuffer = reinterpret_cast<WebPByteType*>( malloc(sizeof( WebPByteType ) * blobSize ) );
+ mWebPData.size = fread( WebPDataBuffer, sizeof( WebPByteType ), mWebPData.size, fp );
+ mWebPData.bytes = WebPDataBuffer;
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Error seeking within file\n" );
+ }
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Error reading file\n" );
+ }
+ }
+ }
+ }
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ // Moveable but not copyable
+
+ Impl( const Impl& ) = delete;
+ Impl& operator=( const Impl& ) = delete;
+ Impl( Impl&& ) = default;
+ Impl& operator=( Impl&& ) = default;
+
+ ~Impl()
+ {
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ if( &mWebPData != NULL )
+ {
+ free( (void*)mWebPData.bytes );
+ mWebPData.bytes = nullptr;
+ WebPDataInit( &mWebPData );
+ }
+ if( mWebPAnimDecoder )
+ {
+ WebPAnimDecoderDelete(mWebPAnimDecoder);
+ }
+#endif
+ }
+
+ std::string mUrl;
+ std::vector<uint32_t> mTimeStamp;
+ uint32_t mLoadingFrame;
+
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ WebPData mWebPData;
+ WebPAnimDecoder* mWebPAnimDecoder;
+ WebPAnimInfo mWebPAnimInfo;
+#endif
+};
+
+AnimatedImageLoadingPtr WebPLoading::New( const std::string &url, bool isLocalResource )
+{
+#if WEBP_DEMUX_ABI_VERSION <= 0x0101
+ DALI_LOG_ERROR( "The system do not support Animated WebP format.\n" );
+#endif
+ return AnimatedImageLoadingPtr( new WebPLoading( url, isLocalResource ) );
+}
+
+WebPLoading::WebPLoading( const std::string &url, bool isLocalResource )
+: mImpl( new WebPLoading::Impl( url, isLocalResource ) )
+{
+}
+
+WebPLoading::~WebPLoading()
+{
+ delete mImpl;
+}
+
+bool WebPLoading::LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData> &pixelData )
+{
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ if( frameStartIndex >= mImpl->mWebPAnimInfo.frame_count )
+ {
+ return false;
+ }
+
+ DALI_LOG_INFO( gWebPLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count );
+
+ if( mImpl->mLoadingFrame > frameStartIndex )
+ {
+ mImpl->mLoadingFrame = 0;
+ WebPAnimDecoderReset( mImpl->mWebPAnimDecoder );
+ }
+
+ for( ; mImpl->mLoadingFrame < frameStartIndex ; ++mImpl->mLoadingFrame )
+ {
+ uint8_t* frameBuffer;
+ int timestamp;
+ WebPAnimDecoderGetNext( mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp );
+ mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp;
+ }
+
+ for( int i = 0; i < count; ++i )
+ {
+ const int bufferSize = mImpl->mWebPAnimInfo.canvas_width * mImpl->mWebPAnimInfo.canvas_height * sizeof( uint32_t );
+ uint8_t* frameBuffer;
+ int timestamp;
+ WebPAnimDecoderGetNext( mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp );
+
+ auto pixelBuffer = new uint8_t[ bufferSize ];
+ memcpy( pixelBuffer, frameBuffer, bufferSize );
+ mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp;
+
+ if( pixelBuffer )
+ {
+ pixelData.push_back( Dali::PixelData::New( pixelBuffer, bufferSize,
+ mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height,
+ Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY) );
+ }
+
+ mImpl->mLoadingFrame++;
+ if( mImpl->mLoadingFrame >= mImpl->mWebPAnimInfo.frame_count )
+ {
+ mImpl->mLoadingFrame = 0;
+ WebPAnimDecoderReset( mImpl->mWebPAnimDecoder );
+ }
+ }
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+ImageDimensions WebPLoading::GetImageSize() const
+{
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ return ImageDimensions( mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height );
+#else
+ return ImageDimensions();
+#endif
+}
+
+uint32_t WebPLoading::GetImageCount() const
+{
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+ return mImpl->mWebPAnimInfo.frame_count;
+#else
+ return 0u;
+#endif
+}
+
+uint32_t WebPLoading::GetFrameInterval( uint32_t frameIndex ) const
+{
+ if( frameIndex >= GetImageCount() )
+ {
+ return 0u;
+ }
+ else
+ {
+ if( frameIndex > 0 )
+ {
+ return mImpl->mTimeStamp[frameIndex] - mImpl->mTimeStamp[frameIndex - 1];
+ }
+ return mImpl->mTimeStamp[frameIndex];
+ }
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
\ No newline at end of file
--- /dev/null
+#ifndef DALI_INTERNAL_WEBP_LOADING_H
+#define DALI_INTERNAL_WEBP_LOADING_H
+
+/*
+ * Copyright (c) 2020 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 <cstdint>
+#include <memory>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/uint-16-pair.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-adaptor-common.h>
+#include <dali/internal/imaging/common/animated-image-loading-impl.h>
+
+namespace Dali
+{
+class PixelData;
+typedef Dali::Uint16Pair ImageDimensions;
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * Class to manage loading frames of an animated webp in small chunks. Lazy initializes only when
+ * data is actually needed.
+ * Note, once the WEBP has loaded, the undecoded data will reside in memory until this object
+ * is released. (This is to speed up frame loads, which would otherwise have to re-acquire the
+ * data from disk)
+ */
+class WebPLoading: public Internal::Adaptor::AnimatedImageLoading
+{
+public:
+
+ /**
+ * Create a WebPLoading with the given url and resourceType.
+ * @param[in] url The url of the webp image to load
+ * @param[in] isLocalResource The true or false whether this is a local resource.
+ * @return A newly created WebPLoading.
+ */
+ static AnimatedImageLoadingPtr New( const std::string& url, bool isLocalResource );
+
+ /**
+ * @brief Constructor
+ *
+ * Construct a Loader with the given URL
+ * @param[in] url The url of the webp image to load
+ * @param[in] isLocalResource The true or false whether this is a local resource.
+ */
+ WebPLoading( const std::string& url, bool isLocalResource );
+
+
+ /**
+ * @brief Destructor
+ */
+ ~WebPLoading() override;
+
+ /**
+ * @brief Load the next N Frames of the webp.
+ *
+ * @note This function will load the entire webp into memory if not already loaded.
+ * @param[in] frameStartIndex The frame counter to start from. Will usually be the next frame
+ * after the previous invocation of this method, or 0 to start.
+ * @param[in] count The number of frames to load
+ * @param[out] pixelData The vector in which to return the frame data
+ * @return True if the frame data was successfully loaded
+ */
+ bool LoadNextNFrames( uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData ) override;
+
+ /**
+ * @brief Get the size of a webp image.
+ *
+ * @return The width and height in pixels of the webp image.
+ */
+ ImageDimensions GetImageSize() const override;
+
+ /**
+ * @brief Get the number of frames in this webp.
+ */
+ uint32_t GetImageCount() const override;
+
+ /**
+ * @brief Get the frame interval of the frame index
+ *
+ * @note The frame is needed to be loaded before this function is called.
+ *
+ * @return The time interval of the frame(microsecond).
+ */
+ uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+private:
+ struct Impl;
+ Impl* mImpl;
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_WEBP_LOADING_H
${adaptor_imaging_dir}/common/loader-png.cpp
${adaptor_imaging_dir}/common/loader-wbmp.cpp
${adaptor_imaging_dir}/common/pixel-manipulation.cpp
+ ${adaptor_imaging_dir}/common/gif-loading.cpp
+ ${adaptor_imaging_dir}/common/webp-loading.cpp
)
# module: imaging, backend: tizen
BuildRequires: gawk
BuildRequires: cmake
BuildRequires: giflib-devel
+BuildRequires: pkgconfig(libwebp)
+BuildRequires: pkgconfig(libwebpdecoder)
+BuildRequires: pkgconfig(libwebpdemux)
+BuildRequires: pkgconfig(libwebpmux)
BuildRequires: pkgconfig(fontconfig)
BuildRequires: libjpeg-turbo-devel
BuildRequires: pkgconfig(vconf)