Dedicated palette type that also stores own length

This commit is contained in:
Vftdan 2024-10-02 23:17:29 +02:00
parent e8c53b1f9b
commit d9f4362615
1 changed files with 32 additions and 28 deletions

View File

@ -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, },