forked from hkc/cc-stuff
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 character;
|
||||||
unsigned char bg, fg;
|
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 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 {
|
struct arguments {
|
||||||
bool fast_mode;
|
bool fast_mode;
|
||||||
|
@ -76,8 +82,7 @@ struct image {
|
||||||
struct image_pal {
|
struct image_pal {
|
||||||
int w, h;
|
int w, h;
|
||||||
uint8_t *pixels;
|
uint8_t *pixels;
|
||||||
const union color *palette;
|
const struct palette *palette;
|
||||||
size_t palette_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool parse_cmdline(int argc, char **argv);
|
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_load(const char *fp);
|
||||||
struct image *image_new(int w, int h);
|
struct image *image_new(int w, int h);
|
||||||
struct image *image_resize(struct image *original, int new_w, int new_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_difference(union color a, union color b);
|
||||||
float get_color_brightness(union color clr);
|
float get_color_brightness(union color clr);
|
||||||
void image_unload(struct image *img);
|
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?
|
// 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) {
|
switch (args.palette_type) {
|
||||||
case PALETTE_DEFAULT: palette = DEFAULT_PALETTE; break;
|
case PALETTE_DEFAULT: palette = &DEFAULT_PALETTE; break;
|
||||||
case PALETTE_DEFAULT_GRAY: palette = DEFAULT_GRAY_PALETTE; break;
|
case PALETTE_DEFAULT_GRAY: palette = &DEFAULT_GRAY_PALETTE; break;
|
||||||
case PALETTE_AUTO: assert(0 && "Not implemented"); break;
|
case PALETTE_AUTO: assert(0 && "Not implemented"); break;
|
||||||
case PALETTE_LIST: assert(0 && "Not implemented"); break;
|
case PALETTE_LIST: assert(0 && "Not implemented"); break;
|
||||||
case PALETTE_PATH: 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
|
// TODO: actually do stuff
|
||||||
struct cc_char *characters = calloc(args.width * args.height, sizeof(struct cc_char));
|
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) {
|
if (!quantized_image) {
|
||||||
fprintf(stderr, "Error: failed to open the file\n");
|
fprintf(stderr, "Error: failed to open the file\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -217,9 +222,9 @@ int main(int argc, char **argv) {
|
||||||
fputc(args.height, fp);
|
fputc(args.height, fp);
|
||||||
fputc(0x00, fp);
|
fputc(0x00, fp);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
fputc(palette[i].rgba.r, fp);
|
fputc(palette->colors[i].rgba.r, fp);
|
||||||
fputc(palette[i].rgba.g, fp);
|
fputc(palette->colors[i].rgba.g, fp);
|
||||||
fputc(palette[i].rgba.b, fp);
|
fputc(palette->colors[i].rgba.b, fp);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < args.width * args.height; i++) {
|
for (int i = 0; i < args.width * args.height; i++) {
|
||||||
fputc(characters[i].character, fp);
|
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));
|
struct image_pal *out = calloc(1, sizeof(struct image_pal));
|
||||||
out->w = original->w;
|
out->w = original->w;
|
||||||
out->h = original->h;
|
out->h = original->h;
|
||||||
out->pixels = calloc(original->w, original->h);
|
out->pixels = calloc(original->w, original->h);
|
||||||
out->palette = colors;
|
out->palette = palette;
|
||||||
out->palette_size = n_colors;
|
|
||||||
|
|
||||||
for (int i = 0; i < out->w * out->h; i++) {
|
for (int i = 0; i < out->w * out->h; i++) {
|
||||||
int closest_color = 0;
|
int closest_color = 0;
|
||||||
float closest_distance = 1e20;
|
float closest_distance = 1e20;
|
||||||
for (int color = 0; color < n_colors; color++) {
|
for (int color = 0; color < palette->count; color++) {
|
||||||
float dist = get_color_difference(colors[color], original->pixels[i]);
|
float dist = get_color_difference(palette->colors[color], original->pixels[i]);
|
||||||
if (dist <= closest_distance) {
|
if (dist <= closest_distance) {
|
||||||
closest_distance = dist;
|
closest_distance = dist;
|
||||||
closest_color = color;
|
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 oy = 0; oy < 3; oy++) {
|
||||||
for (int ox = 0; ox < 2; ox++) {
|
for (int ox = 0; ox < 2; ox++) {
|
||||||
unsigned char pix = img->pixels[ox + (x + (y * 3 + oy) * w) * 2];
|
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) {
|
if (brightness >= brightest_diff) {
|
||||||
brightest_i = pix;
|
brightest_i = pix;
|
||||||
brightest_diff = brightness;
|
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++) {
|
for (int ox = 0; ox < 2; ox++) {
|
||||||
if (ox == 1 && oy == 2) continue;
|
if (ox == 1 && oy == 2) continue;
|
||||||
unsigned char pix = img->pixels[ox + (x + (y * 3 + oy) * w) * 2];
|
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_bg = get_color_difference(img->palette->colors[darkest_i], img->palette->colors[pix]);
|
||||||
float diff_fg = get_color_difference(img->palette[brightest_i], img->palette[pix]);
|
float diff_fg = get_color_difference(img->palette->colors[brightest_i], img->palette->colors[pix]);
|
||||||
if (diff_fg < diff_bg) {
|
if (diff_fg < diff_bg) {
|
||||||
bitmap |= pixel_bits[oy][ox];
|
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];
|
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_bg = get_color_difference(img->palette->colors[darkest_i], img->palette->colors[pix]);
|
||||||
float diff_fg = get_color_difference(img->palette[brightest_i], img->palette[pix]);
|
float diff_fg = get_color_difference(img->palette->colors[brightest_i], img->palette->colors[pix]);
|
||||||
if (diff_fg < diff_bg) {
|
if (diff_fg < diff_bg) {
|
||||||
bitmap ^= 31;
|
bitmap ^= 31;
|
||||||
unsigned char tmp = darkest_i;
|
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) {
|
void convert_8x11(const struct image_pal *img, struct cc_char *characters) {
|
||||||
int w = img->w / 8, h = img->h / 11;
|
int w = img->w / 8, h = img->h / 11;
|
||||||
float palette_self_diffs[0x100][0x10] = {{(float) 0xffffff}};
|
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 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_size; output_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[input_color], img->palette[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[
|
uint8_t pixel_unresolved = img->pixels[
|
||||||
ox + (x + (y * 11 + oy) * w) * 8
|
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];
|
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 } },
|
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
||||||
{ { 0xf2, 0xb2, 0x33, 0xff } },
|
{ { 0xf2, 0xb2, 0x33, 0xff } },
|
||||||
{ { 0xe5, 0x7f, 0xd8, 0xff } },
|
{ { 0xe5, 0x7f, 0xd8, 0xff } },
|
||||||
|
@ -645,7 +649,7 @@ const union color DEFAULT_PALETTE[16] = {
|
||||||
{ { 0x57, 0xa6, 0x4e, 0xff } },
|
{ { 0x57, 0xa6, 0x4e, 0xff } },
|
||||||
{ { 0xcc, 0x4c, 0x4c, 0xff } },
|
{ { 0xcc, 0x4c, 0x4c, 0xff } },
|
||||||
{ { 0x11, 0x11, 0x11, 0xff } }
|
{ { 0x11, 0x11, 0x11, 0xff } }
|
||||||
}, DEFAULT_GRAY_PALETTE[16] = {
|
), DEFAULT_GRAY_PALETTE = PALETTE(
|
||||||
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
||||||
{ { 0x9d, 0x9d, 0x9d, 0xff } },
|
{ { 0x9d, 0x9d, 0x9d, 0xff } },
|
||||||
{ { 0xbe, 0xbe, 0xbe, 0xff } },
|
{ { 0xbe, 0xbe, 0xbe, 0xff } },
|
||||||
|
@ -662,7 +666,7 @@ const union color DEFAULT_PALETTE[16] = {
|
||||||
{ { 0x6e, 0x6e, 0x6e, 0xff } },
|
{ { 0x6e, 0x6e, 0x6e, 0xff } },
|
||||||
{ { 0x76, 0x76, 0x76, 0xff } },
|
{ { 0x76, 0x76, 0x76, 0xff } },
|
||||||
{ { 0x11, 0x11, 0x11, 0xff } }
|
{ { 0x11, 0x11, 0x11, 0xff } }
|
||||||
};
|
);
|
||||||
|
|
||||||
const char font_atlas[256][11] = {
|
const char font_atlas[256][11] = {
|
||||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
||||||
|
|
Loading…
Reference in New Issue