aboutsummaryrefslogtreecommitdiff
path: root/src/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/export.c')
-rw-r--r--src/export.c124
1 files changed, 124 insertions, 0 deletions
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 <png.h>
+
+#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;
+}