Skip to content

Instantly share code, notes, and snippets.

@urraka
Last active January 21, 2024 00:20
Show Gist options
  • Save urraka/685d9a6340b26b830d49 to your computer and use it in GitHub Desktop.
Save urraka/685d9a6340b26b830d49 to your computer and use it in GitHub Desktop.
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define STBI_ONLY_PNG
#define STBI_ONLY_JPEG
#define STBI_ONLY_BMP
#define STBI_ONLY_GIF
#include "stb_image.h"
#include "stb_image_write.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct gif_result_t {
int delay;
unsigned char *data;
struct gif_result_t *next;
} gif_result;
STBIDEF unsigned char *stbi_xload(char const *filename, int *x, int *y, int *frames)
{
FILE *f;
stbi__context s;
unsigned char *result = 0;
if (!(f = stbi__fopen(filename, "rb")))
return stbi__errpuc("can't fopen", "Unable to open file");
stbi__start_file(&s, f);
if (stbi__gif_test(&s))
{
int c;
stbi__gif g;
gif_result head;
gif_result *prev = 0, *gr = &head;
memset(&g, 0, sizeof(g));
memset(&head, 0, sizeof(head));
*frames = 0;
while (gr->data = stbi__gif_load_next(&s, &g, &c, 4))
{
if (gr->data == (unsigned char*)&s)
{
gr->data = 0;
break;
}
if (prev) prev->next = gr;
gr->delay = g.delay;
prev = gr;
gr = (gif_result*) stbi__malloc(sizeof(gif_result));
memset(gr, 0, sizeof(gif_result));
++(*frames);
}
STBI_FREE(g.out);
if (gr != &head)
STBI_FREE(gr);
if (*frames > 0)
{
*x = g.w;
*y = g.h;
}
result = head.data;
if (*frames > 1)
{
unsigned int size = 4 * g.w * g.h;
unsigned char *p = 0;
result = (unsigned char*)stbi__malloc(*frames * (size + 2));
gr = &head;
p = result;
while (gr)
{
prev = gr;
memcpy(p, gr->data, size);
p += size;
*p++ = gr->delay & 0xFF;
*p++ = (gr->delay & 0xFF00) >> 8;
gr = gr->next;
STBI_FREE(prev->data);
if (prev != &head) STBI_FREE(prev);
}
}
}
else
{
result = stbi__load_main(&s, x, y, frames, 4);
*frames = !!result;
}
fclose(f);
return result;
}
#ifdef __cplusplus
}
#endif
@Platforming-Mayhem
Copy link

Platforming-Mayhem commented Nov 21, 2023

image
This is how you allow vertical flipping for the gifs :)

@urraka
Copy link
Author

urraka commented Nov 22, 2023

Hey @Platforming-Mayhem, looks like you got it working, good to know!

By the way, that last line you're highlighting looks suspicious to me. Isn't stbi_set_flip_vertically_on_load a function? My C/C++ is rusty but I think that might be interpreting it as a pointer and just testing that it's not zero, so stbi__vertical_flip_slices is always called.

@Platforming-Mayhem
Copy link

@urraka I'm not sure, since I just copied it from one of the stb_load functions

@urraka
Copy link
Author

urraka commented Nov 23, 2023

@Platforming-Mayhem nevermind what I said, my bad. The function is stbi_set_flip_vertically_on_load but you have stbi__vertically_flip_on_load so it's all good ;D

@Platforming-Mayhem
Copy link

Hi @urraka,
I've been using this code for a while now but recently I found out that it takes up a lot of memory. Is this normal and is there anyway to decrease the amount of memory that is used?
Thanks :)

@urraka
Copy link
Author

urraka commented Jan 4, 2024

Hi @Platforming-Mayhem. The way this works is the easy way out: load every frame into memory in RGBA format. If you have big images with many frames it will take a lot of memory (width * height * 4 * number of frames bytes). I suppose, in theory, one could load the compressed file into memory and buffer a few frames at a time (sort of like video preloading)... but that would need a lot more work.

@Platforming-Mayhem
Copy link

Thanks :)
This was a big help :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment