diff --git a/img2cpi.c b/img2cpi.c index af339bc..960bb54 100644 --- a/img2cpi.c +++ b/img2cpi.c @@ -95,6 +95,8 @@ struct k_means_state { float r, g, b; } sums; size_t count; + union color closest_present_item; + float closest_present_distance; } *centroid_intermediate; size_t item_count; }; @@ -683,6 +685,12 @@ struct k_means_state k_means_init(const struct image *image, struct palette *sta .centroid_intermediate = calloc(cluster_count, sizeof(struct k_means_centroid_intermediate)), .item_count = item_count, }; + if (state.centroid_intermediate) { + for (size_t i = 0; i < cluster_count; i++) { + state.centroid_intermediate[i].closest_present_item = starting_palette->colors[i]; + state.centroid_intermediate[i].closest_present_distance = 1e20; + } + } return state; } @@ -697,11 +705,16 @@ bool k_means_iteration(struct k_means_state *state) { int closest_cluster = 0; float closest_distance = 1e20; for (int cluster = 0; cluster < state->clusters->count; cluster++) { - float dist = get_color_difference(state->clusters->colors[cluster], state->items->pixels[i]); + union color item = state->items->pixels[i]; + float dist = get_color_difference(state->clusters->colors[cluster], item); if (dist <= closest_distance) { closest_distance = dist; closest_cluster = cluster; } + if (dist <= state->centroid_intermediate[cluster].closest_present_distance) { + state->centroid_intermediate[cluster].closest_present_item = item; + state->centroid_intermediate[cluster].closest_present_distance = dist; + } } if (!changed) { changed = state->predicted_cluster[i] != closest_cluster; @@ -731,9 +744,10 @@ bool k_means_iteration(struct k_means_state *state) { state->clusters->colors[i] = centroid; } else { // No pixels are closest to this color - // TODO: wiggle the centroid? + // Warp the centroid onto the closest item + state->clusters->colors[i] = intermediate.closest_present_item; } - state->centroid_intermediate[i] = (struct k_means_centroid_intermediate) { .sums = {0, 0, 0}, .count = 0 }; + state->centroid_intermediate[i] = (struct k_means_centroid_intermediate) { .sums = {0, 0, 0}, .count = 0, .closest_present_item = state->clusters->colors[i], .closest_present_distance = 1e20 }; } return changed;