Created
August 17, 2017 08:47
-
-
Save xylcbd/41150999ec98f95f3947d58220bf5ea3 to your computer and use it in GitHub Desktop.
load gif to opencv mat, using giflib & opencv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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