aboutsummaryrefslogtreecommitdiff
path: root/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
blob: 1e897a7e41b9fb9794f1e7fb8d17777a4e2050c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 *      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
 *  <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include <gif_lib.h>
#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 <vector>
#include <string>
#include <memory>
#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() = default;
  virtual ~GifFrame();

  unsigned char* m_pImage = nullptr;
  unsigned int m_delay = 0;

private:
  GifFrame(const GifFrame& src);

  unsigned int m_top = 0;
  unsigned int m_left = 0;
  unsigned int m_disposal = 0;
  unsigned int m_height = 0;
  unsigned int m_width = 0;
  unsigned int m_imageSize = 0;
  std::vector<GifColor>   m_palette;
};



class GifHelper
{
  friend class GifFrame;

  typedef std::shared_ptr<GifFrame> FramePtr;

public:
  GifHelper();
  virtual ~GifHelper();


  bool LoadGif(const char* file);

  std::vector<FramePtr>& 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<FramePtr> m_frames;
  unsigned int m_imageSize = 0;
  unsigned int m_pitch = 0;
  unsigned int m_loops = 0;
  unsigned int m_numFrames = 0;

  std::string     m_filename;
  GifFileType* m_gif = nullptr;
  std::vector<GifColor> m_globalPalette;
  unsigned char* m_pTemplate = nullptr;
  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<GifColor> &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
};