Skip to content

Instantly share code, notes, and snippets.

@Benau
Created July 30, 2021 06:41
Show Gist options
  • Save Benau/39355417005ca06d5d00b94ecc695e1d to your computer and use it in GitHub Desktop.
Save Benau/39355417005ca06d5d00b94ecc695e1d to your computer and use it in GitHub Desktop.
tgs2gif
// gcc tgs2gif.c -o tgs2gif -lrlottie -O3 -lz `MagickWand-config --cppflags --cxxflags --ldflags --libs`
#include <rlottie_capi.h>
#include <MagickWand/MagickWand.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
// Size of the block of memory to use for reading
#define LENGTH 0x1000
char* readTGS(char* path)
{
size_t cur_size = LENGTH * 2;
size_t cursor = 0;
char* result = (char*)calloc(cur_size, 1);
if (!result)
return NULL;
gzFile file = gzopen(path, "r");
if (!file)
goto err;
while (1)
{
char buffer[LENGTH];
int bytes_read = gzread(file, buffer, LENGTH - 1);
buffer[bytes_read] = '\0';
strncpy(result + cursor, buffer, bytes_read);
if (bytes_read < LENGTH - 1)
{
if (gzeof (file))
break;
else
goto err;
}
char* new_result = (char*)calloc(cur_size + LENGTH, 1);
memcpy(new_result, result, cur_size);
free(result);
result = new_result;
cur_size += LENGTH;
cursor += bytes_read;
}
gzclose(file);
return result;
err:
if (file)
gzclose(file);
free(result);
return NULL;
}
void lottie_configure_model_cache_size(size_t cache_size);
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Usage: tgs2gif path_to_tgs_file\n");
return 1;
}
lottie_configure_model_cache_size(0);
char* tgs = readTGS(argv[1]);
Lottie_Animation* animation = lottie_animation_from_data(tgs, "", "");
if (!animation)
{
printf("Usage: Failed to import tgs\n");
return 2;
}
free(tgs);
size_t w = 0;
size_t h = 0;
lottie_animation_get_size(animation, &w, &h);
void* buffer = malloc(w * h * 4);
if (!buffer)
{
printf("Usage: Not enough memory\n");
return 3;
}
size_t frame_count = lottie_animation_get_totalframe(animation);
double frame_rate = lottie_animation_get_framerate(animation);
MagickWandGenesis();
MagickWand* wand = NewMagickWand();
if (!wand)
{
printf("Usage: Not enough memory\n");
lottie_animation_destroy(animation);
return 3;
}
for (size_t i = 0; i < frame_count ; i++)
{
lottie_animation_render(animation, i, buffer, w, h, w * 4);
MagickConstituteImage(wand, w, h, "BGRA", CharPixel, buffer);
MagickSetImageDispose(wand, BackgroundDispose);
MagickSetImageDelay(wand, (unsigned long)(1000. / frame_rate / 10.));
}
free(buffer);
lottie_animation_destroy(animation);
MagickWand* optimized = MagickOptimizeImageLayers(wand);
DestroyMagickWand(wand);
MagickOptimizeImageTransparency(optimized);
MagickWriteImages(optimized, "output.gif", MagickTrue);
DestroyMagickWand(optimized);
MagickWandTerminus();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment