You know who just implemented RGB merging and splitting? XANTRONIX did. That's right.
This commit is contained in:
parent
924ba313a8
commit
94c8c95f2d
5 changed files with 312 additions and 1 deletions
205
bin/main.c
205
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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
48
src/image.c
48
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; 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,
|
||||
cammy_tile *src,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
32
src/photo.c
32
src/photo.c
|
@ -17,6 +17,20 @@ void cammy_photo_export(cammy_photo *src,
|
|||
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) {
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue