emote2ss

Animated webp to spritesheets converting tool
git clone git://bsandro.tech/emote2ss
Log | Files | Refs | README | LICENSE

animation.c (3504B)


      1 #define _GNU_SOURCE
      2 
      3 #include "animation.h"
      4 #include "fileops.h"
      5 #include <libgen.h>
      6 #include <stdlib.h>
      7 #include <stdio.h>
      8 #include <assert.h>
      9 #include <string.h>
     10 #include <strings.h>
     11 #include "webp/decode.h"
     12 #include "webp/demux.h"
     13 
     14 #ifdef __OpenBSD__
     15 #include <sys/syslimits.h>
     16 #endif
     17 
     18 #ifdef __linux__
     19 #include <linux/limits.h>
     20 #endif
     21 
     22 Animation * ImageLoad(const char *path) {
     23 	Animation *img = malloc(sizeof(Animation));
     24 	assert(img!=NULL);
     25 	bzero(img, sizeof(Animation));
     26 	img->path = realpath(path, NULL);
     27 	assert(img->path!=NULL);
     28 	printf("img->path: %s\n", img->path);
     29 	int r = WebpRead(img->path, img);
     30 	assert(r==0);
     31 
     32 	char *name_copy = strndup(img->path, PATH_MAX);
     33 	char *path_copy = strndup(img->path, PATH_MAX);
     34 	img->filename = strndup(basename(name_copy), NAME_MAX);
     35 	img->dirname = strndup(dirname(path_copy), PATH_MAX);
     36 	free(name_copy);
     37 	free(path_copy);
     38 
     39 	//printf("[%s/%s]\ncols: %d\ndimensions: %dx%dpx\nframes: %d\n", img->dirname, img->filename, cols, img->width, img->height, img->frame_count);
     40 
     41 	return img;
     42 }
     43 
     44 void ImageUnload(Animation **img) {
     45 	free((*img)->path);
     46 	free((*img)->dirname);
     47 	free((*img)->filename);
     48 	free(*img);
     49 	*img = NULL;
     50 }
     51 
     52 int WebpRead(const char *filename, Animation *anim) {
     53 	printf("WebpRead(%s)\n", filename);
     54 
     55 	WebPData webp_data;
     56 	WebPDataInit(&webp_data);
     57 
     58 	if (FileRead(filename, &webp_data.bytes, &webp_data.size) == -1) {
     59 		fprintf(stderr, "FileRead() error\n");
     60 		return -1;
     61 	}
     62 
     63 	if (!WebPGetInfo(webp_data.bytes, webp_data.size, NULL, NULL)) {
     64 		fprintf(stderr, "invalid webp\n");
     65 		WebPDataClear(&webp_data);
     66 		return -1;
     67 	}
     68 
     69 	WebPAnimDecoder *dec = WebPAnimDecoderNew(&webp_data, NULL);
     70 	assert(dec != NULL);
     71 
     72 	WebPAnimInfo anim_info;
     73 	if (!WebPAnimDecoderGetInfo(dec, &anim_info)) {
     74 		fprintf(stderr, "error decoding animation info\n");
     75 		// @todo cleanup
     76 		return -1;
     77 	}
     78 
     79 	anim->width = anim_info.canvas_width;
     80 	anim->height = anim_info.canvas_height;
     81 	anim->loop_count = anim_info.loop_count;
     82 	anim->bgcolor = anim_info.bgcolor;
     83 	AnimationCreate(anim, anim_info.frame_count);
     84 
     85 	uint32_t frame_index = 0;
     86 	int prev_ts = 0;
     87 	while (WebPAnimDecoderHasMoreFrames(dec)) {
     88 		Frame *frame;
     89 		uint8_t *curr_rgba, *frame_rgba;
     90 		int ts;
     91 		if (!WebPAnimDecoderGetNext(dec, &frame_rgba, &ts)) {
     92 			fprintf(stderr, "error decoding frame %d\n", frame_index);
     93 			return -1;
     94 		}
     95 		assert(frame_index < anim_info.frame_count);
     96 		frame = &anim->frames[frame_index];
     97 		curr_rgba = frame->rgba;
     98 		frame->duration = ts - prev_ts;
     99 		memcpy(curr_rgba, frame_rgba, anim->width * anim->height * NUM_CHANNELS);
    100 		// ... <- nani kore?
    101 		++frame_index;
    102 		prev_ts = ts;
    103 	}
    104 
    105 	WebPDataClear(&webp_data);
    106 	WebPAnimDecoderDelete(dec);
    107 	return 0;
    108 }
    109 
    110 void AnimationCreate(Animation *img, uint32_t frame_count) {
    111 	assert(frame_count > 0);
    112 	uint8_t *mem = NULL;
    113 	Frame *frames = NULL;
    114 	const uint64_t rgba_size = img->width * img->height * NUM_CHANNELS;
    115 	const uint64_t img_size = frame_count * rgba_size * sizeof(uint8_t);
    116 	const uint64_t frames_size = frame_count * sizeof(Frame);
    117 
    118 	assert(img_size == (size_t)img_size);
    119 	assert(frames_size == (size_t)frames_size);
    120 
    121 	printf("img mem: %" PRIu64 "\nframes mem: %" PRIu64 "\n", img_size, frames_size);
    122 
    123 	mem = malloc(img_size);
    124 	frames = malloc(frames_size);
    125 	assert(mem != NULL);
    126 	assert(frames != NULL);
    127 
    128 	for (uint32_t i=0; i<frame_count; ++i) {
    129 		frames[i].rgba = mem+i*rgba_size;
    130 		frames[i].duration = 0;
    131 		frames[i].is_key = false;
    132 	}
    133 	img->frame_count = frame_count;
    134 	img->frames = frames;
    135 	img->raw_mem = mem;
    136 }