Support WebP format 24/237124/1
authorSeungho, Baek <sbsh.baek@samsung.com>
Wed, 10 Jun 2020 07:04:07 +0000 (16:04 +0900)
committerSeungho, Baek <sbsh.baek@samsung.com>
Thu, 25 Jun 2020 05:13:00 +0000 (14:13 +0900)
 - 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>
12 files changed:
automated-tests/src/dali-adaptor/utc-Dali-GifLoading.cpp
build/tizen/CMakeLists.txt
dali/devel-api/adaptor-framework/animated-image-loading.cpp [new file with mode: 0644]
dali/devel-api/adaptor-framework/animated-image-loading.h [new file with mode: 0644]
dali/devel-api/file.list
dali/internal/imaging/common/animated-image-loading-impl.h [new file with mode: 0644]
dali/internal/imaging/common/gif-loading.cpp [moved from dali/devel-api/adaptor-framework/gif-loading.cpp with 97% similarity, mode: 0644]
dali/internal/imaging/common/gif-loading.h [moved from dali/devel-api/adaptor-framework/gif-loading.h with 62% similarity, mode: 0644]
dali/internal/imaging/common/webp-loading.cpp [new file with mode: 0644]
dali/internal/imaging/common/webp-loading.h [new file with mode: 0644]
dali/internal/imaging/file.list
packaging/dali-adaptor.spec

index 6a4fa87..b87ce8e 100755 (executable)
@@ -18,7 +18,7 @@
 #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;
 
@@ -50,38 +50,57 @@ void VerifyLoad( std::vector<Dali::PixelData>& pixelDataList, Dali::Vector<uint3
 }
 }
 
-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 );
@@ -90,28 +109,27 @@ int UtcDaliGifLoadingP(void)
   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 );
@@ -120,12 +138,12 @@ int UtcDaliGifLoadingGetImageSizeP(void)
   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 );
 
index 7c56a82..a83d807 100644 (file)
@@ -176,11 +176,13 @@ IF( UNIX )
   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}
diff --git a/dali/devel-api/adaptor-framework/animated-image-loading.cpp b/dali/devel-api/adaptor-framework/animated-image-loading.cpp
new file mode 100644 (file)
index 0000000..f2a9afa
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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
diff --git a/dali/devel-api/adaptor-framework/animated-image-loading.h b/dali/devel-api/adaptor-framework/animated-image-loading.h
new file mode 100644 (file)
index 0000000..7c0a69b
--- /dev/null
@@ -0,0 +1,150 @@
+#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
index b7e8f1f..789939d 100755 (executable)
@@ -2,6 +2,7 @@
 
 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
@@ -14,7 +15,6 @@ SET( devel_api_src_files
   ${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
@@ -42,6 +42,7 @@ SET( devel_api_adaptor_framework_header_files
   ${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
@@ -59,7 +60,6 @@ SET( devel_api_adaptor_framework_header_files
   ${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
diff --git a/dali/internal/imaging/common/animated-image-loading-impl.h b/dali/internal/imaging/common/animated-image-loading-impl.h
new file mode 100644 (file)
index 0000000..759eb09
--- /dev/null
@@ -0,0 +1,118 @@
+#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
old mode 100755 (executable)
new mode 100644 (file)
similarity index 97%
rename from dali/devel-api/adaptor-framework/gif-loading.cpp
rename to dali/internal/imaging/common/gif-loading.cpp
index e49fbc8..187d91c
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -18,7 +18,7 @@
  */
 
 // 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)
@@ -1232,9 +1238,9 @@ public:
   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 )
@@ -1248,7 +1254,7 @@ GifLoading::~GifLoading()
   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;
@@ -1278,36 +1284,23 @@ bool GifLoading::LoadNextNFrames( int frameStartIndex, int count, std::vector<Da
   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
old mode 100755 (executable)
new mode 100644 (file)
similarity index 62%
rename from dali/devel-api/adaptor-framework/gif-loading.h
rename to dali/internal/imaging/common/gif-loading.h
index 6143f15..4ee7565
@@ -2,7 +2,7 @@
 #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
@@ -40,7 +45,7 @@ typedef Dali::Uint16Pair ImageDimensions;
  * 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:
 
@@ -50,7 +55,7 @@ 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
@@ -61,17 +66,10 @@ public:
    */
   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.
@@ -83,50 +81,38 @@ public:
    * @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
diff --git a/dali/internal/imaging/common/webp-loading.cpp b/dali/internal/imaging/common/webp-loading.cpp
new file mode 100644 (file)
index 0000000..78e2e11
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * 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, &timestamp );
+    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, &timestamp );
+
+    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
diff --git a/dali/internal/imaging/common/webp-loading.h b/dali/internal/imaging/common/webp-loading.h
new file mode 100644 (file)
index 0000000..01bd4e3
--- /dev/null
@@ -0,0 +1,121 @@
+#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
index 6558e96..c91ffcf 100644 (file)
@@ -18,6 +18,8 @@ SET( adaptor_imaging_common_src_files
     ${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
index 0e7a469..6d7bafc 100644 (file)
@@ -56,6 +56,10 @@ BuildRequires:  pkgconfig
 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)