Skip to content

Instantly share code, notes, and snippets.

@xylcbd
Created August 17, 2017 08:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save xylcbd/41150999ec98f95f3947d58220bf5ea3 to your computer and use it in GitHub Desktop.
Save xylcbd/41150999ec98f95f3947d58220bf5ea3 to your computer and use it in GitHub Desktop.
load gif to opencv mat, using giflib & opencv
//std headers
#include <fstream>
#include <iostream>
//lib headers
#include <gif_lib.h>
#define USING_NEW_GIF_LIB defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
cv::Mat imread_gif(const std::string& filename, const int flags)
{
std::ifstream stream(filename, std::ios::in | std::ios::binary);
std::vector<unsigned char> contents((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
return imdecode_gif(&contents[0], contents.size(), flags);
}
struct DataDesc
{
const unsigned char* buffer;
int len;
int pos;
};
static int gif_data_cb(GifFileType* f, GifByteType* buffer, int size)
{
DataDesc* user_data = (DataDesc*)f->UserData;
if (size > user_data->len)
{
size = user_data->len;
}
memcpy(buffer, user_data->buffer + user_data->pos, size);
user_data->pos += size;
return size;
}
#if USING_NEW_GIF_LIB
#else
static const char* GifErrorString(int error)
{
return "unknown error.";
}
#endif
cv::Mat imdecode_gif(const unsigned char* buffer, const size_t len, const int flags)
{
cv::Mat result;
int ret = 0;
int error = 0;
DataDesc data_desc;
data_desc.buffer = buffer;
data_desc.len = len;
data_desc.pos = 0;
#if USING_NEW_GIF_LIB
GifFileType* f = DGifOpen(&data_desc, gif_data_cb, &error);
#define CLOSE_GIF(f, error) DGifCloseFile(f, &error);
#else
GifFileType* f = DGifOpen(&data_desc, gif_data_cb);
#define CLOSE_GIF(f, error) DGifCloseFile(f);
#endif //USING_NEW_GIF_LIB
if (!f || error != 0)
{
std::cout << "gif decode error: " << GifErrorString(error) << std::endl;
return result;
}
ret = DGifSlurp(f);
if (ret != GIF_OK)
{
std::cout << "gif decode error: " << GifErrorString(error) << std::endl;
CLOSE_GIF(f, &error);
return result;
}
const int width = f->Image.Width;
const int height = f->Image.Height;
if (f->ImageCount <= 0 || width <= 0 || height<= 0)
{
std::cout << "gif had no any frames."<< std::endl;
CLOSE_GIF(f, &error);
return result;
}
result = cv::Mat(cv::Size(width, height), CV_8UC3);
const ColorMapObject* ColorMap = (f->Image.ColorMap ? f->Image.ColorMap : f->SColorMap);
const unsigned char* src = f->SavedImages[0].RasterBits;
for (int i = 0; i < height; i++)
{
unsigned char* dst = result.data + i * result.step[0];
int loc = width * i;
for (int j = 0; j < width; j++)
{
GifColorType* ColorMapEntry = &(ColorMap->Colors[*(src + loc + j)]);
//BGR
*dst++ = ColorMapEntry->Blue;
*dst++ = ColorMapEntry->Green;
*dst++ = ColorMapEntry->Red;
}
}
CLOSE_GIF(f, &error);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment