From 35fdfc1eb9be244e37002380de6c3ac650648cab Mon Sep 17 00:00:00 2001 From: Krow Savcik Date: Wed, 31 Jul 2024 13:35:43 +0300 Subject: feature: improved the export function to include frames into consideration --- src/export.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/export.c (limited to 'src/export.c') diff --git a/src/export.c b/src/export.c new file mode 100644 index 0000000..381a240 --- /dev/null +++ b/src/export.c @@ -0,0 +1,124 @@ +#include + +#include "types.h" +#include "action.h" +#include "canvas.h" +#include "debug.h" + +#define COORD(x,y) ((x) + (y) * c->w) + +uint8 +canvas_export_png(Canvas *c, const char *path) +{ + /* TODO: use a defer */ + uint xcnt, ycnt, cnt, w, h, i, j, k, l, col; + FILE *file; + png_structp png_ptr; + png_infop info_ptr; + uint *data, **row_ptr; + + if (c == NULL) + return 1; + + if (c->layer_arr_cnt == 0 || c->frame_arr_cnt == 0) + return 1; + + file = fopen(path, "wb"); + if (!file) + return 1; + + cnt = xcnt = ycnt = 0; + + for (i = 0; i < c->frame_arr_cnt; i++) { + cnt++; + if (c->frames[i].state || i+1 == c->frame_arr_cnt) { + ++ycnt; + xcnt = (cnt > xcnt) ? cnt : xcnt; + cnt = 0; + } + } + w = xcnt * c->w; + h = ycnt * c->h; + + data = malloc(h*w*sizeof *data); + if (data == NULL) { + fclose(file); + return 1; + } + row_ptr = malloc(h*sizeof *row_ptr); + if (row_ptr == NULL) { + fclose(file); + free(data); + return 1; + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(file); + free(data); + free(row_ptr); + return 1; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, NULL); + fclose(file); + free(data); + free(row_ptr); + return 1; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(file); + free(data); + free(row_ptr); + return 1; + } + + png_init_io(png_ptr, file); + png_set_IHDR(png_ptr, info_ptr, w, h, + 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); +/* png_set_invert_alpha(png_ptr);*/ + png_write_info(png_ptr, info_ptr); +/* png_set_swap(png_ptr);*/ + + for (i = 0; i < w * h; i++) + data[i] = 0; + + for (i = 0; i < h; i++) + row_ptr[i] = &data[i * w]; + + ycnt = cnt = 0; + for (i = 0; i < c->frame_arr_cnt; i++) { + for (k = 0; k < c->h; k++) { + for (j = 0; j < c->w; j++) { + col = 0; + for (l = 0; l < c->layer_arr_cnt; l++) + if (c->layers[l].visible) + col = canvas_blend_color(col, + c->cells[c->layer_arr_cnt * i + l][COORD(j, k)]); + data[(ycnt * c->h + k) * w + cnt * c->w + j] = + ((col&255)<<24) | (((col>>8)&255)<<16) | (((col>>16)&255)<<8) | (((col>>24)&255)); + } + } + + if (c->frames[i].state || i+1 == c->frame_arr_cnt) { + ++ycnt; + cnt = 0; + } else { + cnt++; + } + } + + png_write_image(png_ptr, row_ptr); + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(file); + free(data); + free(row_ptr); + + return 0; +} -- cgit v1.2.3