Skip to content

Instantly share code, notes, and snippets.

@hrj
Created May 28, 2017 14:26
Show Gist options
  • Save hrj/6d11eb4c2061636e018bbd12f26ff153 to your computer and use it in GitHub Desktop.
Save hrj/6d11eb4c2061636e018bbd12f26ff153 to your computer and use it in GitHub Desktop.
dumpflif
/*
Example application of FLIF decoder using libflif_dec
Copyright (C) 2017 Harshad RJ
Based on the viewflif code.
License: Creative Commons CC0 1.0 Universal (Public Domain)
https://creativecommons.org/publicdomain/zero/1.0/legalcode
*/
#include <flif_dec.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// comment out to not decode progressively
#define PROGRESSIVE_DECODING
#pragma pack(push,1)
typedef struct RGBA { uint8_t r,g,b,a; } RGBA;
#pragma pack(pop)
FLIF_DECODER* d = NULL;
int frame = 0;
int nb_frames = 0;
int* frame_delay = NULL;
volatile int drawing = 0;
volatile int loading = 0;
int framecount = 0;
// Renders the image or current animation frame
clock_t last_preview_time = -CLOCKS_PER_SEC;
// Callback function: converts (partially) decoded image/animation to a/several SDL_Texture(s),
// resizes the viewer window if needed, and calls draw_image()
// Input arguments are: quality (0..10000), current position in the .flif file
// Output is the desired minimal quality before doing the next callback
uint32_t progressive_render(callback_info_t *info, void *user_data) {
uint32_t quality = info->quality;
clock_t now = clock();
/*
double timeElapsed = ((double)(now - last_preview_time)) / CLOCKS_PER_SEC;
if (quality != 10000 && timeElapsed < 0.4) {
return quality + 1000;
}
*/
last_preview_time = now;
int64_t bytes_read = info->bytes_read;
printf("%lli bytes read, rendering at quality=%.2f%%\n",(long long int) bytes_read, 0.01*quality);
// For benchmarking
if (quality == 10000) printf("Total time: %.2lf\n", ((double)now ) / CLOCKS_PER_SEC);
flif_decoder_generate_preview(info);
FLIF_IMAGE* image = flif_decoder_get_image(d, 0);
if (!image) { printf("Error: No decoded image found\n"); return 1; }
uint32_t w = flif_image_get_width(image);
uint32_t h = flif_image_get_height(image);
char* ppBase = malloc(w * h * sizeof(RGBA));
for (int f = 0; f < flif_decoder_num_images(d); f++) {
char* pp = ppBase;
FLIF_IMAGE* image = flif_decoder_get_image(d, f);
if (!image) { printf("Error: No decoded image found\n"); return 1; }
for (uint32_t r=0; r<h; r++) {
flif_image_read_row_RGBA8(image, r, pp, w * sizeof(RGBA));
if (r < 10) {
printf("r %3d :", r);
for (uint32_t c=0; c < 12; c++) {
printf("%2x ", 0xff & pp[c]);
}
printf("\n");
}
pp += w * sizeof(RGBA);
}
}
free(ppBase);
ppBase = NULL;
nb_frames = flif_decoder_num_images(d);
return quality + 2000; // call me back when you have at least 10.00% better quality
}
// When decoding progressively, this is a separate thread (so a partially loaded animation keeps playing while decoding more detail)
static int decodeThread(void * arg) {
char ** argv = (char **)arg;
d = flif_create_decoder();
if (!d) return 1;
// set the quality to 100% (a lower value will decode a lower-quality preview)
flif_decoder_set_quality(d, 100); // this is the default, so can be omitted
// set the scale-down factor to 1 (a higher value will decode a downsampled preview)
flif_decoder_set_scale(d, 1); // this is the default, so can be omitted
#ifdef PROGRESSIVE_DECODING
// set the callback function to render the partial (and final) decoded images
flif_decoder_set_callback(d, &(progressive_render), NULL); // the default is "no callback"; decode completely until quality/scale/size target is reached
// do the first callback when at least 5.00% quality has been decoded
flif_decoder_set_first_callback_quality(d, 500); // the default is to callback almost immediately
#endif
if (!flif_decoder_decode_file(d, argv[1])) {
printf("Error: decoding failed\n");
flif_destroy_decoder(d);
return 1;
}
#ifndef PROGRESSIVE_DECODING
// no callback was set, so we manually call our callback function to render the final image/frames
progressive_render(10000,-1);
#endif
flif_destroy_decoder(d);
d = NULL;
return 0;
}
int main(int argc, char **argv) {
if (argc < 2 || argc > 2) {
printf("Usage: %s image.flif\n",argv[0]);
return 0;
}
int result = decodeThread(argv);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment