From 6ebe98e94ccb75d081978d05e454597819a7ee20 Mon Sep 17 00:00:00 2001 From: Vftdan Date: Thu, 3 Oct 2024 19:36:56 +0200 Subject: [PATCH] [WIP] attempt at factoring out font_atlas linear search For an unknown reason the result is different --- img2cpi.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/img2cpi.c b/img2cpi.c index 01509c9..12a637b 100644 --- a/img2cpi.c +++ b/img2cpi.c @@ -125,6 +125,8 @@ bool k_means_iteration(struct k_means_state *state); void k_means_end(struct k_means_state *state); struct palette *palette_k_means(const struct image *image, const struct palette *prototype); +inline static uint8_t closest_chunk_color_symbol(const typeof(float[8][11][0x10]) *chunk_palette_diffs, uint8_t color_pair); + const char *known_file_extensions[] = { ".png", ".jpg", ".jpeg", ".jfif", ".jpg", ".gif", ".tga", ".bmp", ".hdr", ".pnm", 0 @@ -631,11 +633,9 @@ void convert_8x11(const struct image_pal *img, struct cc_char *characters) { float min_diff = 0xffffff; char closest_sym = 0x00, closest_color = 0xae; - for (int sym = 0x01; sym <= 0xFF; sym++) { - if (sym == '\t' || sym == '\n' || sym == '\r' || sym == '\x0e') { - continue; - } - for (int color = 0x00; color <= 0xff; color++) { + for (int color = 0x00; color <= 0xff; color++) { + { + const int sym = closest_chunk_color_symbol(&chunk_palette_diffs, color); float difference = 0; for (int oy = 0; oy < 11; oy++) { unsigned char sym_line = font_atlas[sym][oy]; @@ -793,6 +793,60 @@ struct palette *palette_k_means(const struct image *image, const struct palette return palette; } +inline static float weighted_glyph_hamming_distance(const GlyphBitmap *lhs, const GlyphBitmap *rhs, typeof(float[11][8]) *weights) { + float dist = 0; + for (int oy = 0; oy < 11; oy++) { + uint8_t sym_line = (*lhs)[oy] ^ (*rhs)[oy]; + for (int ox = 0; ox < 8; ox++) { + bool lit = sym_line & (0x80 >> ox); + if (lit) { + dist += (*weights)[oy][ox]; + } + } + } + return dist; +} + +uint8_t closest_glyph_symbol(const GlyphBitmap *target, typeof(float[11][8]) *weights) { + uint8_t best = 0x01; + float best_dist = weighted_glyph_hamming_distance(target, &font_atlas[best], weights); + for (int sym = 0x02; sym <= 0xFF; sym++) { + if (sym == '\t' || sym == '\n' || sym == '\r' || sym == '\x0e') { + continue; + } + float dist = weighted_glyph_hamming_distance(target, &font_atlas[best], weights); + if (dist <= best_dist) { + best_dist = dist; + best = sym; + } + } + return best; +} + +void construct_chunk_color_glyph(GlyphBitmap *result, typeof(float[11][8]) *weights, const typeof(float[8][11][0x10]) *chunk_palette_diffs, uint8_t color_pair) { + uint8_t fg = color_pair >> 4, + bg = color_pair & 0xF; + for (int oy = 0; oy < 11; oy++) { + uint8_t sym_line = 0; + for (int ox = 0; ox < 8; ox++) { + float dist_diff = (*chunk_palette_diffs)[ox][oy][fg] - (*chunk_palette_diffs)[ox][oy][bg]; + uint8_t lit = dist_diff > 0; + sym_line |= lit << (7 - ox); + if (weights) { + (*weights)[oy][ox] = lit ? dist_diff : -dist_diff; + } + } + (*result)[oy] = sym_line; + } +} + +uint8_t closest_chunk_color_symbol(const typeof(float[8][11][0x10]) *chunk_palette_diffs, uint8_t color_pair) { + GlyphBitmap glyph; + float weights[11][8]; + construct_chunk_color_glyph(&glyph, &weights, chunk_palette_diffs, color_pair); + return closest_glyph_symbol(&glyph, &weights); +} + const struct palette DEFAULT_PALETTE = PALETTE( { { 0xf0, 0xf0, 0xf0, 0xff } }, { { 0xf2, 0xb2, 0x33, 0xff } },