aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartijn Kaijser <martijn@xbmc.org>2016-01-10 07:29:26 -0800
committerMartijn Kaijser <martijn@xbmc.org>2016-01-10 07:29:26 -0800
commit252aceae210e385a32270bcde9c38cc8599fd203 (patch)
treeea9c74afa444d8b4ce10b71fc5028a10b7f7da06
parentc0541b52d6652f95dc966681ea72cfa0f8fddb77 (diff)
parentc3710ddd26195250bbebbb9bdc6970c313f684e4 (diff)
Merge pull request #8823 from ace20022/tp_jarvis
[tools][texturepacker] Fix gif decoding and packaging
-rw-r--r--project/BuildDependencies/scripts/0_package.list4
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp23
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp512
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GifHelper.h164
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/IDecoder.h4
5 files changed, 379 insertions, 328 deletions
diff --git a/project/BuildDependencies/scripts/0_package.list b/project/BuildDependencies/scripts/0_package.list
index b89826dab7..4ce1934db7 100644
--- a/project/BuildDependencies/scripts/0_package.list
+++ b/project/BuildDependencies/scripts/0_package.list
@@ -14,7 +14,7 @@ dnssd-541-win32.zip
doxygen-1.8.2-win32.7z
fontconfig-2.8.0-win32.7z
freetype-2.4.6-win32-3.7z
-giflib-5.1.0-win32.7z
+giflib-5.1.1-win32.7z
gnutls-3.2.3-win32.zip
jsonschemabuilder-1.0.0-win32-3.7z
libass-0.12.1-win32.7z
@@ -49,5 +49,5 @@ python-2.7.8-win32.7z
sqlite-3.8.6-win32-vc120.7z
swig-2.0.7-win32-1.7z
taglib-1.9.1-patched-win32-vc120.7z
-texturepacker-1.0.4-win32.7z
+texturepacker-1.0.5-win32.7z
tinyxml-2.6.2_3-win32-vc120.7z
diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
index 67e6d24389..f970793d02 100644
--- a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
+++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
@@ -34,26 +34,25 @@ bool GIFDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
GifHelper *gifImage = new GifHelper();
if (gifImage->LoadGif(filename.c_str()))
{
- std::vector<GifFrame> extractedFrames = gifImage->GetFrames();
+ auto extractedFrames = gifImage->GetFrames();
n = extractedFrames.size();
if (n > 0)
{
+ unsigned int height = gifImage->GetHeight();
+ unsigned int width = gifImage->GetWidth();
+ unsigned int pitch = gifImage->GetPitch();
+ unsigned int frameSize = pitch * height;
for (unsigned int i = 0; i < extractedFrames.size(); i++)
{
DecodedFrame frame;
- frame.rgbaImage.pixels = (char *)new char[extractedFrames[i].m_imageSize];
- memcpy(frame.rgbaImage.pixels, extractedFrames[i].m_pImage, extractedFrames[i].m_imageSize);
- frame.rgbaImage.height = extractedFrames[i].m_height;
- frame.rgbaImage.width = extractedFrames[i].m_width;
+ frame.rgbaImage.pixels = (char *)new char[frameSize];
+ memcpy(frame.rgbaImage.pixels, extractedFrames[i]->m_pImage, frameSize);
+ frame.rgbaImage.height = height;
+ frame.rgbaImage.width = width;
frame.rgbaImage.bbp = 32;
- frame.rgbaImage.pitch = extractedFrames[i].m_pitch;
-
- frame.delay = extractedFrames[i].m_delay;
- frame.disposal = extractedFrames[i].m_disposal;
- frame.x = extractedFrames[i].m_left;
- frame.y = extractedFrames[i].m_top;
-
+ frame.rgbaImage.pitch = pitch;
+ frame.delay = extractedFrames[i]->m_delay;
frames.frameList.push_back(frame);
}
diff --git a/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp b/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
index 45a5a5e784..d629844399 100644
--- a/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
+++ b/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
@@ -33,134 +33,134 @@ public:
unsigned int buffSize;
unsigned int readPosition;
- Gifreader() : buffer(NULL), buffSize(0), readPosition(0) {}
+ Gifreader() : buffer(nullptr), buffSize(0), readPosition(0) {}
};
-int ReadFromMemory(GifFileType* gif, GifByteType* gifbyte, int len)
-{
- unsigned int alreadyRead = ((Gifreader*)gif->UserData)->readPosition;
- unsigned int buffSizeLeft = ((Gifreader*)gif->UserData)->buffSize - alreadyRead;
- int readBytes = len;
-
- if (len <= 0)
- readBytes = 0;
-
- if ((unsigned int)len > buffSizeLeft)
- readBytes = buffSizeLeft;
-
- if (readBytes > 0)
- {
- unsigned char* src = ((Gifreader*)gif->UserData)->buffer + alreadyRead;
- memcpy(gifbyte, src, readBytes);
- ((Gifreader*)gif->UserData)->readPosition += readBytes;
- }
- return readBytes;
-}
-
int ReadFromVfs(GifFileType* gif, GifByteType* gifbyte, int len)
{
- CFile *gifFile = (CFile *)gif->UserData;
- return (int)gifFile->Read(gifbyte, len);
+ CFile *gifFile = static_cast<CFile*>(gif->UserData);
+ return gifFile->Read(gifbyte, len);
}
-
GifHelper::GifHelper() :
m_imageSize(0),
m_pitch(0),
m_loops(0),
m_numFrames(0),
m_filename(""),
- m_gif(NULL),
- m_hasBackground(false),
- m_pTemplate(NULL),
+ m_gif(nullptr),
+ m_pTemplate(nullptr),
m_isAnimated(-1)
{
- m_backColor = new COLOR();
- memset(m_backColor, 0, sizeof(COLOR));
- m_frames.clear();
+ m_gifFile = new CFile();
}
GifHelper::~GifHelper()
{
- int err;
-#if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
- DGifCloseFile(m_gif, &err);
+ Close(m_gif);
+ Release();
+ delete m_gifFile;
+}
+
+bool GifHelper::Open(GifFileType*& gif, void *dataPtr, InputFunc readFunc)
+{
+ int err = 0;
+#if GIFLIB_MAJOR == 5
+ gif = DGifOpen(dataPtr, readFunc, &err);
+#else
+ gif = DGifOpen(dataPtr, readFunc);
+ if (!gif)
+ err = GifLastError();
+#endif
+
+ if (!gif)
+ {
+ fprintf(stderr, "Gif::Open(): Could not open file %s. Reason: %s\n", m_filename.c_str(), GifErrorString(err));
+ return false;
+ }
+
+ return true;
+}
+
+void GifHelper::Close(GifFileType* gif)
+{
+ int err = 0;
+ int reason = 0;
+#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
+ err = DGifCloseFile(gif, &reason);
#else
- err = DGifCloseFile(m_gif);
+ err = DGifCloseFile(gif);
+#if GIFLIB_MAJOR < 5
+ reason = GifLastError();
#endif
- if (err == D_GIF_ERR_CLOSE_FAILED)
+ if (err == GIF_ERROR)
+ free(gif);
+#endif
+ if (err == GIF_ERROR)
{
- fprintf(stderr, "Gif::~Gif(): D_GIF_ERR_CLOSE_FAILED\n");
- free(m_gif);
+ fprintf(stderr, "GifHelper::Close(): closing file %s failed. Reason: %s\n", m_filename.c_str(), Reason(reason));
}
- Release();
- delete m_backColor;
+}
+
+const char* GifHelper::Reason(int reason)
+{
+ const char* err = GifErrorString(reason);
+ if (err)
+ return err;
+
+ return "unknown";
+
}
void GifHelper::Release()
{
delete[] m_pTemplate;
- m_pTemplate = NULL;
+ m_pTemplate = nullptr;
m_globalPalette.clear();
m_frames.clear();
}
-void GifHelper::ConvertColorTable(std::vector<COLOR> &dest, ColorMapObject* src, unsigned int size)
+void GifHelper::ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size)
{
for (unsigned int i = 0; i < size; ++i)
{
- COLOR c;
+ GifColor c;
c.r = src->Colors[i].Red;
c.g = src->Colors[i].Green;
c.b = src->Colors[i].Blue;
- c.x = 0xff;
+ c.a = 0xff;
dest.push_back(c);
}
}
-bool GifHelper::LoadGifMetaData(GifFileType* file)
+bool GifHelper::LoadGifMetaData(GifFileType* gif)
{
- if (DGifSlurp(m_gif) == GIF_ERROR)
- {
-#if GIFLIB_MAJOR >= 5
- const char* error = GifErrorString(m_gif->Error);
- if (error)
- fprintf(stderr, "Gif::LoadGif(): Could not read file %s - %s\n", m_filename.c_str(), error);
-#else
- int error = GifLastError();
- if (error)
- fprintf(stderr, "Gif::LoadGif(): Could not read file %s - %d\n", m_filename.c_str(), error);
-#endif
- else
- fprintf(stderr, "Gif::LoadGif(): Could not read file %s (reasons unknown)\n", m_filename.c_str());
+ if (!Slurp(gif))
return false;
- }
- m_height = m_gif->SHeight;
- m_width = m_gif->SWidth;
+ m_height = gif->SHeight;
+ m_width = gif->SWidth;
if (!m_height || !m_width)
{
fprintf(stderr, "Gif::LoadGif(): Zero sized image. File %s\n", m_filename.c_str());
return false;
}
- m_numFrames = m_gif->ImageCount;
+ m_numFrames = gif->ImageCount;
if (m_numFrames > 0)
{
-#if GIFLIB_MAJOR >= 5
- GraphicsControlBlock GCB;
- DGifSavedExtensionToGCB(m_gif, 0, &GCB);
- ExtensionBlock* extb = m_gif->SavedImages[0].ExtensionBlocks;
+ ExtensionBlock* extb = gif->SavedImages[0].ExtensionBlocks;
if (extb && extb->Function == APPLICATION_EXT_FUNC_CODE)
{
// Read number of loops
- if(++extb && extb->Function == CONTINUE_EXT_FUNC_CODE)
+ 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);
}
}
-#endif
}
else
{
@@ -168,7 +168,7 @@ bool GifHelper::LoadGifMetaData(GifFileType* file)
return false;
}
- m_pitch = m_width * sizeof(COLOR);
+ m_pitch = m_width * sizeof(GifColor);
m_imageSize = m_pitch * m_height;
unsigned long memoryUsage = m_numFrames * m_imageSize;
if (memoryUsage > GIF_MAX_MEMORY)
@@ -183,31 +183,28 @@ bool GifHelper::LoadGifMetaData(GifFileType* file)
bool GifHelper::LoadGifMetaData(const char* file)
{
- int err = 0;
-
- if (m_gifFile.Open(file))
-#if GIFLIB_MAJOR >= 5
- m_gif = DGifOpen(&m_gifFile, ReadFromVfs, &err);
-#else
- m_gif = DGifOpen(&m_gifFile, ReadFromVfs);
-#endif
+ m_gifFile->Close();
+ if (!m_gifFile->Open(file) || !Open(m_gif, m_gifFile, ReadFromVfs))
+ return false;
- if (!m_gif)
+ return LoadGifMetaData(m_gif);
+}
+
+bool GifHelper::Slurp(GifFileType* gif)
+{
+ if (DGifSlurp(gif) == GIF_ERROR)
{
-#if GIFLIB_MAJOR >= 5
- const char* error = GifErrorString(err);
- if (error)
- fprintf(stderr, "Gif::LoadGif(): Could not open file %s - %s\n", m_filename.c_str(), error);
+ int reason = 0;
+#if GIFLIB_MAJOR == 5
+ reason = gif->Error;
#else
- int error = GifLastError();
- if (error)
- fprintf(stderr, "Gif::LoadGif(): Could not open file %s - %d\n", m_filename.c_str(), error);
+ reason = GifLastError();
#endif
- else
- fprintf(stderr, "Gif::LoadGif(): Could not open file %s (reasons unknown)\n", m_filename.c_str());
+ fprintf(stderr, "Gif::LoadGif(): Could not read file %s. Reason: %s\n", m_filename.c_str(), GifErrorString(reason));
return false;
}
- return LoadGifMetaData(m_gif);
+
+ return true;
}
bool GifHelper::LoadGif(const char* file)
@@ -220,7 +217,19 @@ bool GifHelper::LoadGif(const char* file)
{
InitTemplateAndColormap();
- return ExtractFrames(m_numFrames);
+ int extractedFrames = ExtractFrames(m_numFrames);
+ if (extractedFrames < 0)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Could not extract any frame. File %s\n", m_filename.c_str());
+ return false;
+ }
+ else if (extractedFrames < (int)m_numFrames)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Could only extract %d/%d frames. File %s\n", extractedFrames, m_numFrames, m_filename.c_str());
+ m_numFrames = extractedFrames;
+ }
+
+ return true;
}
catch (std::bad_alloc& ba)
{
@@ -230,40 +239,6 @@ bool GifHelper::LoadGif(const char* file)
}
}
-bool GifHelper::IsAnimated(const char* file)
-{
- if (m_isAnimated < 0)
- {
- m_isAnimated = 0;
-
- GifFileType *gif = NULL;
- FILE *gifFile;
- int err = 0;
- gifFile = fopen(file, "rb");
- if (gifFile != NULL)
- {
-#if GIFLIB_MAJOR >= 5
- gif = DGifOpen(&gifFile, ReadFromVfs, &err);
-#else
- gif = DGifOpen(&gifFile, ReadFromVfs);
-#endif
- }
-
- if (gif)
- {
- if (DGifSlurp(gif) && gif->ImageCount > 1)
- m_isAnimated = 1;
-#if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
- DGifCloseFile(gif, NULL);
-#else
- DGifCloseFile(gif);
-#endif
- fclose(gifFile);
- }
- }
- return m_isAnimated > 0;
-}
-
void GifHelper::InitTemplateAndColormap()
{
m_pTemplate = new unsigned char[m_imageSize];
@@ -273,155 +248,166 @@ void GifHelper::InitTemplateAndColormap()
{
m_globalPalette.clear();
ConvertColorTable(m_globalPalette, m_gif->SColorMap, m_gif->SColorMap->ColorCount);
-
- // draw the canvas
- *m_backColor = m_globalPalette[m_gif->SBackGroundColor];
- m_hasBackground = true;
-
- for (unsigned int i = 0; i < m_height * m_width; ++i)
- {
- unsigned char *dest = m_pTemplate + (i *sizeof(COLOR));
- memcpy(dest, m_backColor, sizeof(COLOR));
- }
}
else
m_globalPalette.clear();
}
-bool GifHelper::gcbToFrame(GifFrame &frame, unsigned int imgIdx)
+bool GifHelper::GcbToFrame(GifFrame &frame, unsigned int imgIdx)
{
int transparent = -1;
frame.m_delay = 0;
frame.m_disposal = 0;
-#if GIFLIB_MAJOR >= 5
+
if (m_gif->ImageCount > 0)
{
+#if GIFLIB_MAJOR == 5
GraphicsControlBlock gcb;
if (!DGifSavedExtensionToGCB(m_gif, imgIdx, &gcb))
{
- const char* error = GifErrorString(m_gif->Error);
- if (error)
- fprintf(stderr, "Gif::ExtractFrames(): Could not read GraphicsControlBlock of frame %d - %s\n", imgIdx, error);
- else
- fprintf(stderr, "Gif::ExtractFrames(): Could not read GraphicsControlBlock of frame %d (reasons unknown)\n", imgIdx);
+ fprintf(stderr, "Gif::GcbToFrame(): Could not read GraphicsControlBlock of frame %d in file %s\n",
+ imgIdx, m_filename.c_str()), GifErrorString(m_gif->Error);
return false;
}
// delay in ms
frame.m_delay = gcb.DelayTime * 10;
frame.m_disposal = gcb.DisposalMode;
transparent = gcb.TransparentColor;
- }
#else
- if (m_gif->ImageCount > 0)
- {
ExtensionBlock* extb = m_gif->SavedImages[imgIdx].ExtensionBlocks;
while (extb && extb->Function != GRAPHICS_EXT_FUNC_CODE)
extb++;
- if (extb)
+ if (!extb || extb->ByteCount != 4)
+ {
+ fprintf(stderr, "Gif::GcbToFrame() : Could not read GraphicsControlBlock of frame %d in file %s\n",
+ imgIdx, m_filename.c_str());
+ return false;
+ }
+ else
{
- frame.m_delay = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]) * 10;
- frame.m_disposal = (extb->Bytes[0] >> 2) & 0x7;
- if (extb->Bytes[0] & 0x1)
- transparent = extb->Bytes[3];
+ 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<uint8_t>(extb->Bytes[3]);
+ }
else
transparent = -1;
}
- }
+
#endif
+ }
if (transparent >= 0 && (unsigned)transparent < frame.m_palette.size())
- frame.m_palette[transparent].x = 0;
+ frame.m_palette[transparent].a = 0;
return true;
}
-bool GifHelper::ExtractFrames(unsigned int count)
+int GifHelper::ExtractFrames(unsigned int count)
{
if (!m_gif)
- return false;
+ return -1;
if (!m_pTemplate)
{
fprintf(stderr, "Gif::ExtractFrames(): No frame template available\n");
- return false;
+ return -1;
}
+ int extracted = 0;
for (unsigned int i = 0; i < count; i++)
{
- GifFrame frame;
+ FramePtr frame(new GifFrame);
SavedImage savedImage = m_gif->SavedImages[i];
GifImageDesc imageDesc = m_gif->SavedImages[i].ImageDesc;
- frame.m_height = imageDesc.Height;
- frame.m_width = imageDesc.Width;
- frame.m_top = imageDesc.Top;
- frame.m_left = imageDesc.Left;
- frame.m_pitch = m_pitch;
-
- if (frame.m_top + frame.m_height > m_height || frame.m_left + frame.m_width > m_width
- || !frame.m_width || !frame.m_height)
+ frame->m_height = imageDesc.Height;
+ frame->m_width = imageDesc.Width;
+ frame->m_top = imageDesc.Top;
+ frame->m_left = imageDesc.Left;
+
+ if (frame->m_top + frame->m_height > m_height || frame->m_left + frame->m_width > m_width
+ || !frame->m_width || !frame->m_height
+ || frame->m_width > m_width || frame->m_height > m_height)
{
- fprintf(stderr, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d)\n",
- frame.m_width, frame.m_height, frame.m_left, frame.m_top, m_width, m_height);
- return false;
+ fprintf(stderr, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d), skip it\n",
+ frame->m_width, frame->m_height, frame->m_left, frame->m_top, m_width, m_height);
+ continue;
}
if (imageDesc.ColorMap)
{
- frame.m_palette.clear();
- ConvertColorTable(frame.m_palette, imageDesc.ColorMap, imageDesc.ColorMap->ColorCount);
- // TODO save a backup of the palette for frames without a table in case there's no gloabl table.
+ frame->m_palette.clear();
+ ConvertColorTable(frame->m_palette, imageDesc.ColorMap, imageDesc.ColorMap->ColorCount);
+ // TODO save a backup of the palette for frames without a table in case there's no global table.
}
else if (m_gif->SColorMap)
{
- frame.m_palette = m_globalPalette;
+ frame->m_palette = m_globalPalette;
+ }
+ else
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): No color map found for frame %d, skip it\n", i);
+ continue;
}
// fill delay, disposal and transparent color into frame
- if (!gcbToFrame(frame, i))
- return false;
+ if (!GcbToFrame(*frame, i))
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Corrupted Graphics Control Block for frame %d, skip it\n", i);
+ continue;
+ }
- frame.m_pImage = new unsigned char[m_imageSize];
- frame.m_imageSize = m_imageSize;
- memcpy(frame.m_pImage, m_pTemplate, m_imageSize);
+ frame->m_pImage = new unsigned char[m_imageSize];
+ frame->m_imageSize = m_imageSize;
+ memcpy(frame->m_pImage, m_pTemplate, m_imageSize);
- ConstructFrame(frame, savedImage.RasterBits);
+ ConstructFrame(*frame, savedImage.RasterBits);
- if(!PrepareTemplate(frame))
- return false;
+ if (!PrepareTemplate(*frame))
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Could not prepare template after frame %d, skip it\n", i);
+ continue;
+ }
+ extracted++;
m_frames.push_back(frame);
}
- return true;
+ return extracted;
}
void GifHelper::ConstructFrame(GifFrame &frame, const unsigned char* src) const
{
+ size_t paletteSize = frame.m_palette.size();
+
for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
{
- unsigned char *to = frame.m_pImage + (dest_y * m_pitch) + (frame.m_left * sizeof(COLOR));
+ unsigned char *to = frame.m_pImage + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
const unsigned char *from = src + (src_y * frame.m_width);
for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
{
- COLOR col = frame.m_palette[*from++];
- if (col.x != 0)
- {
- *to++ = col.b;
- *to++ = col.g;
- *to++ = col.r;
- *to++ = col.x;
- }
- else
+ unsigned char index = *from++;
+
+ if (index >= paletteSize)
{
- to += 4;
+ fprintf(stderr, "Gif::ConstructFrame(): Pixel (%d,%d) has no valid palette entry, skip it\n", src_x, src_y);
+ continue;
}
+
+ GifColor col = frame.m_palette[index];
+ if (col.a != 0)
+ memcpy(to, &col, sizeof(GifColor));
+
+ to += 4;
}
}
}
-bool GifHelper::PrepareTemplate(const GifFrame &frame)
+bool GifHelper::PrepareTemplate(GifFrame &frame)
{
-#if GIFLIB_MAJOR >= 5
switch (frame.m_disposal)
{
/* No disposal specified. */
@@ -431,140 +417,92 @@ bool GifHelper::PrepareTemplate(const GifFrame &frame)
memcpy(m_pTemplate, frame.m_pImage, m_imageSize);
break;
- /* Set area too background color */
+ /*
+ Clear the frame's area to transparency.
+ The disposal names is misleading. Do not restore to the background color because
+ this part of the specification is ignored by all browsers/image viewers.
+ */
case DISPOSE_BACKGROUND:
- {
- if (!m_hasBackground)
- {
- fprintf(stderr, "Gif::PrepareTemplate(): Disposal method DISPOSE_BACKGROUND encountered, but the gif has no background.\n");
- return false;
- }
- SetFrameAreaToBack(m_pTemplate, frame);
- break;
- }
- /* Restore to previous content */
+ {
+ ClearFrameAreaToTransparency(m_pTemplate, frame);
+ break;
+ }
+ /* 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())
{
- bool valid = false;
+ frame.m_disposal = DISPOSE_DO_NOT;
+ return PrepareTemplate(frame);
+ }
- for (int i = m_frames.size() - 1 ; i >= 0; --i)
- {
- if (m_frames[i].m_disposal != DISPOSE_PREVIOUS)
- {
- memcpy(m_pTemplate, m_frames[i].m_pImage, m_imageSize);
- valid = true;
- break;
- }
- }
- if (!valid)
+ bool valid = false;
+
+ for (int i = m_frames.size() - 1; i >= 0; --i)
+ {
+ if (m_frames[i]->m_disposal != DISPOSE_PREVIOUS)
{
- fprintf(stderr, "Gif::PrepareTemplate(): Disposal method DISPOSE_PREVIOUS encountered, but could not find a suitable frame.\n");
- return false;
+ memcpy(m_pTemplate, m_frames[i]->m_pImage, m_imageSize);
+ valid = true;
+ break;
}
- break;
}
- default:
+ if (!valid)
{
- fprintf(stderr, "Gif::PrepareTemplate(): Unknown disposal method: %d\n", frame.m_disposal);
+ fprintf(stderr, "Gif::PrepareTemplate(): Disposal method DISPOSE_PREVIOUS encountered, but could not find a suitable frame.\n");
return false;
}
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Gif::PrepareTemplate(): Unknown disposal method: %d. Using DISPOSAL_UNSPECIFIED, the animation might be wrong now.\n", frame.m_disposal);
+ frame.m_disposal = DISPOSAL_UNSPECIFIED;
+ return PrepareTemplate(frame);
+ }
}
-#endif
return true;
}
-void GifHelper::SetFrameAreaToBack(unsigned char* dest, const GifFrame &frame)
+void GifHelper::ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame)
{
for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
{
- unsigned char *to = dest + (dest_y * m_pitch) + (frame.m_left * sizeof(COLOR));
+ unsigned char *to = dest + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
{
- memcpy(to, m_backColor, sizeof(COLOR));
- to += 4;
+ to += 3;
+ *to++ = 0;
}
}
}
-bool GifHelper::LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize, unsigned int width, unsigned int height)
-{
- if (!buffer || !bufSize || !width || !height)
- return false;
-
- Gifreader reader;
- reader.buffer = buffer;
- reader.buffSize = bufSize;
-
- int err = 0;
-#if GIFLIB_MAJOR >= 5
- m_gif = DGifOpen((void *)&reader, (InputFunc)&ReadFromMemory, &err);
-#else
- m_gif = DGifOpen((void *)&reader, (InputFunc)&ReadFromMemory);
-#endif
- if (!m_gif)
- {
-#if GIFLIB_MAJOR >= 5
- const char* error = GifErrorString(err);
- if (error)
- fprintf(stderr, "Gif::LoadImageFromMemory(): Could not open gif from memory - %s\n", error);
-#else
- int error = GifLastError();
- if (error)
- fprintf(stderr, "Gif::LoadImageFromMemory(): Could not open gif from memory - %d\n", error);
-#endif
- else
- fprintf(stderr, "Gif::LoadImageFromMemory(): Could not open gif from memory (reasons unknown)\n");
- return false;
- }
-
- if (!LoadGifMetaData(m_gif))
- return false;
-
- m_originalWidth = m_width;
- m_originalHeight = m_height;
-
- try
- {
- InitTemplateAndColormap();
-
- if (!ExtractFrames(m_numFrames))
- return false;
- }
- catch (std::bad_alloc& ba)
- {
- fprintf(stderr, "Gif::LoadImageFromMemory(): Out of memory while extracting gif frames - %s\n", ba.what());
- Release();
- return false;
- }
-
- return true;
-}
-
GifFrame::GifFrame() :
- m_pImage(NULL),
+ m_pImage(nullptr),
m_delay(0),
m_imageSize(0),
m_height(0),
m_width(0),
m_top(0),
m_left(0),
- m_disposal(0),
- m_transparent(0),
- m_pitch(0)
+ m_disposal(0)
{}
GifFrame::GifFrame(const GifFrame& src) :
- m_pImage(NULL),
+ m_pImage(nullptr),
m_delay(src.m_delay),
m_imageSize(src.m_imageSize),
m_height(src.m_height),
m_width(src.m_width),
m_top(src.m_top),
m_left(src.m_left),
- m_disposal(src.m_disposal),
- m_transparent(src.m_transparent),
- m_pitch(src.m_pitch)
+ m_disposal(src.m_disposal)
{
if (src.m_pImage)
{
@@ -581,5 +519,5 @@ GifFrame::GifFrame(const GifFrame& src) :
GifFrame::~GifFrame()
{
delete[] m_pImage;
- m_pImage = NULL;
+ m_pImage = nullptr;
}
diff --git a/tools/depends/native/TexturePacker/src/decoder/GifHelper.h b/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
index dae24589e0..02fe25bbb4 100644
--- a/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
+++ b/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
@@ -21,13 +21,36 @@
#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 COLOR { unsigned char b, g, r, x; }; // Windows GDI expects 4bytes per color
+struct GifColor
+{
+ uint8_t b, g, r, a;
+};
#pragma pack()
class CFile;
@@ -39,12 +62,13 @@ public:
GifFrame();
virtual ~GifFrame();
- void Release();
-
- GifFrame(const GifFrame& src);
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;
@@ -52,10 +76,7 @@ public:
unsigned int m_width;
unsigned int m_pitch;
unsigned int m_imageSize;
-
-private:
-
- std::vector<COLOR> m_palette;
+ std::vector<GifColor> m_palette;
int m_transparent;
};
@@ -64,22 +85,24 @@ private:
class GifHelper
{
friend class GifFrame;
+
+ typedef std::shared_ptr<GifFrame> FramePtr;
+
public:
GifHelper();
virtual ~GifHelper();
- bool LoadGifMetaData(const char* file);
+
bool LoadGif(const char* file);
- virtual bool LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize, unsigned int width, unsigned int height);
- //virtual bool Decode(const unsigned char *pixels, unsigned int pitch, unsigned int format);
- bool IsAnimated(const char* file);
- std::vector<GifFrame>& GetFrames() { return m_frames; }
+ 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<GifFrame> m_frames;
+ std::vector<FramePtr> m_frames;
unsigned int m_imageSize;
unsigned int m_pitch;
unsigned int m_loops;
@@ -88,11 +111,11 @@ private:
std::string m_filename;
GifFileType* m_gif;
bool m_hasBackground;
- COLOR* m_backColor;
- std::vector<COLOR> m_globalPalette;
+ GifColor* m_backColor;
+ std::vector<GifColor> m_globalPalette;
unsigned char* m_pTemplate;
int m_isAnimated;
- CFile m_gifFile;
+ CFile* m_gifFile;
unsigned int m_width;
unsigned int m_height;
@@ -101,13 +124,106 @@ private:
unsigned int m_orientation;
bool m_hasAlpha;
+ 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* file);
- static void ConvertColorTable(std::vector<COLOR> &dest, ColorMapObject* src, unsigned int size);
- bool gcbToFrame(GifFrame &frame, unsigned int imgIdx);
- bool ExtractFrames(unsigned int count);
- void SetFrameAreaToBack(unsigned char* dest, const GifFrame &frame);
+ 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(const GifFrame &frame);
+ 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
};
diff --git a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
index def1eca8b1..25363c7be1 100644
--- a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
+++ b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
@@ -37,10 +37,8 @@ public:
class DecodedFrame
{
public:
- DecodedFrame() : x(0), y(0), disposal(0), delay(0) { }
+ DecodedFrame() : delay(0) { }
RGBAImage rgbaImage; /* rgbaimage for this frame */
- int x, y; /* Frame offset position */
- int disposal; /* Disposal code */
int delay; /* Frame delay in ms */
};