1 /* 2 * Copyright (C) 2014 Team Kodi 3 * http://kodi.tv 4 * 5 * This Program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2, or (at your option) 8 * any later version. 9 * 10 * This Program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with XBMC; see the file COPYING. If not, see 17 * <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #pragma once 22 23 #include <gif_lib.h> 24 #ifndef CONTINUE_EXT_FUNC_CODE 25 #define CONTINUE_EXT_FUNC_CODE 0 26 #endif 27 28 #ifndef DISPOSAL_UNSPECIFIED 29 #define DISPOSAL_UNSPECIFIED 0 30 #endif 31 32 #ifndef DISPOSE_DO_NOT 33 #define DISPOSE_DO_NOT 1 34 #endif 35 36 #ifndef DISPOSE_BACKGROUND 37 #define DISPOSE_BACKGROUND 2 38 #endif 39 40 #ifndef DISPOSE_PREVIOUS 41 #define DISPOSE_PREVIOUS 3 42 #endif 43 44 #include <vector> 45 #include <string> 46 #include <memory> 47 #include "SimpleFS.h" 48 49 #pragma pack(1) 50 struct GifColor 51 { 52 uint8_t b, g, r, a; 53 }; 54 #pragma pack() 55 56 class CFile; 57 58 class GifFrame 59 { 60 friend class GifHelper; 61 public: 62 63 GifFrame() = default; 64 virtual ~GifFrame(); 65 66 unsigned char* m_pImage = nullptr; 67 unsigned int m_delay = 0; 68 69 private: 70 GifFrame(const GifFrame& src); 71 72 unsigned int m_top = 0; 73 unsigned int m_left = 0; 74 unsigned int m_disposal = 0; 75 unsigned int m_height = 0; 76 unsigned int m_width = 0; 77 unsigned int m_imageSize = 0; 78 std::vector<GifColor> m_palette; 79 }; 80 81 82 83 class GifHelper 84 { 85 friend class GifFrame; 86 87 typedef std::shared_ptr<GifFrame> FramePtr; 88 89 public: 90 GifHelper(); 91 virtual ~GifHelper(); 92 93 94 bool LoadGif(const char* file); 95 GetFrames()96 std::vector<FramePtr>& GetFrames() { return m_frames; } GetPitch()97 unsigned int GetPitch() const { return m_pitch; } GetNumLoops()98 unsigned int GetNumLoops() const { return m_loops; } GetWidth()99 unsigned int GetWidth() const { return m_width; } GetHeight()100 unsigned int GetHeight() const { return m_height; } 101 102 private: 103 std::vector<FramePtr> m_frames; 104 unsigned int m_imageSize = 0; 105 unsigned int m_pitch = 0; 106 unsigned int m_loops = 0; 107 unsigned int m_numFrames = 0; 108 109 std::string m_filename; 110 GifFileType* m_gif = nullptr; 111 std::vector<GifColor> m_globalPalette; 112 unsigned char* m_pTemplate = nullptr; 113 CFile* m_gifFile; 114 115 unsigned int m_width; 116 unsigned int m_height; 117 118 bool Open(GifFileType *& gif, void * dataPtr, InputFunc readFunc); 119 void Close(GifFileType * gif); 120 121 const char* Reason(int reason); 122 123 bool LoadGifMetaData(const char* file); 124 bool Slurp(GifFileType* gif); 125 void InitTemplateAndColormap(); 126 bool LoadGifMetaData(GifFileType* gif); 127 static void ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size); 128 bool GcbToFrame(GifFrame &frame, unsigned int imgIdx); 129 int ExtractFrames(unsigned int count); 130 void ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame); 131 void ConstructFrame(GifFrame &frame, const unsigned char* src) const; 132 bool PrepareTemplate(GifFrame &frame); 133 void Release(); 134 135 #if GIFLIB_MAJOR != 5 136 /* 137 taken from giflib 5.1.0 138 */ GifErrorString(int ErrorCode)139 const char* GifErrorString(int ErrorCode) 140 { 141 const char *Err; 142 143 switch (ErrorCode) { 144 case E_GIF_ERR_OPEN_FAILED: 145 Err = "Failed to open given file"; 146 break; 147 case E_GIF_ERR_WRITE_FAILED: 148 Err = "Failed to write to given file"; 149 break; 150 case E_GIF_ERR_HAS_SCRN_DSCR: 151 Err = "Screen descriptor has already been set"; 152 break; 153 case E_GIF_ERR_HAS_IMAG_DSCR: 154 Err = "Image descriptor is still active"; 155 break; 156 case E_GIF_ERR_NO_COLOR_MAP: 157 Err = "Neither global nor local color map"; 158 break; 159 case E_GIF_ERR_DATA_TOO_BIG: 160 Err = "Number of pixels bigger than width * height"; 161 break; 162 case E_GIF_ERR_NOT_ENOUGH_MEM: 163 Err = "Failed to allocate required memory"; 164 break; 165 case E_GIF_ERR_DISK_IS_FULL: 166 Err = "Write failed (disk full?)"; 167 break; 168 case E_GIF_ERR_CLOSE_FAILED: 169 Err = "Failed to close given file"; 170 break; 171 case E_GIF_ERR_NOT_WRITEABLE: 172 Err = "Given file was not opened for write"; 173 break; 174 case D_GIF_ERR_OPEN_FAILED: 175 Err = "Failed to open given file"; 176 break; 177 case D_GIF_ERR_READ_FAILED: 178 Err = "Failed to read from given file"; 179 break; 180 case D_GIF_ERR_NOT_GIF_FILE: 181 Err = "Data is not in GIF format"; 182 break; 183 case D_GIF_ERR_NO_SCRN_DSCR: 184 Err = "No screen descriptor detected"; 185 break; 186 case D_GIF_ERR_NO_IMAG_DSCR: 187 Err = "No Image Descriptor detected"; 188 break; 189 case D_GIF_ERR_NO_COLOR_MAP: 190 Err = "Neither global nor local color map"; 191 break; 192 case D_GIF_ERR_WRONG_RECORD: 193 Err = "Wrong record type detected"; 194 break; 195 case D_GIF_ERR_DATA_TOO_BIG: 196 Err = "Number of pixels bigger than width * height"; 197 break; 198 case D_GIF_ERR_NOT_ENOUGH_MEM: 199 Err = "Failed to allocate required memory"; 200 break; 201 case D_GIF_ERR_CLOSE_FAILED: 202 Err = "Failed to close given file"; 203 break; 204 case D_GIF_ERR_NOT_READABLE: 205 Err = "Given file was not opened for read"; 206 break; 207 case D_GIF_ERR_IMAGE_DEFECT: 208 Err = "Image is defective, decoding aborted"; 209 break; 210 case D_GIF_ERR_EOF_TOO_SOON: 211 Err = "Image EOF detected before image complete"; 212 break; 213 default: 214 Err = NULL; 215 break; 216 } 217 return Err; 218 } 219 #endif 220 }; 221