diff options
author | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2016-01-08 19:38:57 +0100 |
---|---|---|
committer | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2016-01-08 19:38:57 +0100 |
commit | 0544094673c015228ecf31e35f5e7c62e61c3a1a (patch) | |
tree | 63c2197094cf34507e5e7500d0136afb58b53fa3 | |
parent | fdccf0db089a2491c4b3fdb1fdcf916c420292c8 (diff) | |
parent | d4b994823e042ec47bf821ca5055216aaf443f6d (diff) |
Merge pull request #8786 from ace20022/gif_jarvis
-rw-r--r-- | xbmc/guilib/DllLibGif.h | 8 | ||||
-rw-r--r-- | xbmc/guilib/Gif.cpp | 80 | ||||
-rw-r--r-- | xbmc/guilib/Gif.h | 7 |
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); } }; |