/* * Copyright (C) 2014 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, see * . * */ #pragma once #include #ifndef CONTINUE_EXT_FUNC_CODE #define CONTINUE_EXT_FUNC_CODE 0 #endif #ifndef DISPOSAL_UNSPECIFIED #define DISPOSAL_UNSPECIFIED 0 #endif #ifndef DISPOSE_DO_NOT #define DISPOSE_DO_NOT 1 #endif #ifndef DISPOSE_BACKGROUND #define DISPOSE_BACKGROUND 2 #endif #ifndef DISPOSE_PREVIOUS #define DISPOSE_PREVIOUS 3 #endif #include #include #include #include "SimpleFS.h" #pragma pack(1) struct GifColor { uint8_t b, g, r, a; }; #pragma pack() class CFile; class GifFrame { friend class GifHelper; public: GifFrame(); virtual ~GifFrame(); unsigned char* m_pImage; unsigned int m_delay; private: GifFrame(const GifFrame& src); unsigned int m_top; unsigned int m_left; unsigned int m_disposal; unsigned int m_height; unsigned int m_width; unsigned int m_imageSize; std::vector m_palette; }; class GifHelper { friend class GifFrame; typedef std::shared_ptr FramePtr; public: GifHelper(); virtual ~GifHelper(); bool LoadGif(const char* file); std::vector& GetFrames() { return m_frames; } unsigned int GetPitch() const { return m_pitch; } unsigned int GetNumLoops() const { return m_loops; } unsigned int GetWidth() const { return m_width; } unsigned int GetHeight() const { return m_height; } private: std::vector m_frames; unsigned int m_imageSize; unsigned int m_pitch; unsigned int m_loops; unsigned int m_numFrames; std::string m_filename; GifFileType* m_gif; std::vector m_globalPalette; unsigned char* m_pTemplate; CFile* m_gifFile; unsigned int m_width; unsigned int m_height; bool Open(GifFileType *& gif, void * dataPtr, InputFunc readFunc); void Close(GifFileType * gif); const char* Reason(int reason); bool LoadGifMetaData(const char* file); bool Slurp(GifFileType* gif); void InitTemplateAndColormap(); bool LoadGifMetaData(GifFileType* gif); static void ConvertColorTable(std::vector &dest, ColorMapObject* src, unsigned int size); bool GcbToFrame(GifFrame &frame, unsigned int imgIdx); int ExtractFrames(unsigned int count); void ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame); void ConstructFrame(GifFrame &frame, const unsigned char* src) const; bool PrepareTemplate(GifFrame &frame); void Release(); #if GIFLIB_MAJOR != 5 /* taken from giflib 5.1.0 */ const char* GifErrorString(int ErrorCode) { const char *Err; switch (ErrorCode) { case E_GIF_ERR_OPEN_FAILED: Err = "Failed to open given file"; break; case E_GIF_ERR_WRITE_FAILED: Err = "Failed to write to given file"; break; case E_GIF_ERR_HAS_SCRN_DSCR: Err = "Screen descriptor has already been set"; break; case E_GIF_ERR_HAS_IMAG_DSCR: Err = "Image descriptor is still active"; break; case E_GIF_ERR_NO_COLOR_MAP: Err = "Neither global nor local color map"; break; case E_GIF_ERR_DATA_TOO_BIG: Err = "Number of pixels bigger than width * height"; break; case E_GIF_ERR_NOT_ENOUGH_MEM: Err = "Failed to allocate required memory"; break; case E_GIF_ERR_DISK_IS_FULL: Err = "Write failed (disk full?)"; break; case E_GIF_ERR_CLOSE_FAILED: Err = "Failed to close given file"; break; case E_GIF_ERR_NOT_WRITEABLE: Err = "Given file was not opened for write"; break; case D_GIF_ERR_OPEN_FAILED: Err = "Failed to open given file"; break; case D_GIF_ERR_READ_FAILED: Err = "Failed to read from given file"; break; case D_GIF_ERR_NOT_GIF_FILE: Err = "Data is not in GIF format"; break; case D_GIF_ERR_NO_SCRN_DSCR: Err = "No screen descriptor detected"; break; case D_GIF_ERR_NO_IMAG_DSCR: Err = "No Image Descriptor detected"; break; case D_GIF_ERR_NO_COLOR_MAP: Err = "Neither global nor local color map"; break; case D_GIF_ERR_WRONG_RECORD: Err = "Wrong record type detected"; break; case D_GIF_ERR_DATA_TOO_BIG: Err = "Number of pixels bigger than width * height"; break; case D_GIF_ERR_NOT_ENOUGH_MEM: Err = "Failed to allocate required memory"; break; case D_GIF_ERR_CLOSE_FAILED: Err = "Failed to close given file"; break; case D_GIF_ERR_NOT_READABLE: Err = "Given file was not opened for read"; break; case D_GIF_ERR_IMAGE_DEFECT: Err = "Image is defective, decoding aborted"; break; case D_GIF_ERR_EOF_TOO_SOON: Err = "Image EOF detected before image complete"; break; default: Err = NULL; break; } return Err; } #endif };