[Tizen] Fix a gif crash
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / gif-loading.cpp
index 098b1a5..88b8e1e 100644 (file)
@@ -61,7 +61,7 @@ Debug::Filter* gGifLoadingLogFilter = Debug::Filter::New(Debug::NoLogging, false
 const int        IMG_MAX_SIZE                = 65000;
 constexpr size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE = 50 * 1024 * 1024;
 
-constexpr int LOCAL_CACHED_COLOR_GENERATE_THRESHOLD = 16; ///< Generate color map optimize only if colorCount * threshold < width * height, So we don't loop if image is small
+constexpr int LOCAL_CACHED_COLOR_GENERATE_THRESHOLD = 64; ///< Generate color map optimize only if colorCount * threshold < width * height, So we don't loop if image is small
 
 #if GIFLIB_MAJOR < 5
 const int DISPOSE_BACKGROUND = 2; /* Set area too background color */
@@ -140,7 +140,6 @@ struct GifCachedColorData
   // precalculated colormap table
   std::vector<std::uint32_t> globalCachedColor{};
   std::vector<std::uint32_t> localCachedColor{};
-  ColorMapObject*            localCachedColorMap{nullptr}; // Weak-pointer of ColorMapObject. should be nullptr if image changed
 };
 
 // Forward declaration
@@ -717,20 +716,14 @@ bool DecodeImage(GifFileType* gif, GifCachedColorData& gifCachedColor, uint32_t*
   if(gif->Image.ColorMap)
   {
     colorMap = gif->Image.ColorMap;
-    // use local cached color map without re-calculate cache.
-    if(gifCachedColor.localCachedColorMap == colorMap)
-    {
-      cachedColorPtr = gifCachedColor.localCachedColor.data();
-    }
-    // else if w * h is big enough, generate local cached color.
-    else if(colorMap->ColorCount * LOCAL_CACHED_COLOR_GENERATE_THRESHOLD < w * h)
+    // if w * h is big enough, generate local cached color.
+    if(colorMap->ColorCount * LOCAL_CACHED_COLOR_GENERATE_THRESHOLD < w * h)
     {
       gifCachedColor.localCachedColor.resize(colorMap->ColorCount);
       for(i = 0; i < colorMap->ColorCount; ++i)
       {
         gifCachedColor.localCachedColor[i] = PixelLookup(colorMap, i);
       }
-      gifCachedColor.localCachedColorMap = colorMap;
 
       cachedColorPtr = gifCachedColor.localCachedColor.data();
     }
@@ -878,12 +871,10 @@ on_error:
  *
  * @param[in] loaderInfo A LoaderInfo structure containing file descriptor and other data about GIF.
  * @param[out] prop A ImageProperties structure for storing information about GIF data.
- * @param[out] error Error code
  * @return The true or false whether reading was successful or not.
  */
 bool ReadHeader(LoaderInfo&      loaderInfo,
-                ImageProperties& prop, //output struct
-                int*             error)
+                ImageProperties& prop)
 {
   GifAnimationData&     animated    = loaderInfo.animated;
   GifCachedColorData&   cachedColor = loaderInfo.cachedColor;
@@ -1084,13 +1075,14 @@ bool ReadHeader(LoaderInfo&      loaderInfo,
               cachedColor.globalCachedColor[i] = PixelLookup(colorMap, i);
             }
           }
-          cachedColor.localCachedColorMap = nullptr;
-
-          // no errors in header scan etc. so set err and return value
-          *error = 0;
         }
       }
     }
+    else
+    {
+      success = false;
+      DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+    }
   }
   return success;
 }
@@ -1406,15 +1398,29 @@ struct GifLoading::Impl
 public:
   Impl(const std::string& url, bool isLocalResource)
   : mUrl(url),
-    mLoadSucceeded(true),
+    mLoadSucceeded(false),
     mMutex()
   {
-    loaderInfo.gifAccessor = nullptr;
-    int error;
+    loaderInfo.gifAccessor              = nullptr;
     loaderInfo.fileData.fileName        = mUrl.c_str();
     loaderInfo.fileData.isLocalResource = isLocalResource;
+  }
+
+  bool LoadGifInformation()
+  {
+    // Block to do not load this file again.
+    Mutex::ScopedLock lock(mMutex);
+    if(DALI_LIKELY(mLoadSucceeded))
+    {
+      return mLoadSucceeded;
+    }
 
-    mLoadSucceeded = ReadHeader(loaderInfo, imageProperties, &error);
+    mLoadSucceeded = ReadHeader(loaderInfo, imageProperties);
+    if(!mLoadSucceeded)
+    {
+      DALI_LOG_ERROR("ReadHeader is failed [%s]\n", mUrl.c_str());
+    }
+    return mLoadSucceeded;
   }
 
   // Moveable but not copyable
@@ -1445,52 +1451,20 @@ GifLoading::~GifLoading()
   delete mImpl;
 }
 
-bool GifLoading::LoadNextNFrames(uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData)
-{
-  int  error;
-  bool ret = false;
-
-  Mutex::ScopedLock lock(mImpl->mMutex);
-  if(DALI_UNLIKELY(!mImpl->mLoadSucceeded))
-  {
-    return false;
-  }
-
-  const int bufferSize = mImpl->imageProperties.w * mImpl->imageProperties.h * sizeof(uint32_t);
-
-  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count);
-
-  for(int i = 0; i < count; ++i)
-  {
-    auto pixelBuffer = new unsigned char[bufferSize];
-
-    mImpl->loaderInfo.animated.currentFrame = 1 + ((frameStartIndex + i) % mImpl->loaderInfo.animated.frameCount);
-
-    if(ReadNextFrame(mImpl->loaderInfo, mImpl->imageProperties, pixelBuffer, &error))
-    {
-      if(pixelBuffer)
-      {
-        pixelData.push_back(Dali::PixelData::New(pixelBuffer, bufferSize, mImpl->imageProperties.w, mImpl->imageProperties.h, Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY));
-        ret = true;
-      }
-    }
-  }
-
-  return ret;
-}
-
 Dali::Devel::PixelBuffer GifLoading::LoadFrame(uint32_t frameIndex)
 {
   int                      error;
   Dali::Devel::PixelBuffer pixelBuffer;
-  if(!mImpl->mLoadSucceeded)
+
+  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "LoadFrame( frameIndex:%d )\n", frameIndex);
+
+  // If Gif file is still not loaded, Load the information.
+  if(DALI_UNLIKELY(!mImpl->LoadGifInformation()))
   {
     return pixelBuffer;
   }
 
   Mutex::ScopedLock lock(mImpl->mMutex);
-  DALI_LOG_INFO(gGifLoadingLogFilter, Debug::Concise, "LoadFrame( frameIndex:%d )\n", frameIndex);
-
   pixelBuffer = Dali::Devel::PixelBuffer::New(mImpl->imageProperties.w, mImpl->imageProperties.h, Dali::Pixel::RGBA8888);
 
   mImpl->loaderInfo.animated.currentFrame = 1 + (frameIndex % mImpl->loaderInfo.animated.frameCount);
@@ -1505,17 +1479,35 @@ Dali::Devel::PixelBuffer GifLoading::LoadFrame(uint32_t frameIndex)
 
 ImageDimensions GifLoading::GetImageSize() const
 {
+  if(DALI_UNLIKELY(!mImpl->mLoadSucceeded))
+  {
+    mImpl->LoadGifInformation();
+  }
   return ImageDimensions(mImpl->imageProperties.w, mImpl->imageProperties.h);
 }
 
 uint32_t GifLoading::GetImageCount() const
 {
+  if(DALI_UNLIKELY(!mImpl->mLoadSucceeded))
+  {
+    mImpl->LoadGifInformation();
+  }
   return mImpl->loaderInfo.animated.frameCount;
 }
 
 uint32_t GifLoading::GetFrameInterval(uint32_t frameIndex) const
 {
-  return mImpl->loaderInfo.animated.frames[frameIndex].info.delay * 10;
+  if(DALI_UNLIKELY(!mImpl->mLoadSucceeded))
+  {
+    mImpl->LoadGifInformation();
+  }
+
+  uint32_t interval = 0u;
+  if(DALI_LIKELY(mImpl->mLoadSucceeded))
+  {
+    interval = mImpl->loaderInfo.animated.frames[frameIndex].info.delay * 10;
+  }
+  return interval;
 }
 
 std::string GifLoading::GetUrl() const