Dedicated palette type that also stores own length
This commit is contained in:
parent
e8c53b1f9b
commit
d9f4362615
60
img2cpi.c
60
img2cpi.c
|
@ -23,9 +23,15 @@ struct cc_char {
|
|||
unsigned char character;
|
||||
unsigned char bg, fg;
|
||||
};
|
||||
struct palette {
|
||||
const uint8_t count;
|
||||
union color colors[] __attribute__((counted_by(count)));
|
||||
};
|
||||
#define LENGTHOF(...) (sizeof(__VA_ARGS__) / sizeof(*(__VA_ARGS__)))
|
||||
#define PALETTE(...) { .count = LENGTHOF((union color[]){__VA_ARGS__}), .colors = {__VA_ARGS__} }
|
||||
|
||||
const extern char font_atlas[256][11];
|
||||
const extern union color DEFAULT_PALETTE[16], DEFAULT_GRAY_PALETTE[16];
|
||||
const extern struct palette DEFAULT_PALETTE, DEFAULT_GRAY_PALETTE;
|
||||
|
||||
struct arguments {
|
||||
bool fast_mode;
|
||||
|
@ -76,8 +82,7 @@ struct image {
|
|||
struct image_pal {
|
||||
int w, h;
|
||||
uint8_t *pixels;
|
||||
const union color *palette;
|
||||
size_t palette_size;
|
||||
const struct palette *palette;
|
||||
};
|
||||
|
||||
bool parse_cmdline(int argc, char **argv);
|
||||
|
@ -85,7 +90,7 @@ void show_help(const char *progname, bool show_all, FILE *fp);
|
|||
struct image *image_load(const char *fp);
|
||||
struct image *image_new(int w, int h);
|
||||
struct image *image_resize(struct image *original, int new_w, int new_h);
|
||||
struct image_pal *image_quantize(struct image *original, const union color *colors, size_t n_colors);
|
||||
struct image_pal *image_quantize(struct image *original, const struct palette *palette);
|
||||
float get_color_difference(union color a, union color b);
|
||||
float get_color_brightness(union color clr);
|
||||
void image_unload(struct image *img);
|
||||
|
@ -163,10 +168,10 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
// TODO: load palette, maybe calculate it too? k-means?
|
||||
const union color *palette = DEFAULT_PALETTE;
|
||||
const struct palette *palette = &DEFAULT_PALETTE;
|
||||
switch (args.palette_type) {
|
||||
case PALETTE_DEFAULT: palette = DEFAULT_PALETTE; break;
|
||||
case PALETTE_DEFAULT_GRAY: palette = DEFAULT_GRAY_PALETTE; break;
|
||||
case PALETTE_DEFAULT: palette = &DEFAULT_PALETTE; break;
|
||||
case PALETTE_DEFAULT_GRAY: palette = &DEFAULT_GRAY_PALETTE; break;
|
||||
case PALETTE_AUTO: assert(0 && "Not implemented"); break;
|
||||
case PALETTE_LIST: assert(0 && "Not implemented"); break;
|
||||
case PALETTE_PATH: assert(0 && "Not implemented"); break;
|
||||
|
@ -198,7 +203,7 @@ int main(int argc, char **argv) {
|
|||
// TODO: actually do stuff
|
||||
struct cc_char *characters = calloc(args.width * args.height, sizeof(struct cc_char));
|
||||
|
||||
struct image_pal *quantized_image = image_quantize(canvas, palette, 16);
|
||||
struct image_pal *quantized_image = image_quantize(canvas, palette);
|
||||
if (!quantized_image) {
|
||||
fprintf(stderr, "Error: failed to open the file\n");
|
||||
return EXIT_FAILURE;
|
||||
|
@ -217,9 +222,9 @@ int main(int argc, char **argv) {
|
|||
fputc(args.height, fp);
|
||||
fputc(0x00, fp);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
fputc(palette[i].rgba.r, fp);
|
||||
fputc(palette[i].rgba.g, fp);
|
||||
fputc(palette[i].rgba.b, fp);
|
||||
fputc(palette->colors[i].rgba.r, fp);
|
||||
fputc(palette->colors[i].rgba.g, fp);
|
||||
fputc(palette->colors[i].rgba.b, fp);
|
||||
}
|
||||
for (int i = 0; i < args.width * args.height; i++) {
|
||||
fputc(characters[i].character, fp);
|
||||
|
@ -486,19 +491,18 @@ void get_size_keep_aspect(int w, int h, int dw, int dh, int *ow, int *oh)
|
|||
}
|
||||
}
|
||||
|
||||
struct image_pal *image_quantize(struct image *original, const union color *colors, size_t n_colors) {
|
||||
struct image_pal *image_quantize(struct image *original, const struct palette *palette) {
|
||||
struct image_pal *out = calloc(1, sizeof(struct image_pal));
|
||||
out->w = original->w;
|
||||
out->h = original->h;
|
||||
out->pixels = calloc(original->w, original->h);
|
||||
out->palette = colors;
|
||||
out->palette_size = n_colors;
|
||||
out->palette = palette;
|
||||
|
||||
for (int i = 0; i < out->w * out->h; i++) {
|
||||
int closest_color = 0;
|
||||
float closest_distance = 1e20;
|
||||
for (int color = 0; color < n_colors; color++) {
|
||||
float dist = get_color_difference(colors[color], original->pixels[i]);
|
||||
for (int color = 0; color < palette->count; color++) {
|
||||
float dist = get_color_difference(palette->colors[color], original->pixels[i]);
|
||||
if (dist <= closest_distance) {
|
||||
closest_distance = dist;
|
||||
closest_color = color;
|
||||
|
@ -531,7 +535,7 @@ void convert_2x3(const struct image_pal *img, struct cc_char *characters) {
|
|||
for (int oy = 0; oy < 3; oy++) {
|
||||
for (int ox = 0; ox < 2; ox++) {
|
||||
unsigned char pix = img->pixels[ox + (x + (y * 3 + oy) * w) * 2];
|
||||
float brightness = get_color_brightness(img->palette[pix]);
|
||||
float brightness = get_color_brightness(img->palette->colors[pix]);
|
||||
if (brightness >= brightest_diff) {
|
||||
brightest_i = pix;
|
||||
brightest_diff = brightness;
|
||||
|
@ -549,8 +553,8 @@ void convert_2x3(const struct image_pal *img, struct cc_char *characters) {
|
|||
for (int ox = 0; ox < 2; ox++) {
|
||||
if (ox == 1 && oy == 2) continue;
|
||||
unsigned char pix = img->pixels[ox + (x + (y * 3 + oy) * w) * 2];
|
||||
float diff_bg = get_color_difference(img->palette[darkest_i], img->palette[pix]);
|
||||
float diff_fg = get_color_difference(img->palette[brightest_i], img->palette[pix]);
|
||||
float diff_bg = get_color_difference(img->palette->colors[darkest_i], img->palette->colors[pix]);
|
||||
float diff_fg = get_color_difference(img->palette->colors[brightest_i], img->palette->colors[pix]);
|
||||
if (diff_fg < diff_bg) {
|
||||
bitmap |= pixel_bits[oy][ox];
|
||||
}
|
||||
|
@ -559,8 +563,8 @@ void convert_2x3(const struct image_pal *img, struct cc_char *characters) {
|
|||
|
||||
{
|
||||
unsigned char pix = img->pixels[1 + (x + (y * 3 + 2) * w) * 2];
|
||||
float diff_bg = get_color_difference(img->palette[darkest_i], img->palette[pix]);
|
||||
float diff_fg = get_color_difference(img->palette[brightest_i], img->palette[pix]);
|
||||
float diff_bg = get_color_difference(img->palette->colors[darkest_i], img->palette->colors[pix]);
|
||||
float diff_fg = get_color_difference(img->palette->colors[brightest_i], img->palette->colors[pix]);
|
||||
if (diff_fg < diff_bg) {
|
||||
bitmap ^= 31;
|
||||
unsigned char tmp = darkest_i;
|
||||
|
@ -579,9 +583,9 @@ void convert_2x3(const struct image_pal *img, struct cc_char *characters) {
|
|||
void convert_8x11(const struct image_pal *img, struct cc_char *characters) {
|
||||
int w = img->w / 8, h = img->h / 11;
|
||||
float palette_self_diffs[0x100][0x10] = {{(float) 0xffffff}};
|
||||
for (int input_color = 0x0; input_color < 0x100 && input_color < img->palette_size; input_color++) {
|
||||
for (int output_color = 0x0; output_color < 0x10 && output_color < img->palette_size; output_color++) {
|
||||
palette_self_diffs[input_color][output_color] = get_color_difference(img->palette[input_color], img->palette[output_color]);
|
||||
for (int input_color = 0x0; input_color < 0x100 && input_color < img->palette->count; input_color++) {
|
||||
for (int output_color = 0x0; output_color < 0x10 && output_color < img->palette->count; output_color++) {
|
||||
palette_self_diffs[input_color][output_color] = get_color_difference(img->palette->colors[input_color], img->palette->colors[output_color]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,7 +597,7 @@ void convert_8x11(const struct image_pal *img, struct cc_char *characters) {
|
|||
uint8_t pixel_unresolved = img->pixels[
|
||||
ox + (x + (y * 11 + oy) * w) * 8
|
||||
];
|
||||
for (int color = 0x0; color < 0x10 && color < img->palette_size; color++) {
|
||||
for (int color = 0x0; color < 0x10 && color < img->palette->count; color++) {
|
||||
chunk_palette_diffs[ox][oy][color] = palette_self_diffs[pixel_unresolved][color];
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +632,7 @@ void convert_8x11(const struct image_pal *img, struct cc_char *characters) {
|
|||
}
|
||||
}
|
||||
|
||||
const union color DEFAULT_PALETTE[16] = {
|
||||
const struct palette DEFAULT_PALETTE = PALETTE(
|
||||
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
||||
{ { 0xf2, 0xb2, 0x33, 0xff } },
|
||||
{ { 0xe5, 0x7f, 0xd8, 0xff } },
|
||||
|
@ -645,7 +649,7 @@ const union color DEFAULT_PALETTE[16] = {
|
|||
{ { 0x57, 0xa6, 0x4e, 0xff } },
|
||||
{ { 0xcc, 0x4c, 0x4c, 0xff } },
|
||||
{ { 0x11, 0x11, 0x11, 0xff } }
|
||||
}, DEFAULT_GRAY_PALETTE[16] = {
|
||||
), DEFAULT_GRAY_PALETTE = PALETTE(
|
||||
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
||||
{ { 0x9d, 0x9d, 0x9d, 0xff } },
|
||||
{ { 0xbe, 0xbe, 0xbe, 0xff } },
|
||||
|
@ -662,7 +666,7 @@ const union color DEFAULT_PALETTE[16] = {
|
|||
{ { 0x6e, 0x6e, 0x6e, 0xff } },
|
||||
{ { 0x76, 0x76, 0x76, 0xff } },
|
||||
{ { 0x11, 0x11, 0x11, 0xff } }
|
||||
};
|
||||
);
|
||||
|
||||
const char font_atlas[256][11] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
||||
|
|
Loading…
Reference in New Issue