#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; }