aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjenkins4kodi <jenkins4kodi@users.noreply.github.com>2016-01-08 19:38:57 +0100
committerjenkins4kodi <jenkins4kodi@users.noreply.github.com>2016-01-08 19:38:57 +0100
commit0544094673c015228ecf31e35f5e7c62e61c3a1a (patch)
tree63c2197094cf34507e5e7500d0136afb58b53fa3
parentfdccf0db089a2491c4b3fdb1fdcf916c420292c8 (diff)
parentd4b994823e042ec47bf821ca5055216aaf443f6d (diff)
Merge pull request #8786 from ace20022/gif_jarvis
-rw-r--r--xbmc/guilib/DllLibGif.h8
-rw-r--r--xbmc/guilib/Gif.cpp80
-rw-r--r--xbmc/guilib/Gif.h7
3 files changed, 75 insertions, 20 deletions
diff --git a/xbmc/guilib/DllLibGif.h b/xbmc/guilib/DllLibGif.h
index 284f52d715..e082f697db 100644
--- a/xbmc/guilib/DllLibGif.h
+++ b/xbmc/guilib/DllLibGif.h
@@ -52,8 +52,12 @@ public:
virtual GifFileType* DGifOpenFileName(const char *GifFileName, int *Error) = 0;
virtual GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error) = 0;
virtual int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex, GraphicsControlBlock *GCB) = 0;
+#if GIFLIB_MINOR >= 1
virtual int DGifCloseFile(GifFileType* GifFile, int *Error)=0;
#else
+ virtual int DGifCloseFile(GifFileType* GifFile) = 0;
+#endif
+#else
virtual GifFileType* DGifOpenFileName(const char *GifFileName) = 0;
virtual GifFileType *DGifOpen(void *userPtr, InputFunc readFunc)=0;
virtual int DGifGetExtension(GifFileType * GifFile, int *GifExtCode, GifByteType ** GifExtension) = 0;
@@ -72,8 +76,12 @@ class DllLibGif : public DllDynamic, DllLibGifInterface
DEFINE_METHOD2(GifFileType*, DGifOpenFileName, (const char *p1, int *p2))
DEFINE_METHOD3(GifFileType*, DGifOpen, (void *p1, InputFunc p2, int *p3))
DEFINE_METHOD3(int, DGifSavedExtensionToGCB, (GifFileType *p1, int p2, GraphicsControlBlock *p3))
+#if GIFLIB_MINOR >= 1
DEFINE_METHOD2(int, DGifCloseFile, (GifFileType* p1, int *p2))
#else
+ DEFINE_METHOD1(int, DGifCloseFile, (GifFileType* p1))
+#endif
+#else
DEFINE_METHOD0(int, GifLastError)
DEFINE_METHOD1(GifFileType*, DGifOpenFileName, (const char *p1))
DEFINE_METHOD2(GifFileType*, DGifOpen, (void *p1, InputFunc p2))
diff --git a/xbmc/guilib/Gif.cpp b/xbmc/guilib/Gif.cpp
index 02f0c6e7bc..1e5792d82d 100644
--- a/xbmc/guilib/Gif.cpp
+++ b/xbmc/guilib/Gif.cpp
@@ -98,11 +98,13 @@ void Gif::Close(GifFileType* gif)
{
int err = 0;
int reason = 0;
-#if GIFLIB_MAJOR == 5
+#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
err = m_dll.DGifCloseFile(gif, &reason);
#else
err = m_dll.DGifCloseFile(gif);
+#if GIFLIB_MAJOR < 5
reason = m_dll.GifLastError();
+#endif
if (err == GIF_ERROR)
free(gif);
#endif
@@ -154,7 +156,9 @@ bool Gif::LoadGifMetaData(GifFileType* gif)
// Read number of loops
if (++extb && extb->Function == CONTINUE_EXT_FUNC_CODE)
{
- m_loops = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]);
+ uint8_t low = static_cast<uint8_t>(extb->Bytes[1]);
+ uint8_t high = static_cast<uint8_t>(extb->Bytes[2]);
+ m_loops = UNSIGNED_LITTLE_ENDIAN(low, high);
}
}
}
@@ -216,7 +220,19 @@ bool Gif::LoadGif(const char* file)
{
InitTemplateAndColormap();
- return ExtractFrames(m_numFrames);
+ int extractedFrames = ExtractFrames(m_numFrames);
+ if (extractedFrames < 0)
+ {
+ CLog::Log(LOGDEBUG, "Gif::LoadGif(): Could not extract any frame. File %s", memOrFile().c_str());
+ return false;
+ }
+ else if (extractedFrames < (int)m_numFrames)
+ {
+ CLog::Log(LOGDEBUG, "Gif::LoadGif(): Could only extract %d/%d frames. File %s", extractedFrames, m_numFrames, memOrFile().c_str());
+ m_numFrames = extractedFrames;
+ }
+
+ return true;
}
catch (std::bad_alloc& ba)
{
@@ -321,13 +337,13 @@ bool Gif::GcbToFrame(GifFrame &frame, unsigned int imgIdx)
}
else
{
- frame.m_delay = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]) * 10;
+ uint8_t low = static_cast<uint8_t>(extb->Bytes[1]);
+ uint8_t high = static_cast<uint8_t>(extb->Bytes[2]);
+ frame.m_delay = UNSIGNED_LITTLE_ENDIAN(low, high) * 10;
frame.m_disposal = (extb->Bytes[0] >> 2) & 0x07;
if (extb->Bytes[0] & 0x01)
{
- transparent = static_cast<int>(extb->Bytes[3]);
- if (transparent < 0)
- transparent += 256;
+ transparent = static_cast<uint8_t>(extb->Bytes[3]);
}
else
transparent = -1;
@@ -341,17 +357,18 @@ bool Gif::GcbToFrame(GifFrame &frame, unsigned int imgIdx)
return true;
}
-bool Gif::ExtractFrames(unsigned int count)
+int Gif::ExtractFrames(unsigned int count)
{
if (!m_gif)
- return false;
+ return -1;
if (!m_pTemplate)
{
CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): No frame template available");
- return false;
+ return -1;
}
+ int extracted = 0;
for (unsigned int i = 0; i < count; i++)
{
FramePtr frame(new GifFrame);
@@ -366,7 +383,7 @@ bool Gif::ExtractFrames(unsigned int count)
|| !frame->m_width || !frame->m_height
|| frame->m_width > m_width || frame->m_height > m_height)
{
- CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d)",
+ CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d), skip it",
frame->m_width, frame->m_height, frame->m_left, frame->m_top, m_width, m_height);
continue;
}
@@ -383,13 +400,16 @@ bool Gif::ExtractFrames(unsigned int count)
}
else
{
- CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): No color map found for frame %d", i);
+ CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): No color map found for frame %d, skip it", i);
continue;
}
// fill delay, disposal and transparent color into frame
if (!GcbToFrame(*frame, i))
- return false;
+ {
+ CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): Corrupted Graphics Control Block for frame %d, skip it", i);
+ continue;
+ }
frame->m_pImage = new unsigned char[m_imageSize];
frame->m_imageSize = m_imageSize;
@@ -398,11 +418,15 @@ bool Gif::ExtractFrames(unsigned int count)
ConstructFrame(*frame, savedImage.RasterBits);
if (!PrepareTemplate(*frame))
- return false;
+ {
+ CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): Could not prepare template after frame %d, skip it", i);
+ continue;
+ }
+ extracted++;
m_frames.push_back(frame);
}
- return true;
+ return extracted;
}
void Gif::ConstructFrame(GifFrame &frame, const unsigned char* src) const
@@ -433,7 +457,7 @@ void Gif::ConstructFrame(GifFrame &frame, const unsigned char* src) const
}
}
-bool Gif::PrepareTemplate(const GifFrame &frame)
+bool Gif::PrepareTemplate(GifFrame &frame)
{
switch (frame.m_disposal)
{
@@ -457,6 +481,17 @@ bool Gif::PrepareTemplate(const GifFrame &frame)
/* Restore to previous content */
case DISPOSE_PREVIOUS:
{
+
+ /*
+ * This disposal method makes no sense for the first frame
+ * Since browsers etc. handle that too, we'll fall back to DISPOSE_DO_NOT
+ */
+ if (m_frames.empty())
+ {
+ frame.m_disposal = DISPOSE_DO_NOT;
+ return PrepareTemplate(frame);
+ }
+
bool valid = false;
for (int i = m_frames.size() - 1; i >= 0; --i)
@@ -522,8 +557,19 @@ bool Gif::LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize, unsig
{
InitTemplateAndColormap();
- if (!ExtractFrames(m_numFrames))
+ int extractedFrames = ExtractFrames(m_numFrames);
+ if (extractedFrames < 0)
+ {
+ CLog::Log(LOGDEBUG, "Gif::LoadGif(): Could not extract any frame. File %s", memOrFile().c_str());
return false;
+ }
+ else if (extractedFrames < (int)m_numFrames)
+ {
+ CLog::Log(LOGDEBUG, "Gif::LoadGif(): Could only extract %d/%d frames. File %s", extractedFrames, m_numFrames, memOrFile().c_str());
+ m_numFrames = extractedFrames;
+ }
+
+ return true;
}
catch (std::bad_alloc& ba)
{
diff --git a/xbmc/guilib/Gif.h b/xbmc/guilib/Gif.h
index d144504c0f..2ad43e0ff2 100644
--- a/xbmc/guilib/Gif.h
+++ b/xbmc/guilib/Gif.h
@@ -24,6 +24,7 @@
#include "DllLibGif.h"
#include <memory>
#include <vector>
+#include "URL.h"
namespace XFILE
{
@@ -104,16 +105,16 @@ private:
bool Slurp(GifFileType* gif);
static void ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size);
bool GcbToFrame(GifFrame &frame, unsigned int imgIdx);
- bool ExtractFrames(unsigned int count);
+ int ExtractFrames(unsigned int count);
void ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame);
void ConstructFrame(GifFrame &frame, const unsigned char* src) const;
- bool PrepareTemplate(const GifFrame &frame);
+ bool PrepareTemplate(GifFrame &frame);
void Release();
void PrettyPrintError(std::string messageTemplate, int reason);
inline std::string memOrFile()
{
- return m_filename.empty() ? std::string("memory file") : m_filename;
+ return m_filename.empty() ? std::string("memory file") : CURL::GetRedacted(m_filename);
}
};