emote2ss

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

commit ca53d7d32806bb43437c9c401bb1ae32215ab960
parent 0960303193e14f0e7492df1819da4680b6044f0b
Author: bsandro <email@bsandro.tech>
Date:   Mon, 28 Aug 2023 23:48:45 +0300

began splitting source code into different files

Diffstat:
Agui/animation.c | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agui/animation.h | 24++++++++++++++++++++++++
Mgui/main.c | 146++++---------------------------------------------------------------------------
3 files changed, 166 insertions(+), 139 deletions(-)

diff --git a/gui/animation.c b/gui/animation.c @@ -0,0 +1,135 @@ +#define _GNU_SOURCE + +#include "animation.h" +#include <libgen.h> +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <strings.h> +#include "webp/decode.h" +#include "webp/demux.h" + +#ifdef __OpenBSD__ +#include <sys/syslimits.h> +#endif + +#ifdef __linux__ +#include <linux/limits.h> +#endif + +Animation * ImageLoad(const char *path) { + Animation *img = malloc(sizeof(Animation)); + assert(img!=NULL); + bzero(img, sizeof(Animation)); + img->path = realpath(path, NULL); + assert(img->path!=NULL); + printf("img->path: %s\n", img->path); + int r = WebpRead(img->path, img); + assert(r==0); + + char *name_copy = strndup(img->path, PATH_MAX); + char *path_copy = strndup(img->path, PATH_MAX); + img->filename = strndup(basename(name_copy), NAME_MAX); + img->dirname = strndup(dirname(path_copy), PATH_MAX); + free(name_copy); + free(path_copy); + + //printf("[%s/%s]\ncols: %d\ndimensions: %dx%dpx\nframes: %d\n", img->dirname, img->filename, cols, img->width, img->height, img->frame_count); + + return img; +} + +void ImageUnload(Animation **img) { + free((*img)->path); + free((*img)->dirname); + free((*img)->filename); + free(*img); + *img = NULL; +} + +int WebpRead(const char *filename, Animation *anim) { + printf("WebpRead(%s)\n", filename); + + WebPData webp_data; + WebPDataInit(&webp_data); + + if (ReadFile(filename, &webp_data.bytes, &webp_data.size) == -1) { + fprintf(stderr, "ReadFile error\n"); + return -1; + } + + if (!WebPGetInfo(webp_data.bytes, webp_data.size, NULL, NULL)) { + fprintf(stderr, "invalid webp\n"); + WebPDataClear(&webp_data); + return -1; + } + + WebPAnimDecoder *dec = WebPAnimDecoderNew(&webp_data, NULL); + assert(dec != NULL); + + WebPAnimInfo anim_info; + if (!WebPAnimDecoderGetInfo(dec, &anim_info)) { + fprintf(stderr, "error decoding animation info\n"); + // @todo cleanup + return -1; + } + + anim->width = anim_info.canvas_width; + anim->height = anim_info.canvas_height; + anim->loop_count = anim_info.loop_count; + anim->bgcolor = anim_info.bgcolor; + AnimationCreate(anim, anim_info.frame_count); + + uint32_t frame_index = 0; + int prev_ts = 0; + while (WebPAnimDecoderHasMoreFrames(dec)) { + Frame *frame; + uint8_t *curr_rgba, *frame_rgba; + int ts; + if (!WebPAnimDecoderGetNext(dec, &frame_rgba, &ts)) { + fprintf(stderr, "error decoding frame %d\n", frame_index); + return -1; + } + assert(frame_index < anim_info.frame_count); + frame = &anim->frames[frame_index]; + curr_rgba = frame->rgba; + frame->duration = ts - prev_ts; + memcpy(curr_rgba, frame_rgba, anim->width * anim->height * NUM_CHANNELS); + // ... <- nani kore? + ++frame_index; + prev_ts = ts; + } + + WebPDataClear(&webp_data); + WebPAnimDecoderDelete(dec); + return 0; +} + +void AnimationCreate(Animation *img, uint32_t frame_count) { + assert(frame_count > 0); + uint8_t *mem = NULL; + Frame *frames = NULL; + const uint64_t rgba_size = img->width * img->height * NUM_CHANNELS; + const uint64_t img_size = frame_count * rgba_size * sizeof(uint8_t); + const uint64_t frames_size = frame_count * sizeof(Frame); + + assert(img_size == (size_t)img_size); + assert(frames_size == (size_t)frames_size); + + printf("img mem: %" PRIu64 "\nframes mem: %" PRIu64 "\n", img_size, frames_size); + + mem = malloc(img_size); + frames = malloc(frames_size); + assert(mem != NULL); + assert(frames != NULL); + + for (uint32_t i=0; i<frame_count; ++i) { + frames[i].rgba = mem+i*rgba_size; + frames[i].duration = 0; + frames[i].is_key = false; + } + img->frame_count = frame_count; + img->frames = frames; + img->raw_mem = mem; +} diff --git a/gui/animation.h b/gui/animation.h @@ -0,0 +1,24 @@ +#include <stdbool.h> +#include <stdint.h> + +#define NUM_CHANNELS 4 + +typedef struct { + uint8_t *rgba; + int duration; + bool is_key; +} Frame; + +typedef struct { + int width, height, bgcolor, loop_count; + Frame *frames; + uint32_t frame_count; + void *raw_mem; + char *path; + char *dirname; + char *filename; +} Animation; + +Animation * ImageLoad(const char *path); +void ImageUnload(Animation **img); +int WebpRead(const char *filename, Animation *anim); diff --git a/gui/main.c b/gui/main.c @@ -2,7 +2,7 @@ * Loosely based on the libwebp example program "anim_dump" */ -#define _GNU_SOURCE +// #define _GNU_SOURCE // moved into the compiler command line arguments // #define UI_LINUX @@ -20,6 +20,8 @@ #include <assert.h> #include "luigi.h" +#include "animation.h" + #ifdef __OpenBSD__ #include <sys/syslimits.h> #endif @@ -34,7 +36,6 @@ #define DIR_SEPARATOR '/' #endif -#define NUM_CHANNELS 4 #define WIN_WIDTH 750 #define WIN_HEIGHT 400 @@ -54,22 +55,6 @@ typedef struct { int width, height, stride; } Spritesheet; -typedef struct { - uint8_t *rgba; - int duration; - bool is_key; -} Frame; - -typedef struct { - int width, height, bgcolor, loop_count; - Frame *frames; - uint32_t frame_count; - void *raw_mem; - char *path; - char *dirname; - char *filename; -} Animation; - // let it be global variable for now static Animation *img = NULL; static int cols = 1; @@ -78,38 +63,11 @@ static UIImageDisplay *img_disp = NULL; static UILabel *lbl_header = NULL; //@todo headers! -Animation * ImageLoad(const char *); -void ImageUnload(Animation **); +//Animation * ImageLoad(const char *); +//void ImageUnload(Animation **); void PreviewUpdate(Animation *, UIImageDisplay *); -void AnimationCreate(Animation *img, uint32_t frame_count) { - assert(frame_count > 0); - uint8_t *mem = NULL; - Frame *frames = NULL; - const uint64_t rgba_size = img->width * img->height * NUM_CHANNELS; - const uint64_t img_size = frame_count * rgba_size * sizeof(uint8_t); - const uint64_t frames_size = frame_count * sizeof(Frame); - - assert(img_size == (size_t)img_size); - assert(frames_size == (size_t)frames_size); - - printf("img mem: %" PRIu64 "\nframes mem: %" PRIu64 "\n", img_size, frames_size); - - mem = malloc(img_size); - frames = malloc(frames_size); - assert(mem != NULL); - assert(frames != NULL); - - for (uint32_t i=0; i<frame_count; ++i) { - frames[i].rgba = mem+i*rgba_size; - frames[i].duration = 0; - frames[i].is_key = false; - } - img->frame_count = frame_count; - img->frames = frames; - img->raw_mem = mem; -} - +// @todo collision with ms windows function int ReadFile(const char *filename, const uint8_t **data, size_t *size) { assert(data != NULL); assert(size != NULL); @@ -139,64 +97,6 @@ int ReadFile(const char *filename, const uint8_t **data, size_t *size) { return 0; } -int WebpRead(const char *filename, Animation *anim) { - printf("WebpRead(%s)\n", filename); - - WebPData webp_data; - WebPDataInit(&webp_data); - - if (ReadFile(filename, &webp_data.bytes, &webp_data.size) == -1) { - fprintf(stderr, "ReadFile error\n"); - return -1; - } - - if (!WebPGetInfo(webp_data.bytes, webp_data.size, NULL, NULL)) { - fprintf(stderr, "invalid webp\n"); - WebPDataClear(&webp_data); - return -1; - } - - WebPAnimDecoder *dec = WebPAnimDecoderNew(&webp_data, NULL); - assert(dec != NULL); - - WebPAnimInfo anim_info; - if (!WebPAnimDecoderGetInfo(dec, &anim_info)) { - fprintf(stderr, "error decoding animation info\n"); - // @todo cleanup - return -1; - } - - anim->width = anim_info.canvas_width; - anim->height = anim_info.canvas_height; - anim->loop_count = anim_info.loop_count; - anim->bgcolor = anim_info.bgcolor; - AnimationCreate(anim, anim_info.frame_count); - - uint32_t frame_index = 0; - int prev_ts = 0; - while (WebPAnimDecoderHasMoreFrames(dec)) { - Frame *frame; - uint8_t *curr_rgba, *frame_rgba; - int ts; - if (!WebPAnimDecoderGetNext(dec, &frame_rgba, &ts)) { - fprintf(stderr, "error decoding frame %d\n", frame_index); - return -1; - } - assert(frame_index < anim_info.frame_count); - frame = &anim->frames[frame_index]; - curr_rgba = frame->rgba; - frame->duration = ts - prev_ts; - memcpy(curr_rgba, frame_rgba, anim->width * anim->height * NUM_CHANNELS); - // ... <- nani kore? - ++frame_index; - prev_ts = ts; - } - - WebPDataClear(&webp_data); - WebPAnimDecoderDelete(dec); - return 0; -} - Spritesheet GenSpritesheet(Animation *img, int cols) { int rows = (int)img->frame_count / cols; if ((int)img->frame_count % cols > 0) { @@ -303,7 +203,7 @@ int ButtonDialogOpenEvent(UIElement *element, UIMessage msg, int di, void *dp) { img = ImageLoad(filepath); assert(img!=NULL); PreviewUpdate(img, img_disp); - + UILabelSetContent(lbl_header, img->path, -1); } return 0; } @@ -445,38 +345,6 @@ int WinMainEvent(UIElement *element, UIMessage msg, int di, void *dp) { return 0; } -void ImageUnload(Animation **img) { - free((*img)->path); - free((*img)->dirname); - free((*img)->filename); - free(*img); - *img = NULL; -} - -Animation * ImageLoad(const char *path) { - Animation *img = malloc(sizeof(Animation)); - assert(img!=NULL); - bzero(img, sizeof(Animation)); - img->path = realpath(path, NULL); - assert(img->path!=NULL); - printf("img->path: %s\n", img->path); - int r = WebpRead(img->path, img); - assert(r==0); - - char *name_copy = strndup(img->path, PATH_MAX); - char *path_copy = strndup(img->path, PATH_MAX); - img->filename = strndup(basename(name_copy), NAME_MAX); - img->dirname = strndup(dirname(path_copy), PATH_MAX); - free(name_copy); - free(path_copy); - - printf("[%s/%s]\ncols: %d\ndimensions: %dx%dpx\nframes: %d\n", img->dirname, img->filename, cols, img->width, img->height, img->frame_count); - - UILabelSetContent(lbl_header, img->path, -1); - - return img; -} - #ifdef UI_LINUX int main(int argc, const char **argv) { #else