summaryrefslogtreecommitdiff
path: root/dali
diff options
context:
space:
mode:
authorAdeel Kazmi <adeel.kazmi@samsung.com>2023-10-10 16:03:25 +0100
committerAdeel Kazmi <adeel.kazmi@samsung.com>2023-10-10 16:03:25 +0100
commitefc7fc493b65bada3643ac00f9e297ff643054cd (patch)
treef1c7357d334d76d1253bfa34a2d610c0613eea10 /dali
parentb5dbfb710bdab25f43630ea90a966b7c663df2ce (diff)
downloaddali-adaptor-efc7fc493b65bada3643ac00f9e297ff643054cd.tar.gz
dali-adaptor-efc7fc493b65bada3643ac00f9e297ff643054cd.tar.bz2
dali-adaptor-efc7fc493b65bada3643ac00f9e297ff643054cd.zip
(gif-loading.cpp) Reduce CC of some functions
Change-Id: I9f3bb907fab9573114b3c1b68df6f1ab3a0ed528
Diffstat (limited to 'dali')
-rw-r--r--dali/internal/imaging/common/gif-loading.cpp959
1 files changed, 533 insertions, 426 deletions
diff --git a/dali/internal/imaging/common/gif-loading.cpp b/dali/internal/imaging/common/gif-loading.cpp
index 88b8e1e4f..bf9329322 100644
--- a/dali/internal/imaging/common/gif-loading.cpp
+++ b/dali/internal/imaging/common/gif-loading.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -641,6 +641,191 @@ FrameInfo* NewFrame(GifAnimationData& animated, int transparent, int dispose, in
return &(animated.frames.back().info);
}
+/// FILL (overwrite with transparency kept)
+void FillOverwriteWithTransparencyKept(
+ const std::uint32_t*& cachedColorPtr,
+ int& xx, int& yy,
+ const int x, const int y,
+ const int w, const int h,
+ const int xin, const int yin,
+ const int rowpix,
+ const int transparent,
+ const uint32_t fillColor,
+ int& pix,
+ uint32_t*& p,
+ uint32_t*& data,
+ GifRowType*& rows,
+ ColorMapObject*& colorMap)
+{
+ // if we use cachedColor, use it
+ if(cachedColorPtr)
+ {
+ for(yy = 0; yy < h; yy++)
+ {
+ p = data + ((y + yy) * rowpix) + x;
+ for(xx = 0; xx < w; xx++)
+ {
+ pix = rows[yin + yy][xin + xx];
+ if(pix != transparent)
+ {
+ *p = cachedColorPtr[pix];
+ }
+ else
+ {
+ *p = fillColor;
+ }
+ p++;
+ }
+ }
+ }
+ // we don't have cachedColor. use PixelLookup function.
+ else
+ {
+ for(yy = 0; yy < h; yy++)
+ {
+ p = data + ((y + yy) * rowpix) + x;
+ for(xx = 0; xx < w; xx++)
+ {
+ pix = rows[yin + yy][xin + xx];
+ if(pix != transparent)
+ {
+ *p = PixelLookup(colorMap, pix);
+ }
+ else
+ {
+ *p = fillColor;
+ }
+ p++;
+ }
+ }
+ }
+}
+
+/// Paste on top with transparent pixels untouched
+void PasteOnTopWithTransparentPixelsUntouched(
+ const std::uint32_t*& cachedColorPtr,
+ int& xx, int& yy,
+ const int x, const int y,
+ const int w, const int h,
+ const int xin, const int yin,
+ const int rowpix,
+ const int transparent,
+ const uint32_t fillColor,
+ int& pix,
+ uint32_t*& p,
+ uint32_t*& data,
+ GifRowType*& rows,
+ ColorMapObject*& colorMap)
+{
+ // if we use cachedColor, use it
+ if(cachedColorPtr)
+ {
+ for(yy = 0; yy < h; yy++)
+ {
+ p = data + ((y + yy) * rowpix) + x;
+ for(xx = 0; xx < w; xx++)
+ {
+ pix = rows[yin + yy][xin + xx];
+ if(pix != transparent)
+ {
+ *p = cachedColorPtr[pix];
+ }
+ p++;
+ }
+ }
+ }
+ // we don't have cachedColor. use PixelLookup function.
+ else
+ {
+ for(yy = 0; yy < h; yy++)
+ {
+ p = data + ((y + yy) * rowpix) + x;
+ for(xx = 0; xx < w; xx++)
+ {
+ pix = rows[yin + yy][xin + xx];
+ if(pix != transparent)
+ {
+ *p = PixelLookup(colorMap, pix);
+ }
+ p++;
+ }
+ }
+ }
+}
+
+void HandleTransparentPixels(
+ const bool fill,
+ const std::uint32_t*& cachedColorPtr,
+ int& xx, int& yy,
+ const int x, const int y,
+ const int w, const int h,
+ const int xin, const int yin,
+ const int rowpix,
+ const int transparent,
+ const uint32_t fillColor,
+ int& pix,
+ uint32_t*& p,
+ uint32_t*& data,
+ GifRowType*& rows,
+ ColorMapObject*& colorMap)
+{
+ if(fill)
+ {
+ FillOverwriteWithTransparencyKept(cachedColorPtr, xx, yy, x, y, w, h, xin, yin, rowpix, transparent, fillColor, pix, p, data, rows, colorMap);
+ }
+ else
+ {
+ PasteOnTopWithTransparentPixelsUntouched(cachedColorPtr, xx, yy, x, y, w, h, xin, yin, rowpix, transparent, fillColor, pix, p, data, rows, colorMap);
+ }
+}
+
+void HandleNonTransparentPixels(
+ const std::uint32_t*& cachedColorPtr,
+ int& xx, int& yy,
+ const int x, const int y,
+ const int w, const int h,
+ const int xin, const int yin,
+ const int rowpix,
+ const int transparent,
+ const uint32_t fillColor,
+ int& pix,
+ uint32_t*& p,
+ uint32_t*& data,
+ GifRowType*& rows,
+ ColorMapObject*& colorMap)
+{
+ // if we use cachedColor, use it
+ if(cachedColorPtr)
+ {
+ // walk pixels without worring about transparency at all
+ for(yy = 0; yy < h; yy++)
+ {
+ p = data + ((y + yy) * rowpix) + x;
+ for(xx = 0; xx < w; xx++)
+ {
+ pix = rows[yin + yy][xin + xx];
+ *p = cachedColorPtr[pix];
+ p++;
+ }
+ }
+ }
+ // we don't have cachedColor. use PixelLookup function.
+ else
+ {
+ // walk pixels without worring about transparency at all
+ for(yy = 0; yy < h; yy++)
+ {
+ p = data + ((y + yy) * rowpix) + x;
+ for(xx = 0; xx < w; xx++)
+ {
+ pix = rows[yin + yy][xin + xx];
+ *p = PixelLookup(colorMap, pix);
+ p++;
+ }
+ }
+ }
+}
+
/**
* @brief Decode a gif image into rows then expand to 32bit into the destination
* data pointer.
@@ -738,132 +923,153 @@ bool DecodeImage(GifFileType* gif, GifCachedColorData& gifCachedColor, uint32_t*
// if we need to deal with transparent pixels at all...
if(transparent >= 0)
{
- // if we are told to FILL (overwrite with transparency kept)
- if(fill)
+ HandleTransparentPixels(fill, cachedColorPtr, xx, yy, x, y, w, h, xin, yin, rowpix, transparent, fillColor, pix, p, data, rows, colorMap);
+ }
+ else
+ {
+ HandleNonTransparentPixels(cachedColorPtr, xx, yy, x, y, w, h, xin, yin, rowpix, transparent, fillColor, pix, p, data, rows, colorMap);
+ }
+ ret = true;
+
+on_error:
+ if(rows)
+ {
+ free(rows);
+ }
+ return ret;
+}
+
+/// Walk through gif records in file to figure out info while reading the header
+void WalkThroughGifRecordsWhileReadingHeader(
+ const GifAccessor& gifAccessor,
+ GifRecordType& rec,
+ int& imageNumber,
+ FrameInfo*& frameInfo,
+ bool& full,
+ const ImageProperties& prop,
+ GifAnimationData& animated,
+ int& loopCount,
+ bool& success)
+{
+ do
+ {
+ if(DGifGetRecordType(gifAccessor.gif, &rec) == GIF_ERROR)
{
- // if we use cachedColor, use it
- if(cachedColorPtr)
+ // if we have a gif that ends part way through a sequence
+ // (or animation) consider it valid and just break - no error
+ if(imageNumber <= 1)
{
- for(yy = 0; yy < h; yy++)
- {
- p = data + ((y + yy) * rowpix) + x;
- for(xx = 0; xx < w; xx++)
- {
- pix = rows[yin + yy][xin + xx];
- if(pix != transparent)
- {
- *p = cachedColorPtr[pix];
- }
- else
- {
- *p = fillColor;
- }
- p++;
- }
- }
+ success = true;
}
- // we don't have cachedColor. use PixelLookup function.
else
{
- for(yy = 0; yy < h; yy++)
- {
- p = data + ((y + yy) * rowpix) + x;
- for(xx = 0; xx < w; xx++)
- {
- pix = rows[yin + yy][xin + xx];
- if(pix != transparent)
- {
- *p = PixelLookup(colorMap, pix);
- }
- else
- {
- *p = fillColor;
- }
- p++;
- }
- }
+ success = false;
+ DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
}
+ break;
}
- // paste on top with transparent pixels untouched
- else
+
+ // get image description section
+ if(rec == IMAGE_DESC_RECORD_TYPE)
{
- // if we use cachedColor, use it
- if(cachedColorPtr)
+ int img_code;
+ GifByteType* img;
+
+ // get image desc
+ if(DALI_UNLIKELY(DGifGetImageDesc(gifAccessor.gif) == GIF_ERROR))
{
- for(yy = 0; yy < h; yy++)
- {
- p = data + ((y + yy) * rowpix) + x;
- for(xx = 0; xx < w; xx++)
- {
- pix = rows[yin + yy][xin + xx];
- if(pix != transparent)
- {
- *p = cachedColorPtr[pix];
- }
- p++;
- }
- }
+ success = false;
+ DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+ break;
+ }
+ // skip decoding and just walk image to next
+ if(DALI_UNLIKELY(DGifGetCode(gifAccessor.gif, &img_code, &img) == GIF_ERROR))
+ {
+ success = false;
+ DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+ break;
}
- // we don't have cachedColor. use PixelLookup function.
+ // skip till next...
+ while(img)
+ {
+ img = NULL;
+ DGifGetCodeNext(gifAccessor.gif, &img);
+ }
+ // store geometry in the last frame info data
+ if(frameInfo)
+ {
+ StoreFrameInfo(gifAccessor.gif, frameInfo);
+ CheckTransparency(full, frameInfo, prop.w, prop.h);
+ }
+ // or if we dont have a frameInfo entry - create one even for stills
else
{
- for(yy = 0; yy < h; yy++)
+ // allocate and save frame with field data
+ frameInfo = NewFrame(animated, -1, 0, 0, imageNumber + 1);
+ if(DALI_UNLIKELY(!frameInfo))
{
- p = data + ((y + yy) * rowpix) + x;
- for(xx = 0; xx < w; xx++)
- {
- pix = rows[yin + yy][xin + xx];
- if(pix != transparent)
- {
- *p = PixelLookup(colorMap, pix);
- }
- p++;
- }
+ success = false;
+ DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+ break;
}
+ // store geometry info from gif image
+ StoreFrameInfo(gifAccessor.gif, frameInfo);
+ // check for transparency/alpha
+ CheckTransparency(full, frameInfo, prop.w, prop.h);
}
+ imageNumber++;
}
- }
- else
- {
- // if we use cachedColor, use it
- if(cachedColorPtr)
+ // we have an extension code block - for animated gifs for sure
+ else if(rec == EXTENSION_RECORD_TYPE)
{
- // walk pixels without worring about transparency at all
- for(yy = 0; yy < h; yy++)
+ int ext_code;
+ GifByteType* ext = NULL;
+
+ // get the first extension entry
+ DGifGetExtension(gifAccessor.gif, &ext_code, &ext);
+ while(ext)
{
- p = data + ((y + yy) * rowpix) + x;
- for(xx = 0; xx < w; xx++)
+ // graphic control extension - for animated gif data
+ // and transparent index + flag
+ if(ext_code == 0xf9)
{
- pix = rows[yin + yy][xin + xx];
- *p = cachedColorPtr[pix];
- p++;
+ // create frame and store it in image
+ int transparencyIndex = (ext[1] & 1) ? ext[4] : -1;
+ int disposeMode = (ext[1] >> 2) & 0x7;
+ int delay = (int(ext[3]) << 8) | int(ext[2]);
+ frameInfo = NewFrame(animated, transparencyIndex, disposeMode, delay, imageNumber + 1);
+ if(DALI_UNLIKELY(!frameInfo))
+ {
+ success = false;
+ DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+ break;
+ }
}
- }
- }
- // we don't have cachedColor. use PixelLookup function.
- else
- {
- // walk pixels without worring about transparency at all
- for(yy = 0; yy < h; yy++)
- {
- p = data + ((y + yy) * rowpix) + x;
- for(xx = 0; xx < w; xx++)
+ // netscape extension indicating loop count.
+ else if(ext_code == 0xff) /* application extension */
{
- pix = rows[yin + yy][xin + xx];
- *p = PixelLookup(colorMap, pix);
- p++;
+ if(!strncmp(reinterpret_cast<char*>(&ext[1]), "NETSCAPE2.0", 11) ||
+ !strncmp(reinterpret_cast<char*>(&ext[1]), "ANIMEXTS1.0", 11))
+ {
+ ext = NULL;
+ DGifGetExtensionNext(gifAccessor.gif, &ext);
+ if(ext[1] == 0x01)
+ {
+ loopCount = (int(ext[3]) << 8) | int(ext[2]);
+ if(loopCount > 0)
+ {
+ loopCount++;
+ }
+ }
+ }
}
+
+ // and continue onto the next extension entry
+ ext = NULL;
+ DGifGetExtensionNext(gifAccessor.gif, &ext);
}
}
- }
- ret = true;
-
-on_error:
- if(rows)
- {
- free(rows);
- }
- return ret;
+ } while(rec != TERMINATE_RECORD_TYPE && success);
}
/**
@@ -925,127 +1131,8 @@ bool ReadHeader(LoaderInfo& loaderInfo,
}
else
{
- // walk through gif records in file to figure out info
success = true;
- do
- {
- if(DGifGetRecordType(gifAccessor.gif, &rec) == GIF_ERROR)
- {
- // if we have a gif that ends part way through a sequence
- // (or animation) consider it valid and just break - no error
- if(imageNumber <= 1)
- {
- success = true;
- }
- else
- {
- success = false;
- DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
- }
- break;
- }
-
- // get image description section
- if(rec == IMAGE_DESC_RECORD_TYPE)
- {
- int img_code;
- GifByteType* img;
-
- // get image desc
- if(DALI_UNLIKELY(DGifGetImageDesc(gifAccessor.gif) == GIF_ERROR))
- {
- success = false;
- DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
- break;
- }
- // skip decoding and just walk image to next
- if(DALI_UNLIKELY(DGifGetCode(gifAccessor.gif, &img_code, &img) == GIF_ERROR))
- {
- success = false;
- DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
- break;
- }
- // skip till next...
- while(img)
- {
- img = NULL;
- DGifGetCodeNext(gifAccessor.gif, &img);
- }
- // store geometry in the last frame info data
- if(frameInfo)
- {
- StoreFrameInfo(gifAccessor.gif, frameInfo);
- CheckTransparency(full, frameInfo, prop.w, prop.h);
- }
- // or if we dont have a frameInfo entry - create one even for stills
- else
- {
- // allocate and save frame with field data
- frameInfo = NewFrame(animated, -1, 0, 0, imageNumber + 1);
- if(DALI_UNLIKELY(!frameInfo))
- {
- success = false;
- DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
- break;
- }
- // store geometry info from gif image
- StoreFrameInfo(gifAccessor.gif, frameInfo);
- // check for transparency/alpha
- CheckTransparency(full, frameInfo, prop.w, prop.h);
- }
- imageNumber++;
- }
- // we have an extension code block - for animated gifs for sure
- else if(rec == EXTENSION_RECORD_TYPE)
- {
- int ext_code;
- GifByteType* ext = NULL;
-
- // get the first extension entry
- DGifGetExtension(gifAccessor.gif, &ext_code, &ext);
- while(ext)
- {
- // graphic control extension - for animated gif data
- // and transparent index + flag
- if(ext_code == 0xf9)
- {
- // create frame and store it in image
- int transparencyIndex = (ext[1] & 1) ? ext[4] : -1;
- int disposeMode = (ext[1] >> 2) & 0x7;
- int delay = (int(ext[3]) << 8) | int(ext[2]);
- frameInfo = NewFrame(animated, transparencyIndex, disposeMode, delay, imageNumber + 1);
- if(DALI_UNLIKELY(!frameInfo))
- {
- success = false;
- DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
- break;
- }
- }
- // netscape extension indicating loop count.
- else if(ext_code == 0xff) /* application extension */
- {
- if(!strncmp(reinterpret_cast<char*>(&ext[1]), "NETSCAPE2.0", 11) ||
- !strncmp(reinterpret_cast<char*>(&ext[1]), "ANIMEXTS1.0", 11))
- {
- ext = NULL;
- DGifGetExtensionNext(gifAccessor.gif, &ext);
- if(ext[1] == 0x01)
- {
- loopCount = (int(ext[3]) << 8) | int(ext[2]);
- if(loopCount > 0)
- {
- loopCount++;
- }
- }
- }
- }
-
- // and continue onto the next extension entry
- ext = NULL;
- DGifGetExtensionNext(gifAccessor.gif, &ext);
- }
- }
- } while(rec != TERMINATE_RECORD_TYPE && success);
+ WalkThroughGifRecordsWhileReadingHeader(gifAccessor, rec, imageNumber, frameInfo, full, prop, animated, loopCount, success);
if(success)
{
@@ -1087,6 +1174,226 @@ bool ReadHeader(LoaderInfo& loaderInfo,
return success;
}
+/// Walk through gif records in file to figure out info
+bool WalkThroughGifRecords(
+ GifRecordType& rec,
+ LoaderInfo& loaderInfo,
+ GifAnimationData& animated,
+ int& imageNumber,
+ const int& index,
+ FrameInfo*& frameInfo,
+ const ImageProperties& prop,
+ ImageFrame*& lastPreservedFrame,
+ unsigned char*& pixels)
+{
+ do
+ {
+ if(DALI_UNLIKELY(DGifGetRecordType(loaderInfo.gifAccessor->gif, &rec) == GIF_ERROR))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+ return false;
+ }
+
+ if(rec == EXTENSION_RECORD_TYPE)
+ {
+ int ext_code;
+ GifByteType* ext = NULL;
+ DGifGetExtension(loaderInfo.gifAccessor->gif, &ext_code, &ext);
+
+ while(ext)
+ {
+ ext = NULL;
+ DGifGetExtensionNext(loaderInfo.gifAccessor->gif, &ext);
+ }
+ }
+ // get image description section
+ else if(rec == IMAGE_DESC_RECORD_TYPE)
+ {
+ int xin = 0, yin = 0, x = 0, y = 0, w = 0, h = 0;
+ int img_code;
+ GifByteType* img;
+ ImageFrame* previousFrame = NULL;
+ ImageFrame* thisFrame = NULL;
+
+ // get image desc
+ if(DALI_UNLIKELY(DGifGetImageDesc(loaderInfo.gifAccessor->gif) == GIF_ERROR))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+ return false;
+ }
+
+ // get the previous frame entry AND the current one to fill in
+ previousFrame = FindFrame(animated, imageNumber - 1);
+ thisFrame = FindFrame(animated, imageNumber);
+
+ // if we have a frame AND we're animated AND we have no data...
+ if((thisFrame) && (!thisFrame->data) && (animated.animated))
+ {
+ bool first = false;
+
+ // allocate it
+ thisFrame->data = new uint32_t[prop.w * prop.h];
+
+ if(DALI_UNLIKELY(!thisFrame->data))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
+ return false;
+ }
+
+ // Lazy fill background color feature.
+ // DecodeImage function draw range is EQUAL with previous FillImage range,
+ // We don't need to fill background that time.
+ // It will try to reduce the number of FillImage API call
+ // Note : We might check overlapping. But that operation looks expensive
+ // So, just optimize only if EQUAL case.
+ bool updateBackgroundColorLazy = false;
+ uint32_t backgroundColor = 0u;
+ int prevX = 0;
+ int prevY = 0;
+ int prevW = 0;
+ int prevH = 0;
+
+ // if we have no prior frame OR prior frame data... empty
+ if((!previousFrame) || (!previousFrame->data))
+ {
+ first = true;
+ frameInfo = &(thisFrame->info);
+ updateBackgroundColorLazy = true;
+ backgroundColor = 0u;
+ prevX = 0;
+ prevY = 0;
+ prevW = prop.w;
+ prevH = prop.h;
+ }
+ // we have a prior frame to copy data from...
+ else
+ {
+ frameInfo = &(previousFrame->info);
+
+ // fix coords of sub image in case it goes out...
+ ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
+
+ // if dispose mode is not restore - then copy pre frame
+ if(frameInfo->dispose != DISPOSE_PREVIOUS)
+ {
+ memcpy(thisFrame->data, previousFrame->data, prop.w * prop.h * sizeof(uint32_t));
+ }
+
+ // if dispose mode is "background" then fill with bg
+ if(frameInfo->dispose == DISPOSE_BACKGROUND)
+ {
+ updateBackgroundColorLazy = true;
+ backgroundColor = GetBackgroundColor(loaderInfo.gifAccessor->gif, frameInfo);
+ prevX = x;
+ prevY = y;
+ prevW = w;
+ prevH = h;
+ }
+ else if(frameInfo->dispose == DISPOSE_PREVIOUS) // GIF_DISPOSE_RESTORE
+ {
+ int prevIndex = 2;
+ do
+ {
+ // Find last preserved frame.
+ lastPreservedFrame = FindFrame(animated, imageNumber - prevIndex);
+ if(DALI_UNLIKELY(!lastPreservedFrame))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_LAST_PRESERVED_FRAME_NOT_FOUND");
+ return false;
+ }
+ prevIndex++;
+ } while(lastPreservedFrame && lastPreservedFrame->info.dispose == DISPOSE_PREVIOUS);
+
+ if(lastPreservedFrame)
+ {
+ memcpy(thisFrame->data, lastPreservedFrame->data, prop.w * prop.h * sizeof(uint32_t));
+ }
+ }
+ }
+ // now draw this frame on top
+ frameInfo = &(thisFrame->info);
+ ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
+
+ if(updateBackgroundColorLazy)
+ {
+ // If this frame's x,y,w,h is not equal with previous x,y,w,h, FillImage. else, don't fill
+ if(prevX != x || prevY != y || prevW != w || prevH != h)
+ {
+ FillImage(thisFrame->data, prop.w, backgroundColor, prevX, prevY, prevW, prevH);
+ // Don't send background color information to DecodeImage function.
+ updateBackgroundColorLazy = false;
+ }
+ }
+ if(DALI_UNLIKELY(!DecodeImage(loaderInfo.gifAccessor->gif, loaderInfo.cachedColor, thisFrame->data, prop.w, xin, yin, frameInfo->transparent, x, y, w, h, first || updateBackgroundColorLazy, backgroundColor)))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
+ return false;
+ }
+
+ // mark as loaded and done
+ thisFrame->loaded = true;
+
+ FlushFrames(animated, prop.w, prop.h, thisFrame, previousFrame, lastPreservedFrame);
+ }
+ // if we have a frame BUT the image is not animated. different
+ // path
+ else if((thisFrame) && (!thisFrame->data) && (!animated.animated))
+ {
+ // if we don't have the data decoded yet - decode it
+ if((!thisFrame->loaded) || (!thisFrame->data))
+ {
+ // use frame info but we WONT allocate frame pixels
+ frameInfo = &(thisFrame->info);
+ ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
+
+ // clear out all pixels only if x,y,w,h is not whole image.
+ if(x != 0 || y != 0 || w != static_cast<int>(prop.w) || h != static_cast<int>(prop.h))
+ {
+ const std::uint32_t backgroundColor = GetBackgroundColor(loaderInfo.gifAccessor->gif, frameInfo);
+ FillImage(reinterpret_cast<uint32_t*>(pixels), prop.w, backgroundColor, 0, 0, prop.w, prop.h);
+ }
+
+ // and decode the gif with overwriting
+ if(DALI_UNLIKELY(!DecodeImage(loaderInfo.gifAccessor->gif, loaderInfo.cachedColor, reinterpret_cast<uint32_t*>(pixels), prop.w, xin, yin, frameInfo->transparent, x, y, w, h, true, 0u)))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
+ return false;
+ }
+
+ // mark as loaded and done
+ thisFrame->loaded = true;
+ }
+ // flush mem we don't need (at expense of decode cpu)
+ }
+ else
+ {
+ // skip decoding and just walk image to next
+ if(DALI_UNLIKELY(DGifGetCode(loaderInfo.gifAccessor->gif, &img_code, &img) == GIF_ERROR))
+ {
+ DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
+ return false;
+ }
+
+ while(img)
+ {
+ img = NULL;
+ DGifGetCodeNext(loaderInfo.gifAccessor->gif, &img);
+ }
+ }
+
+ imageNumber++;
+ // if we found the image we wanted - get out of here
+ if(imageNumber > index)
+ {
+ break;
+ }
+ }
+ } while(rec != TERMINATE_RECORD_TYPE);
+
+ return true;
+}
+
+
/**
* @brief Reader next frame of the gif file and populates structures accordingly.
*
@@ -1163,210 +1470,10 @@ bool ReadNextFrame(LoaderInfo& loaderInfo, ImageProperties& prop, // use for w
// our current position is the previous frame we decoded from the file
imageNumber = loaderInfo.imageNumber;
- // walk through gif records in file to figure out info
- do
+ if(!WalkThroughGifRecords(rec, loaderInfo, animated, imageNumber, index, frameInfo, prop, lastPreservedFrame, pixels))
{
- if(DALI_UNLIKELY(DGifGetRecordType(loaderInfo.gifAccessor->gif, &rec) == GIF_ERROR))
- {
- DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
- return false;
- }
-
- if(rec == EXTENSION_RECORD_TYPE)
- {
- int ext_code;
- GifByteType* ext = NULL;
- DGifGetExtension(loaderInfo.gifAccessor->gif, &ext_code, &ext);
-
- while(ext)
- {
- ext = NULL;
- DGifGetExtensionNext(loaderInfo.gifAccessor->gif, &ext);
- }
- }
- // get image description section
- else if(rec == IMAGE_DESC_RECORD_TYPE)
- {
- int xin = 0, yin = 0, x = 0, y = 0, w = 0, h = 0;
- int img_code;
- GifByteType* img;
- ImageFrame* previousFrame = NULL;
- ImageFrame* thisFrame = NULL;
-
- // get image desc
- if(DALI_UNLIKELY(DGifGetImageDesc(loaderInfo.gifAccessor->gif) == GIF_ERROR))
- {
- DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
- return false;
- }
-
- // get the previous frame entry AND the current one to fill in
- previousFrame = FindFrame(animated, imageNumber - 1);
- thisFrame = FindFrame(animated, imageNumber);
-
- // if we have a frame AND we're animated AND we have no data...
- if((thisFrame) && (!thisFrame->data) && (animated.animated))
- {
- bool first = false;
-
- // allocate it
- thisFrame->data = new uint32_t[prop.w * prop.h];
-
- if(DALI_UNLIKELY(!thisFrame->data))
- {
- DALI_LOG_ERROR("LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
- return false;
- }
-
- // Lazy fill background color feature.
- // DecodeImage function draw range is EQUAL with previous FillImage range,
- // We don't need to fill background that time.
- // It will try to reduce the number of FillImage API call
- // Note : We might check overlapping. But that operation looks expensive
- // So, just optimize only if EQUAL case.
- bool updateBackgroundColorLazy = false;
- uint32_t backgroundColor = 0u;
- int prevX = 0;
- int prevY = 0;
- int prevW = 0;
- int prevH = 0;
-
- // if we have no prior frame OR prior frame data... empty
- if((!previousFrame) || (!previousFrame->data))
- {
- first = true;
- frameInfo = &(thisFrame->info);
- updateBackgroundColorLazy = true;
- backgroundColor = 0u;
- prevX = 0;
- prevY = 0;
- prevW = prop.w;
- prevH = prop.h;
- }
- // we have a prior frame to copy data from...
- else
- {
- frameInfo = &(previousFrame->info);
-
- // fix coords of sub image in case it goes out...
- ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
-
- // if dispose mode is not restore - then copy pre frame
- if(frameInfo->dispose != DISPOSE_PREVIOUS)
- {
- memcpy(thisFrame->data, previousFrame->data, prop.w * prop.h * sizeof(uint32_t));
- }
-
- // if dispose mode is "background" then fill with bg
- if(frameInfo->dispose == DISPOSE_BACKGROUND)
- {
- updateBackgroundColorLazy = true;
- backgroundColor = GetBackgroundColor(loaderInfo.gifAccessor->gif, frameInfo);
- prevX = x;
- prevY = y;
- prevW = w;
- prevH = h;
- }
- else if(frameInfo->dispose == DISPOSE_PREVIOUS) // GIF_DISPOSE_RESTORE
- {
- int prevIndex = 2;
- do
- {
- // Find last preserved frame.
- lastPreservedFrame = FindFrame(animated, imageNumber - prevIndex);
- if(DALI_UNLIKELY(!lastPreservedFrame))
- {
- DALI_LOG_ERROR("LOAD_ERROR_LAST_PRESERVED_FRAME_NOT_FOUND");
- return false;
- }
- prevIndex++;
- } while(lastPreservedFrame && lastPreservedFrame->info.dispose == DISPOSE_PREVIOUS);
-
- if(lastPreservedFrame)
- {
- memcpy(thisFrame->data, lastPreservedFrame->data, prop.w * prop.h * sizeof(uint32_t));
- }
- }
- }
- // now draw this frame on top
- frameInfo = &(thisFrame->info);
- ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
-
- if(updateBackgroundColorLazy)
- {
- // If this frame's x,y,w,h is not equal with previous x,y,w,h, FillImage. else, don't fill
- if(prevX != x || prevY != y || prevW != w || prevH != h)
- {
- FillImage(thisFrame->data, prop.w, backgroundColor, prevX, prevY, prevW, prevH);
- // Don't send background color information to DecodeImage function.
- updateBackgroundColorLazy = false;
- }
- }
- if(DALI_UNLIKELY(!DecodeImage(loaderInfo.gifAccessor->gif, loaderInfo.cachedColor, thisFrame->data, prop.w, xin, yin, frameInfo->transparent, x, y, w, h, first || updateBackgroundColorLazy, backgroundColor)))
- {
- DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
- return false;
- }
-
- // mark as loaded and done
- thisFrame->loaded = true;
-
- FlushFrames(animated, prop.w, prop.h, thisFrame, previousFrame, lastPreservedFrame);
- }
- // if we have a frame BUT the image is not animated. different
- // path
- else if((thisFrame) && (!thisFrame->data) && (!animated.animated))
- {
- // if we don't have the data decoded yet - decode it
- if((!thisFrame->loaded) || (!thisFrame->data))
- {
- // use frame info but we WONT allocate frame pixels
- frameInfo = &(thisFrame->info);
- ClipCoordinates(prop.w, prop.h, &xin, &yin, frameInfo->x, frameInfo->y, frameInfo->w, frameInfo->h, &x, &y, &w, &h);
-
- // clear out all pixels only if x,y,w,h is not whole image.
- if(x != 0 || y != 0 || w != static_cast<int>(prop.w) || h != static_cast<int>(prop.h))
- {
- const std::uint32_t backgroundColor = GetBackgroundColor(loaderInfo.gifAccessor->gif, frameInfo);
- FillImage(reinterpret_cast<uint32_t*>(pixels), prop.w, backgroundColor, 0, 0, prop.w, prop.h);
- }
-
- // and decode the gif with overwriting
- if(DALI_UNLIKELY(!DecodeImage(loaderInfo.gifAccessor->gif, loaderInfo.cachedColor, reinterpret_cast<uint32_t*>(pixels), prop.w, xin, yin, frameInfo->transparent, x, y, w, h, true, 0u)))
- {
- DALI_LOG_ERROR("LOAD_ERROR_CORRUPT_FILE\n");
- return false;
- }
-
- // mark as loaded and done
- thisFrame->loaded = true;
- }
- // flush mem we don't need (at expense of decode cpu)
- }
- else
- {
- // skip decoding and just walk image to next
- if(DALI_UNLIKELY(DGifGetCode(loaderInfo.gifAccessor->gif, &img_code, &img) == GIF_ERROR))
- {
- DALI_LOG_ERROR("LOAD_ERROR_UNKNOWN_FORMAT\n");
- return false;
- }
-
- while(img)
- {
- img = NULL;
- DGifGetCodeNext(loaderInfo.gifAccessor->gif, &img);
- }
- }
-
- imageNumber++;
- // if we found the image we wanted - get out of here
- if(imageNumber > index)
- {
- break;
- }
- }
- } while(rec != TERMINATE_RECORD_TYPE);
+ return false;
+ }
// if we are at the end of the animation or not animated, close file
loaderInfo.imageNumber = imageNumber;