#include #include #include #include #include #include "pnglite.h" #include #include #include static cammy_tile_palette palette = { .colors = { { 0, 0, 0 }, { 85, 85, 85 }, { 171, 171, 171 }, { 255, 255, 255 } } }; static void usage(int argc, char **argv, const char *message, ...) { if (message) { va_list args; va_start(args, message); vfprintf(stderr, message, args); va_end(args); fprintf(stderr, "\n"); } fprintf(stderr, "usage: %1$s import file.sav photo1..30 input.png\n" " %1$s export file.sav photo1..30 output.png\n" " %1$s dither input.png output.png\n", argv[0]); exit(1); } static inline uint8_t *buf_malloc(size_t width, size_t height, int stride) { return malloc(stride * width * height); } static int import(int argc, char **argv) { cammy_sram *sram; png_t *png; int photo = 0; uint8_t *buf; int error; if (argc < 3) { usage(argc, argv, "No save file provided"); } else if (argc < 4) { usage(argc, argv, "No photo number provided"); } else if (argc < 5) { usage(argc, argv, "No photo provided"); } photo = atoi(argv[3]); if (photo < 1 || photo > CAMMY_SRAM_PHOTO_COUNT) { usage(argc, argv, "Invalid photo number"); } if ((sram = cammy_sram_open(argv[2])) == NULL) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "cammy_sram_open()", argv[2], strerror(errno)); goto error_sram_open; } png_init(malloc, free); if ((png = malloc(sizeof(*png))) == NULL) { goto error_malloc_png; } if ((error = png_open_file_read(png, argv[4])) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_open_file_read()", argv[4], png_error_string(error)); goto error_png_open_file_read; } if (png->width != CAMMY_PHOTO_WIDTH || png->height != CAMMY_PHOTO_HEIGHT) { fprintf(stderr, "%s: %s: %s\n", argv[0], argv[4], "Invalid image dimensions"); goto error_invalid_dimensions; } if ((buf = buf_malloc(png->width, png->height, (int)png->bpp)) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "malloc()", strerror(errno)); goto error_buf_malloc; } if ((error = png_get_data(png, buf)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_get_data()", argv[4], png_error_string(error)); goto error_png_get_data; } cammy_photo_import(&sram->data->photos[photo-1], buf, (int)png->bpp); free(buf); png_close_file(png); free(png); cammy_sram_close(sram); return 0; error_png_get_data: free(buf); error_buf_malloc: error_invalid_dimensions: png_close_file(png); error_png_open_file_read: free(png); error_malloc_png: cammy_sram_close(sram); error_sram_open: return 1; } static int export(int argc, char **argv) { cammy_sram *sram; png_t *png; int photo = 0; uint8_t *buf; int error; if (argc < 3) { usage(argc, argv, "No save file provided"); } else if (argc < 4) { usage(argc, argv, "No photo number provided"); } else if (argc < 5) { usage(argc, argv, "No output filename provided"); } photo = atoi(argv[3]); if (photo < 1 || photo > CAMMY_SRAM_PHOTO_COUNT) { usage(argc, argv, "Invalid photo number"); } if ((sram = cammy_sram_open(argv[2])) == NULL) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "cammy_sram_open()", argv[2], strerror(errno)); goto error_sram_open; } png_init(malloc, free); if ((png = malloc(sizeof(*png))) == NULL) { goto error_malloc_png; } if ((error = png_open_file_write(png, argv[4])) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_open_file_write()", argv[4], png_error_string(error)); goto error_png_open_file_write; } if ((buf = buf_malloc(CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_HEIGHT, 3)) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "malloc()", strerror(errno)); goto error_buf_malloc; } cammy_photo_export(&sram->data->photos[photo-1], buf, 3, &palette); if ((error = png_set_data(png, CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_HEIGHT, 8, PNG_TRUECOLOR, buf)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_set_data()", argv[4], png_error_string(error)); goto error_png_set_data; } png_close_file(png); free(buf); free(png); cammy_sram_close(sram); return 0; error_png_set_data: free(buf); error_buf_malloc: png_close_file(png); error_png_open_file_write: free(png); error_malloc_png: cammy_sram_close(sram); error_sram_open: return 1; } static int dither(int argc, char **argv) { png_t *in, *out; uint8_t *bufin, *bufout; int error; if (argc < 3) { usage(argc, argv, "No PNG input file provided"); } else if (argc < 4) { usage(argc, argv, "No PNG output filename provided"); } png_init(malloc, free); if ((in = malloc(sizeof(*in))) == NULL) { goto error_malloc_in; } if ((out = malloc(sizeof(*in))) == NULL) { goto error_malloc_out; } if ((error = png_open_file_read(in, argv[2])) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_open_file_read()", argv[2], png_error_string(error)); goto error_png_open_file_read; } if ((error = png_open_file_write(out, argv[3])) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_open_file_write()", argv[3], png_error_string(error)); goto error_png_open_file_write; } if ((bufin = buf_malloc(in->width, in->height, (int)in->bpp)) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "malloc()", strerror(errno)); goto error_buf_malloc_bufin; } if ((bufout = buf_malloc(in->width, in->height, (int)in->bpp)) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "malloc()", strerror(errno)); goto error_buf_malloc_bufout; } if ((error = png_get_data(in, bufin)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_get_data()", argv[2], png_error_string(error)); goto error_png_get_data; } cammy_image_dither(bufout, bufin, in->width, in->height, in->bpp, &palette); if ((error = png_set_data(out, in->width, in->height, in->depth, in->color_type, bufout)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "png_set_data()", argv[4], png_error_string(error)); goto error_png_set_data; } png_close_file(out); png_close_file(in); free(bufout); free(bufin); free(out); free(in); return 0; error_png_set_data: error_png_get_data: free(bufout); error_buf_malloc_bufout: free(bufin); error_buf_malloc_bufin: png_close_file(out); error_png_open_file_write: png_close_file(in); error_png_open_file_read: free(out); error_malloc_out: free(in); error_malloc_in: return 1; } static struct { char *name; int (*fun)(int, char **); } commands[] = { { "import", import }, { "export", export }, { "dither", dither }, { NULL, NULL } }; int main(int argc, char **argv) { int i; if (argc < 2) { usage(argc, argv, "No command specified"); } for (i=0; commands[i].name; i++) { if (strcmp(argv[1], commands[i].name) == 0) { return commands[i].fun(argc, argv); } } usage(argc, argv, "Unknown command '%s'", argv[1]); return 0; }