From 94c8c95f2dd8b5c0e5aaa1fcd714fd77524e71cc Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Fri, 20 May 2016 22:24:11 +0000 Subject: [PATCH] You know who just implemented RGB merging and splitting? XANTRONIX did. That's right. --- bin/main.c | 205 +++++++++++++++++++++++++++++++++++++++++- include/cammy/image.h | 16 ++++ include/cammy/photo.h | 12 +++ src/image.c | 48 ++++++++++ src/photo.c | 32 +++++++ 5 files changed, 312 insertions(+), 1 deletion(-) diff --git a/bin/main.c b/bin/main.c index 306bf0c..e3ab884 100644 --- a/bin/main.c +++ b/bin/main.c @@ -30,7 +30,9 @@ static void usage(int argc, char **argv, const char *message, ...) { 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", + " %1$s dither input.png output.png\n" + " %1$s split file.sav rn gn bn input.png\n" + " %1$s merge file.sav rn gn bn output.png\n", argv[0]); exit(1); @@ -320,6 +322,205 @@ error_malloc_in: return 1; } +static void validate_photo_number(int argc, char **argv, int num) { + if (num < 1 || num > CAMMY_SRAM_PHOTO_COUNT) { + usage(argc, argv, "Invalid photo number"); + } +} + +static int split(int argc, char **argv) { + cammy_sram *sram; + png_t *png; + + int photo_r = 0, + photo_g = 0, + photo_b = 0; + + uint8_t *buf; + + int error; + + if (argc < 3) { + usage(argc, argv, "No save file provided"); + } else if (argc < 4) { + usage(argc, argv, "No red photo number provided"); + } else if (argc < 5) { + usage(argc, argv, "No green photo number provided"); + } else if (argc < 6) { + usage(argc, argv, "No blue photo number provided"); + } else if (argc < 7) { + usage(argc, argv, "No photo provided"); + } + + validate_photo_number(argc, argv, photo_r = atoi(argv[3])); + validate_photo_number(argc, argv, photo_g = atoi(argv[4])); + validate_photo_number(argc, argv, photo_b = atoi(argv[5])); + + 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[6])) < 0) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "png_open_file_read()", argv[6], 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[6], "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_rgb(&sram->data->photos[photo_r-1], + &sram->data->photos[photo_g-1], + &sram->data->photos[photo_b-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 merge(int argc, char **argv) { + cammy_sram *sram; + png_t *png; + + int photo_r = 0, + photo_g = 0, + photo_b = 0; + + uint8_t *buf; + + int error; + + if (argc < 3) { + usage(argc, argv, "No save file provided"); + } else if (argc < 4) { + usage(argc, argv, "No red photo number provided"); + } else if (argc < 5) { + usage(argc, argv, "No green photo number provided"); + } else if (argc < 6) { + usage(argc, argv, "No blue photo number provided"); + } else if (argc < 7) { + usage(argc, argv, "No photo provided"); + } + + validate_photo_number(argc, argv, photo_r = atoi(argv[3])); + validate_photo_number(argc, argv, photo_g = atoi(argv[4])); + validate_photo_number(argc, argv, photo_b = atoi(argv[5])); + + 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[6])) < 0) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "png_open_file_write()", argv[6], 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_merge(&sram->data->photos[photo_r-1], + &sram->data->photos[photo_g-1], + &sram->data->photos[photo_b-1], buf, 3); + + 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[6], 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 struct { char *name; int (*fun)(int, char **); @@ -327,6 +528,8 @@ static struct { { "import", import }, { "export", export }, { "dither", dither }, + { "split", split }, + { "merge", merge }, { NULL, NULL } }; diff --git a/include/cammy/image.h b/include/cammy/image.h index 6d271d3..6f788f7 100644 --- a/include/cammy/image.h +++ b/include/cammy/image.h @@ -22,6 +22,14 @@ void cammy_image_dither_to_tile(cammy_tile *dest, size_t height, int depth); +void cammy_image_split_to_tiles(cammy_tile *destr, + cammy_tile *destg, + cammy_tile *destb, + uint8_t *src, + size_t width, + size_t height, + int depth); + void cammy_image_copy_from_tile(uint8_t *dest, cammy_tile *src, size_t width, @@ -29,4 +37,12 @@ void cammy_image_copy_from_tile(uint8_t *dest, int depth, cammy_tile_palette *palette); +void cammy_image_merge_tiles(uint8_t *dest, + cammy_tile *srcr, + cammy_tile *srcg, + cammy_tile *srcb, + size_t width, + size_t height, + int depth); + #endif /* _CAMMY_IMAGE_H */ diff --git a/include/cammy/photo.h b/include/cammy/photo.h index 79760ae..d46cb33 100644 --- a/include/cammy/photo.h +++ b/include/cammy/photo.h @@ -39,6 +39,18 @@ void cammy_photo_export(cammy_photo *src, int depth, cammy_tile_palette *palette); +void cammy_photo_merge(cammy_photo *srcr, + cammy_photo *srcg, + cammy_photo *srcb, + uint8_t *dest, + int depth); + void cammy_photo_import(cammy_photo *dest, uint8_t *src, int depth); +void cammy_photo_import_rgb(cammy_photo *destr, + cammy_photo *destg, + cammy_photo *destb, + uint8_t *src, + int depth); + #endif /* _CAMMY_PHOTO_H */ diff --git a/src/image.c b/src/image.c index 968afb4..97e93d6 100644 --- a/src/image.c +++ b/src/image.c @@ -69,6 +69,10 @@ static uint32_t bayer_matrix[256] = { 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, }; +static uint8_t level_2bpp_to_8bpp[4] = { + 0, 85, 171, 255 +}; + static uint8_t rgb_to_grayscale(uint8_t r, uint8_t g, uint8_t b) { return (uint8_t)((CAMMY_IMAGE_Y_COEFFICIENT_R * (float)r) + (CAMMY_IMAGE_Y_COEFFICIENT_G * (float)g) @@ -157,6 +161,28 @@ void cammy_image_dither(uint8_t *dest, } } +void cammy_image_split_to_tiles(cammy_tile *destr, + cammy_tile *destg, + cammy_tile *destb, + uint8_t *src, + size_t width, + size_t height, + int depth) { + size_t x, y; + + for (y=0; ytiles, + (cammy_tile *)&srcg->tiles, + (cammy_tile *)&srcb->tiles, + CAMMY_PHOTO_WIDTH, + CAMMY_PHOTO_HEIGHT, + depth); +} + void cammy_photo_import(cammy_photo *dest, uint8_t *src, int depth) { memset(&dest->thumb, '\xff', sizeof(dest->thumb)); @@ -26,3 +40,21 @@ void cammy_photo_import(cammy_photo *dest, uint8_t *src, int depth) { CAMMY_PHOTO_HEIGHT, depth); } + +void cammy_photo_import_rgb(cammy_photo *destr, + cammy_photo *destg, + cammy_photo *destb, + uint8_t *src, + int depth) { + memset(&destr->thumb, '\xff', sizeof(destr->thumb)); + memset(&destg->thumb, '\xff', sizeof(destg->thumb)); + memset(&destb->thumb, '\xff', sizeof(destb->thumb)); + + cammy_image_split_to_tiles((cammy_tile *)&destr->tiles, + (cammy_tile *)&destg->tiles, + (cammy_tile *)&destb->tiles, + src, + CAMMY_PHOTO_WIDTH, + CAMMY_PHOTO_HEIGHT, + depth); +}