- Make webp file that has wrong file extension can be loaded as a single image with image-visual.
- Make webp file that hasn't animated option can be loaded with animated-image-visual without duplicated loading.
Change-Id: Idab5ed59d3bb06e87dd6028a39b41b8ea0986371
Signed-off-by: seungho <sbsh.baek@samsung.com>
#include <dali/internal/imaging/common/loader-astc.h>
#include <dali/internal/imaging/common/loader-bmp.h>
#include <dali/internal/imaging/common/loader-gif.h>
+#include <dali/internal/imaging/common/loader-webp.h>
#include <dali/internal/imaging/common/loader-ico.h>
#include <dali/internal/imaging/common/loader-jpeg.h>
#include <dali/internal/imaging/common/loader-ktx.h>
FORMAT_JPEG,
FORMAT_BMP,
FORMAT_GIF,
+ FORMAT_WEBP,
FORMAT_KTX,
FORMAT_ASTC,
FORMAT_ICO,
{Jpeg::MAGIC_BYTE_1, Jpeg::MAGIC_BYTE_2, LoadBitmapFromJpeg, LoadJpegHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{Bmp::MAGIC_BYTE_1, Bmp::MAGIC_BYTE_2, LoadBitmapFromBmp, LoadBmpHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{Gif::MAGIC_BYTE_1, Gif::MAGIC_BYTE_2, LoadBitmapFromGif, LoadGifHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
+ {Webp::MAGIC_BYTE_1, Webp::MAGIC_BYTE_2, LoadBitmapFromWebp, LoadWebpHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{Ktx::MAGIC_BYTE_1, Ktx::MAGIC_BYTE_2, LoadBitmapFromKtx, LoadKtxHeader, Bitmap::BITMAP_COMPRESSED },
{Astc::MAGIC_BYTE_1, Astc::MAGIC_BYTE_2, LoadBitmapFromAstc, LoadAstcHeader, Bitmap::BITMAP_COMPRESSED },
{Ico::MAGIC_BYTE_1, Ico::MAGIC_BYTE_2, LoadBitmapFromIco, LoadIcoHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{".jpg", FORMAT_JPEG},
{".bmp", FORMAT_BMP },
{".gif", FORMAT_GIF },
+ {".webp", FORMAT_WEBP },
{".ktx", FORMAT_KTX },
{".astc", FORMAT_ASTC},
{".ico", FORMAT_ICO },
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/imaging/common/loader-webp.h>
+
+// EXTERNAL INCLUDES
+#ifdef DALI_WEBP_AVAILABLE
+#include <webp/decode.h>
+#include <webp/demux.h>
+
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+#define DALI_ANIMATED_WEBP_ENABLED 1
+#endif
+#endif
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/integration-api/debug.h>
+#include <cstring>
+#include <memory>
+
+typedef unsigned char WebPByteType;
+
+namespace Dali
+{
+namespace TizenPlatform
+{
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+bool ReadWebPInformation(FILE* const fp, WebPData& webPData)
+{
+ if(fp == NULL)
+ {
+ return false;
+ }
+
+ if(fseek(fp, 0, SEEK_END) <= -1)
+ {
+ return false;
+ }
+ WebPDataInit(&webPData);
+ webPData.size = ftell(fp);
+
+ if((!fseek(fp, 0, SEEK_SET)))
+ {
+ unsigned char* WebPDataBuffer;
+ WebPDataBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * webPData.size));
+ webPData.size = fread(WebPDataBuffer, sizeof(WebPByteType), webPData.size, fp);
+ webPData.bytes = WebPDataBuffer;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+void ReleaseResource(WebPData& webPData, WebPAnimDecoder* webPAnimDecoder)
+{
+ free((void*)webPData.bytes);
+ webPData.bytes = nullptr;
+ WebPDataInit(&webPData);
+ if(webPAnimDecoder)
+ {
+ WebPAnimDecoderDelete(webPAnimDecoder);
+ }
+}
+
+#endif
+
+bool LoadWebpHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height)
+{
+ FILE* const fp = input.file;
+ if(fp == NULL)
+ {
+ return false;
+ }
+
+ if(fseek(fp, 0, SEEK_END) <= -1)
+ {
+ return false;
+ }
+
+ // If the image is non-animated webp
+#ifdef DALI_WEBP_AVAILABLE
+ size_t webPSize = ftell(fp);
+ if((!fseek(fp, 0, SEEK_SET)))
+ {
+ std::vector<uint8_t> encodedImage;
+ encodedImage.resize(webPSize, 0);
+ size_t readCount = fread(&encodedImage[0], sizeof(uint8_t), encodedImage.size(), fp);
+ if(readCount != encodedImage.size())
+ {
+ return false;
+ }
+ int32_t imageWidth, imageHeight;
+ if(WebPGetInfo(&encodedImage[0], encodedImage.size(), &imageWidth, &imageHeight))
+ {
+ width = static_cast<uint32_t>(imageWidth);
+ height = static_cast<uint32_t>(imageHeight);
+ return true;
+ }
+ }
+#endif
+
+ // If the image is animated webp
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+ WebPData webPData;
+ WebPAnimDecoder* webPAnimDecoder;
+ WebPAnimInfo webPAnimInfo;
+ if(ReadWebPInformation(fp, webPData))
+ {
+ WebPAnimDecoderOptions webPAnimDecoderOptions;
+ WebPAnimDecoderOptionsInit(&webPAnimDecoderOptions);
+ webPAnimDecoderOptions.color_mode = MODE_RGBA;
+ webPAnimDecoder = WebPAnimDecoderNew(&webPData, &webPAnimDecoderOptions);
+ if(webPAnimDecoder != nullptr)
+ {
+ WebPAnimDecoderGetInfo(webPAnimDecoder, &webPAnimInfo);
+ width = webPAnimInfo.canvas_width;
+ height = webPAnimInfo.canvas_height;
+ return true;
+ }
+ }
+ ReleaseResource(webPData, webPAnimDecoder);
+#endif
+ DALI_LOG_ERROR("WebP file open failed.\n");
+ return false;
+}
+
+bool LoadBitmapFromWebp(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap)
+{
+ FILE* const fp = input.file;
+ if(fp == NULL)
+ {
+ return false;
+ }
+
+ if(fseek(fp, 0, SEEK_END) <= -1)
+ {
+ return false;
+ }
+
+ // If the image is non-animated webp
+#ifdef DALI_WEBP_AVAILABLE
+ size_t webPSize = ftell(fp);
+ if((!fseek(fp, 0, SEEK_SET)))
+ {
+ std::vector<uint8_t> encodedImage;
+ encodedImage.resize(webPSize, 0);
+ size_t readCount = fread(&encodedImage[0], sizeof(uint8_t), encodedImage.size(), fp);
+ if(readCount != encodedImage.size())
+ {
+ DALI_LOG_ERROR("WebP image loading failed.\n");
+ return false;
+ }
+
+ int32_t width, height;
+ if(!WebPGetInfo(&encodedImage[0], encodedImage.size(), &width, &height))
+ {
+ DALI_LOG_ERROR("Cannot retrieve WebP image size information.\n");
+ return false;
+ }
+
+ WebPBitstreamFeatures features;
+ if(VP8_STATUS_NOT_ENOUGH_DATA == WebPGetFeatures(&encodedImage[0], encodedImage.size(), &features))
+ {
+ DALI_LOG_ERROR("Cannot retrieve WebP image features.\n");
+ return false;
+ }
+
+ uint32_t channelNumber = (features.has_alpha) ? 4 : 3;
+ Pixel::Format pixelFormat = (channelNumber == 4) ? Pixel::RGBA8888 : Pixel::RGB888;
+ bitmap = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
+ uint8_t* frameBuffer = nullptr;
+ if(channelNumber == 4)
+ {
+ frameBuffer = WebPDecodeRGBA(&encodedImage[0], encodedImage.size(), &width, &height);
+ }
+ else
+ {
+ frameBuffer = WebPDecodeRGB(&encodedImage[0], encodedImage.size(), &width, &height);
+ }
+
+ if(frameBuffer != nullptr)
+ {
+ const int32_t bufferSize = width * height * sizeof(uint8_t) * channelNumber;
+ memcpy(bitmap.GetBuffer(), frameBuffer, bufferSize);
+ free((void*)frameBuffer);
+ return true;
+ }
+ }
+#endif
+
+ // If the image is animated webp
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+ WebPData webPData;
+ WebPAnimDecoder* webPAnimDecoder;
+ WebPAnimInfo webPAnimInfo;
+ if(ReadWebPInformation(fp, webPData))
+ {
+ WebPAnimDecoderOptions webPAnimDecoderOptions;
+ WebPAnimDecoderOptionsInit(&webPAnimDecoderOptions);
+ webPAnimDecoderOptions.color_mode = MODE_RGBA;
+ webPAnimDecoder = WebPAnimDecoderNew(&webPData, &webPAnimDecoderOptions);
+ if(webPAnimDecoder != nullptr)
+ {
+ uint8_t* frameBuffer;
+ int timestamp;
+ WebPAnimDecoderGetInfo(webPAnimDecoder, &webPAnimInfo);
+ WebPAnimDecoderReset(webPAnimDecoder);
+ WebPAnimDecoderGetNext(webPAnimDecoder, &frameBuffer, ×tamp);
+
+ bitmap = Dali::Devel::PixelBuffer::New(webPAnimInfo.canvas_width, webPAnimInfo.canvas_height, Dali::Pixel::RGBA8888);
+ const int32_t bufferSize = webPAnimInfo.canvas_width * webPAnimInfo.canvas_height * sizeof(uint32_t);
+ memcpy(bitmap.GetBuffer(), frameBuffer, bufferSize);
+ return true;
+ }
+ }
+ ReleaseResource(webPData, webPAnimDecoder);
+#endif
+
+ DALI_LOG_ERROR("WebP image loading failed.\n");
+ return false;
+}
+
+} // namespace TizenPlatform
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TIZEN_PLATFORM_LOADER_WEBP_H
+#define DALI_TIZEN_PLATFORM_LOADER_WEBP_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/devel-api/adaptor-framework/image-loader-input.h>
+#include <cstdio>
+
+namespace Dali
+{
+namespace Devel
+{
+class PixelBuffer;
+}
+
+namespace TizenPlatform
+{
+class ResourceLoadingClient;
+
+namespace Webp
+{
+const unsigned char MAGIC_BYTE_1 = 0x52;
+const unsigned char MAGIC_BYTE_2 = 0x49;
+} // namespace Webp
+
+/**
+ * Loads the header of a Webp file and fills in the width and height appropriately.
+ * @param[in] input Information about the input image (including file pointer)
+ * @param[out] width Is set with the width of the image
+ * @param[out] height Is set with the height of the image
+ * @return true if the file's header was read successully, false otherwise
+ */
+bool LoadWebpHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height);
+
+/**
+ * Loads the bitmap from a Webp file. This function checks the header first
+ * and if it is not a Webp file, then it returns straight away.
+ * @note For animated Webps, only the first image is displayed
+ * @param[in] input Information about the input image (including file pointer)
+ * @param[out] bitmap The bitmap class where the decoded image will be stored
+ * @return true if file decoded successfully, false otherwise
+ */
+bool LoadBitmapFromWebp(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap);
+
+} // namespace TizenPlatform
+
+} // namespace Dali
+
+#endif // DALI_TIZEN_PLATFORM_LOADER_WEBP_H
#include <webp/demux.h>
#if WEBP_DEMUX_ABI_VERSION > 0x0101
-#define DALI_WEBP_ENABLED 1
+#define DALI_ANIMATED_WEBP_ENABLED 1
#endif
#endif
#include <unistd.h>
#include <cstring>
+// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+
typedef unsigned char WebPByteType;
namespace Dali
public:
Impl(const std::string& url, bool isLocalResource)
: mUrl(url),
- mLoadSucceeded(true),
- mMutex()
+ mFrameCount(1u),
+ mMutex(),
+ mBuffer(nullptr),
+ mBufferSize(0u),
+ mImageSize(),
+ mLoadSucceeded(true)
{
-#ifdef DALI_WEBP_ENABLED
+ // mFrameCount will be 1 if the input image is non-animated image or animated image with single frame.
if(ReadWebPInformation(isLocalResource))
{
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+ WebPDataInit(&mWebPData);
+ mWebPData.size = mBufferSize;
+ mWebPData.bytes = mBuffer;
WebPAnimDecoderOptions webPAnimDecoderOptions;
WebPAnimDecoderOptionsInit(&webPAnimDecoderOptions);
webPAnimDecoderOptions.color_mode = MODE_RGBA;
mWebPAnimDecoder = WebPAnimDecoderNew(&mWebPData, &webPAnimDecoderOptions);
WebPAnimDecoderGetInfo(mWebPAnimDecoder, &mWebPAnimInfo);
mTimeStamp.assign(mWebPAnimInfo.frame_count, 0);
+ mFrameCount = mWebPAnimInfo.frame_count;
+ mImageSize = ImageDimensions(mWebPAnimInfo.canvas_width, mWebPAnimInfo.canvas_height);
+#elif DALI_WEBP_AVAILABLE
+ int32_t imageWidth, imageHeight;
+ if(WebPGetInfo(mBuffer, mBufferSize, &imageWidth, &imageHeight))
+ {
+ mImageSize = ImageDimensions(imageWidth, imageHeight);
+ }
+#endif
+#ifndef DALI_WEBP_AVAILABLE
+ // If the system doesn't support webp, loading will be failed.
+ mFrameCount = 0u;
+ mLoadSucceeded = false;
+#endif
}
else
{
+ mFrameCount = 0u;
mLoadSucceeded = false;
+ DALI_LOG_ERROR("Image loading failed for: \"%s\".\n", mUrl.c_str());
}
-#endif
}
bool ReadWebPInformation(bool isLocalResource)
{
-#ifdef DALI_WEBP_ENABLED
- WebPDataInit(&mWebPData);
+ FILE* fp = nullptr;
if(isLocalResource)
{
Internal::Platform::FileReader fileReader(mUrl);
- FILE* fp = fileReader.GetFile();
+ fp = fileReader.GetFile();
if(fp == NULL)
{
return false;
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
+ mBufferSize = ftell(fp);
+ if(!fseek(fp, 0, SEEK_SET))
{
- return false;
+ mBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * mBufferSize));
+ mBufferSize = fread(mBuffer, sizeof(WebPByteType), mBufferSize, fp);
+ return true;
}
}
else
succeeded = TizenPlatform::Network::DownloadRemoteFileIntoMemory(mUrl, dataBuffer, dataSize, MAXIMUM_DOWNLOAD_IMAGE_SIZE);
if(succeeded)
{
- size_t blobSize = dataBuffer.Size();
- if(blobSize > 0U)
+ mBufferSize = dataBuffer.Size();
+ if(mBufferSize > 0U)
{
// Open a file handle on the memory buffer:
- Dali::Internal::Platform::FileReader fileReader(dataBuffer, blobSize);
- FILE* const fp = fileReader.GetFile();
- if(NULL != fp)
+ Internal::Platform::FileReader fileReader(dataBuffer, mBufferSize);
+ fp = fileReader.GetFile();
+ if(fp != nullptr)
{
- if((!fseek(fp, 0, SEEK_SET)))
+ 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;
+ mBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * mBufferSize));
+ mBufferSize = fread(mBuffer, sizeof(WebPByteType), mBufferSize, fp);
+ return true;
}
- 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()
{
-#ifdef DALI_WEBP_ENABLED
+#ifdef DALI_ANIMATED_WEBP_ENABLED
if(&mWebPData != NULL)
{
- free((void*)mWebPData.bytes);
mWebPData.bytes = nullptr;
WebPDataInit(&mWebPData);
}
WebPAnimDecoderDelete(mWebPAnimDecoder);
}
#endif
+ free((void*)mBuffer);
+ mBuffer = nullptr;
}
std::string mUrl;
std::vector<uint32_t> mTimeStamp;
uint32_t mLoadingFrame{0};
- bool mLoadSucceeded;
+ uint32_t mFrameCount;
Mutex mMutex;
+ // For the case the system doesn't support DALI_ANIMATED_WEBP_ENABLED
+ unsigned char* mBuffer;
+ uint32_t mBufferSize;
+ ImageDimensions mImageSize;
+ bool mLoadSucceeded;
-#ifdef DALI_WEBP_ENABLED
+#ifdef DALI_ANIMATED_WEBP_ENABLED
WebPData mWebPData{0};
WebPAnimDecoder* mWebPAnimDecoder{nullptr};
WebPAnimInfo mWebPAnimInfo{0};
AnimatedImageLoadingPtr WebPLoading::New(const std::string& url, bool isLocalResource)
{
-#ifndef DALI_WEBP_ENABLED
+#ifndef DALI_ANIMATED_WEBP_ENABLED
DALI_LOG_ERROR("The system does not support Animated WebP format.\n");
#endif
return AnimatedImageLoadingPtr(new WebPLoading(url, isLocalResource));
bool WebPLoading::LoadNextNFrames(uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData)
{
-#ifdef DALI_WEBP_ENABLED
- Mutex::ScopedLock lock(mImpl->mMutex);
- if(frameStartIndex >= mImpl->mWebPAnimInfo.frame_count || !mImpl->mLoadSucceeded)
+ for(int i = 0; i < count; ++i)
{
- return false;
+ Dali::Devel::PixelBuffer pixelBuffer = LoadFrame((frameStartIndex + i) % mImpl->mFrameCount);
+ Dali::PixelData imageData = Devel::PixelBuffer::Convert(pixelBuffer);
+ pixelData.push_back(imageData);
}
-
- DALI_LOG_INFO(gWebPLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count);
-
- if(mImpl->mLoadingFrame > frameStartIndex)
+ if(pixelData.size() != static_cast<uint32_t>(count))
{
- mImpl->mLoadingFrame = 0;
- WebPAnimDecoderReset(mImpl->mWebPAnimDecoder);
+ return false;
}
+ return true;
+}
- for(; mImpl->mLoadingFrame < frameStartIndex; ++mImpl->mLoadingFrame)
- {
- uint8_t* frameBuffer;
- int timestamp;
- WebPAnimDecoderGetNext(mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp);
- mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp;
- }
+Dali::Devel::PixelBuffer WebPLoading::LoadFrame(uint32_t frameIndex)
+{
+ Dali::Devel::PixelBuffer pixelBuffer;
- for(int i = 0; i < count; ++i)
+ // WebPDecodeRGBA is faster than to use demux API for loading non-animated image.
+ // If frame count is 1, use WebPDecodeRGBA api.
+#ifdef DALI_WEBP_AVAILABLE
+ if(mImpl->mFrameCount == 1)
{
- const int bufferSize = mImpl->mWebPAnimInfo.canvas_width * mImpl->mWebPAnimInfo.canvas_height * sizeof(uint32_t);
- uint8_t* frameBuffer;
- int timestamp;
- WebPAnimDecoderGetNext(mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp);
+ int32_t width, height;
+ if(!WebPGetInfo(mImpl->mBuffer, mImpl->mBufferSize, &width, &height))
+ {
+ return pixelBuffer;
+ }
- auto pixelBuffer = new uint8_t[bufferSize];
- memcpy(pixelBuffer, frameBuffer, bufferSize);
- mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp;
+ WebPBitstreamFeatures features;
+ if(VP8_STATUS_NOT_ENOUGH_DATA == WebPGetFeatures(mImpl->mBuffer, mImpl->mBufferSize, &features))
+ {
+ return pixelBuffer;
+ }
- if(pixelBuffer)
+ uint32_t channelNumber = (features.has_alpha) ? 4 : 3;
+ Pixel::Format pixelFormat = (channelNumber == 4) ? Pixel::RGBA8888 : Pixel::RGB888;
+ pixelBuffer = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
+ uint8_t* frameBuffer = nullptr;
+ if(channelNumber == 4)
+ {
+ frameBuffer = WebPDecodeRGBA(mImpl->mBuffer, mImpl->mBufferSize, &width, &height);
+ }
+ else
{
- pixelData.push_back(Dali::PixelData::New(pixelBuffer, bufferSize, mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height, Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY));
+ frameBuffer = WebPDecodeRGB(mImpl->mBuffer, mImpl->mBufferSize, &width, &height);
}
- mImpl->mLoadingFrame++;
- if(mImpl->mLoadingFrame >= mImpl->mWebPAnimInfo.frame_count)
+ if(frameBuffer != nullptr)
{
- mImpl->mLoadingFrame = 0;
- WebPAnimDecoderReset(mImpl->mWebPAnimDecoder);
+ const int32_t imageBufferSize = width * height * sizeof(uint8_t) * channelNumber;
+ memcpy(pixelBuffer.GetBuffer(), frameBuffer, imageBufferSize);
+ free((void*)frameBuffer);
+ return pixelBuffer;
}
}
-
- return true;
-#else
- return false;
#endif
-}
-Dali::Devel::PixelBuffer WebPLoading::LoadFrame(uint32_t frameIndex)
-{
- Dali::Devel::PixelBuffer pixelBuffer;
-
-#ifdef DALI_WEBP_ENABLED
+#ifdef DALI_ANIMATED_WEBP_ENABLED
Mutex::ScopedLock lock(mImpl->mMutex);
if(frameIndex >= mImpl->mWebPAnimInfo.frame_count || !mImpl->mLoadSucceeded)
{
ImageDimensions WebPLoading::GetImageSize() const
{
-#ifdef DALI_WEBP_ENABLED
- return ImageDimensions(mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height);
-#else
- return ImageDimensions();
-#endif
+ return mImpl->mImageSize;
}
uint32_t WebPLoading::GetImageCount() const
{
-#ifdef DALI_WEBP_ENABLED
- return mImpl->mWebPAnimInfo.frame_count;
-#else
- return 0u;
-#endif
+ return mImpl->mFrameCount;
}
uint32_t WebPLoading::GetFrameInterval(uint32_t frameIndex) const
${adaptor_imaging_dir}/common/loader-ktx.cpp
${adaptor_imaging_dir}/common/loader-png.cpp
${adaptor_imaging_dir}/common/loader-wbmp.cpp
+ ${adaptor_imaging_dir}/common/loader-webp.cpp
${adaptor_imaging_dir}/common/pixel-manipulation.cpp
${adaptor_imaging_dir}/common/gif-loading.cpp
${adaptor_imaging_dir}/common/webp-loading.cpp