aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarry Jeffery <harry@exec64.co.uk>2015-11-09 12:18:18 +0000
committerHarry Jeffery <harry@exec64.co.uk>2015-11-09 12:18:18 +0000
commitcbf161ff5ecb71ee65f295aeb7c7678ee36962ae (patch)
treebb7298969e9438a2e12dbd6925e3b6cf2a1811f7
parent9c3ae1d958cb87396f94820bf9ed4a812667914d (diff)
downloadimv-cbf161ff5ecb71ee65f295aeb7c7678ee36962ae.tar.gz
Add step by step gif animation support
-rw-r--r--main.c128
1 files changed, 111 insertions, 17 deletions
diff --git a/main.c b/main.c
index 7ccedcc..9300ab2 100644
--- a/main.c
+++ b/main.c
@@ -44,10 +44,12 @@ struct {
} g_path = {NULL,NULL,NULL,1,1};
struct {
- FIBITMAP *img;
+ FIMULTIBITMAP *mbmp;
+ FIBITMAP *frame;
SDL_Texture *tex;
int width, height;
-} g_img = {NULL,NULL,0,0};
+ int cur_frame, next_frame, num_frames;
+} g_img = {NULL,NULL,NULL,0,0,0,0,0};
void toggle_fullscreen()
{
@@ -138,22 +140,16 @@ void prev_path()
g_path.dir = -1;
}
-void load_image(const char* path)
+void render_image(FIBITMAP *image)
{
- FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(path,0);
- FIBITMAP *image = FreeImage_Load(fmt, path, 0);
- FreeImage_FlipVertical(image);
-
- if(g_img.img) {
- FreeImage_Unload(g_img.img);
+ if(g_img.frame) {
+ FreeImage_Unload(g_img.frame);
}
- g_img.img = FreeImage_ConvertTo32Bits(image);
- FreeImage_Unload(image);
-
- g_img.width = FreeImage_GetWidth(g_img.img);
- g_img.height = FreeImage_GetHeight(g_img.img);
+ g_img.frame = FreeImage_ConvertTo32Bits(image);
+ g_img.width = FreeImage_GetWidth(g_img.frame);
+ g_img.height = FreeImage_GetHeight(g_img.frame);
- char* pixels = (char*)FreeImage_GetBits(g_img.img);
+ char* pixels = (char*)FreeImage_GetBits(g_img.frame);
if(g_img.tex) {
SDL_DestroyTexture(g_img.tex);
@@ -164,6 +160,100 @@ void load_image(const char* path)
g_img.width, g_img.height);
SDL_Rect area = {0,0,g_img.width,g_img.height};
SDL_UpdateTexture(g_img.tex, &area, pixels, 4 * g_img.width);
+ g_view.redraw = 1;
+}
+
+void next_frame()
+{
+ FITAG *tag = NULL;
+ char disposal_method = 0;
+
+ g_img.cur_frame = g_img.next_frame;
+ g_img.next_frame = (g_img.cur_frame + 1) % g_img.num_frames;
+ FIBITMAP *frame = FreeImage_LockPage(g_img.mbmp, g_img.cur_frame);
+ FIBITMAP *frame32 = FreeImage_ConvertTo32Bits(frame);
+ FreeImage_FlipVertical(frame32);
+
+ //First frame is always going to use the raw frame
+ if(g_img.cur_frame > 0) {
+ FreeImage_GetMetadata(FIMD_ANIMATION, frame, "DisposalMethod", &tag);
+ if(FreeImage_GetTagValue(tag)) {
+ disposal_method = *(char*)FreeImage_GetTagValue(tag);
+ }
+ }
+
+ FreeImage_UnlockPage(g_img.mbmp, frame, 0);
+
+ switch(disposal_method) {
+ case 0: /*nothing specified, just use the raw frame*/
+ render_image(frame32);
+ break;
+ case 1: /*composite over previous frame*/
+ if(g_img.frame && g_img.cur_frame > 0) {
+ FIBITMAP *bg_frame = FreeImage_ConvertTo24Bits(g_img.frame);
+ FIBITMAP *comp = FreeImage_Composite(frame32, 1, NULL, bg_frame);
+ FreeImage_Unload(bg_frame);
+ render_image(comp);
+ FreeImage_Unload(comp);
+ } else {
+ //No previous frame, just render directly
+ render_image(frame32);
+ }
+ break;
+ case 2: /*set to background, composite over that*/
+ fprintf(stdout, "tried to set to bg\n");
+ break;
+ case 3: /*restore to previous content*/
+ fprintf(stdout, "restore to content\n");
+ break;
+ }
+ FreeImage_Unload(frame32);
+}
+
+void load_gif(const char* path)
+{
+
+ FIMULTIBITMAP *gif =
+ FreeImage_OpenMultiBitmap(FIF_GIF, path,
+ /* don't create */ 0,
+ /* read only */ 1,
+ /* keep in memory */ 1,
+ /* flags */ GIF_LOAD256);
+
+ if(!gif) {
+ return;
+ }
+
+ g_img.mbmp = gif;
+ g_img.num_frames = FreeImage_GetPageCount(gif);
+ g_img.cur_frame = 0;
+ g_img.next_frame = 0;
+
+ next_frame();
+}
+
+void load_image(const char* path)
+{
+ if(g_img.mbmp) {
+ FreeImage_CloseMultiBitmap(g_img.mbmp, 0);
+ g_img.mbmp = NULL;
+ }
+
+ FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(path,0);
+ if(fmt == FIF_GIF) {
+ load_gif(path);
+ return;
+ }
+
+ g_img.num_frames = 0;
+ g_img.cur_frame = 0;
+ g_img.next_frame = 0;
+
+ FIBITMAP *image = FreeImage_Load(fmt, path, 0);
+ FIBITMAP *frame = FreeImage_ConvertTo32Bits(image);
+ FreeImage_FlipVertical(frame);
+ render_image(frame);
+ FreeImage_Unload(image);
}
int main(int argc, char** argv)
@@ -241,6 +331,7 @@ int main(int argc, char** argv)
case SDLK_l: move_view(-50, 0); break;
case SDLK_x: remove_current_path(); break;
case SDLK_f: toggle_fullscreen(); break;
+ case SDLK_PERIOD: next_frame(); break;
}
break;
case SDL_MOUSEWHEEL:
@@ -297,8 +388,11 @@ int main(int argc, char** argv)
SDL_Delay(10);
}
- if(g_img.img) {
- FreeImage_Unload(g_img.img);
+ if(g_img.mbmp) {
+ FreeImage_CloseMultiBitmap(g_img.mbmp, 0);
+ }
+ if(g_img.frame) {
+ FreeImage_Unload(g_img.frame);
}
if(g_img.tex) {
SDL_DestroyTexture(g_img.tex);