You know who just implemented RGB merging and splitting? XANTRONIX did. That's right.

This commit is contained in:
XANTRONIX Development 2016-05-20 22:24:11 +00:00
parent 924ba313a8
commit 94c8c95f2d
5 changed files with 312 additions and 1 deletions

View file

@ -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" 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 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]); argv[0]);
exit(1); exit(1);
@ -320,6 +322,205 @@ error_malloc_in:
return 1; 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 { static struct {
char *name; char *name;
int (*fun)(int, char **); int (*fun)(int, char **);
@ -327,6 +528,8 @@ static struct {
{ "import", import }, { "import", import },
{ "export", export }, { "export", export },
{ "dither", dither }, { "dither", dither },
{ "split", split },
{ "merge", merge },
{ NULL, NULL } { NULL, NULL }
}; };

View file

@ -22,6 +22,14 @@ void cammy_image_dither_to_tile(cammy_tile *dest,
size_t height, size_t height,
int depth); 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, void cammy_image_copy_from_tile(uint8_t *dest,
cammy_tile *src, cammy_tile *src,
size_t width, size_t width,
@ -29,4 +37,12 @@ void cammy_image_copy_from_tile(uint8_t *dest,
int depth, int depth,
cammy_tile_palette *palette); 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 */ #endif /* _CAMMY_IMAGE_H */

View file

@ -39,6 +39,18 @@ void cammy_photo_export(cammy_photo *src,
int depth, int depth,
cammy_tile_palette *palette); 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(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 */ #endif /* _CAMMY_PHOTO_H */

View file

@ -69,6 +69,10 @@ static uint32_t bayer_matrix[256] = {
0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, 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) { 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) return (uint8_t)((CAMMY_IMAGE_Y_COEFFICIENT_R * (float)r)
+ (CAMMY_IMAGE_Y_COEFFICIENT_G * (float)g) + (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; y<height; y++) {
for (x=0; x<width; x++) {
uint8_t r, g, b;
buf_read(src, x, y, width, &r, &g, &b, depth);
tile_write(destr, x, y, width, rgb_to_tile_2bpp(r, r, r, x, y) ^ 3);
tile_write(destg, x, y, width, rgb_to_tile_2bpp(g, g, g, x, y) ^ 3);
tile_write(destb, x, y, width, rgb_to_tile_2bpp(b, b, b, x, y) ^ 3);
}
}
}
void cammy_image_copy_from_tile(uint8_t *dest, void cammy_image_copy_from_tile(uint8_t *dest,
cammy_tile *src, cammy_tile *src,
size_t width, size_t width,
@ -195,3 +221,25 @@ void cammy_image_dither_to_tile(cammy_tile *dest,
} }
} }
} }
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) {
size_t x, y;
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
uint8_t r = tile_read(srcr, x, y, width),
g = tile_read(srcg, x, y, width),
b = tile_read(srcb, x, y, width);
buf_write(dest, x, y, width, level_2bpp_to_8bpp[r],
level_2bpp_to_8bpp[g],
level_2bpp_to_8bpp[b], depth);
}
}
}

View file

@ -17,6 +17,20 @@ void cammy_photo_export(cammy_photo *src,
palette); palette);
} }
void cammy_photo_merge(cammy_photo *srcr,
cammy_photo *srcg,
cammy_photo *srcb,
uint8_t *dest,
int depth) {
cammy_image_merge_tiles(dest,
(cammy_tile *)&srcr->tiles,
(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) { void cammy_photo_import(cammy_photo *dest, uint8_t *src, int depth) {
memset(&dest->thumb, '\xff', sizeof(dest->thumb)); 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, CAMMY_PHOTO_HEIGHT,
depth); 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);
}