Created
May 28, 2017 14:26
-
-
Save hrj/6d11eb4c2061636e018bbd12f26ff153 to your computer and use it in GitHub Desktop.
dumpflif
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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