#include "gif_player.h" #include #include #include #include "hid_handler.h" #pragma comment(lib,"Gdiplus.lib") using namespace Gdiplus; DGifPlayer gif_player; void ConvertBGRAtoRGBA(unsigned char* data, int width, int height) { for (int i = 0; i < width * height; i++) { unsigned char* px = &data[i * 4]; unsigned char b = px[0]; unsigned char g = px[1]; unsigned char r = px[2]; unsigned char a = px[3]; px[0] = r; px[1] = g; px[2] = b; px[3] = a; } } bool DGifPlayer::Load(const std::string& path) { GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); std::wstring wpath(path.begin(), path.end()); Image gif(wpath.c_str()); if (gif.GetLastStatus() != Ok) { hid_handler.log << "Failed to load gif" << std::endl; return false; } width = gif.GetWidth(); height = gif.GetHeight(); GUID dimension = FrameDimensionTime; UINT frameCount = gif.GetFrameCount(&dimension); // get frame delays UINT size = gif.GetPropertyItemSize(PropertyTagFrameDelay); if (size <= 0) { hid_handler.log << "Failed to load gif properties (0x1)" << std::endl; return false; } PropertyItem* prop = (PropertyItem*)malloc(size); if (prop == nullptr) { hid_handler.log << "Failed to load gif properties (0x2)" << std::endl; return false; } if (gif.GetPropertyItem(PropertyTagFrameDelay, size, prop) != Ok) { hid_handler.log << "Failed to load gif properties (0x3)" << std::endl; return false; } int frameSize = width * height * 4; for (UINT i = 0; i < frameCount; i++) { gif.SelectActiveFrame(&dimension, i); Bitmap bmp(width, height, PixelFormat32bppARGB); Graphics g(&bmp); g.DrawImage(&gif, 0, 0); BitmapData data; Rect rect(0, 0, width, height); bmp.LockBits(&rect, ImageLockModeRead, PixelFormat32bppARGB, &data); unsigned char* frame = new unsigned char[frameSize]; memcpy(frame, data.Scan0, frameSize); bmp.UnlockBits(&data); // Convert to RGBA for rendering correct color channels ConvertBGRAtoRGBA(frame, width, height); frames.push_back(frame); int delay = ((UINT*)prop->value)[i]; delays.push_back(delay > 0 ? delay : 10); } free(prop); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frames[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); return true; } void DGifPlayer::Update(float deltaTime) { if (frames.empty()) { return; } timer += deltaTime; float delaySec = delays[currentFrame] * 0.01f; if (timer >= delaySec) { timer = 0.0f; currentFrame++; if (currentFrame >= frames.size()) { currentFrame = 0; } glBindTexture(GL_TEXTURE_2D, texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frames[currentFrame]); } } void DGifPlayer::Destroy() { for (auto f : frames) { delete[] f; } frames.clear(); delays.clear(); if (texture) { glDeleteTextures(1, &texture); } }