forked from hkc/cc-stuff
Compare commits
2 Commits
c5af524dac
...
5f95f895d2
Author | SHA1 | Date |
---|---|---|
Vftdan | 5f95f895d2 | |
Vftdan | c91f4d79bd |
23
img2cpi.c
23
img2cpi.c
|
@ -95,6 +95,8 @@ struct k_means_state {
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
} sums;
|
} sums;
|
||||||
size_t count;
|
size_t count;
|
||||||
|
union color closest_present_item;
|
||||||
|
float closest_present_distance;
|
||||||
} *centroid_intermediate;
|
} *centroid_intermediate;
|
||||||
size_t item_count;
|
size_t item_count;
|
||||||
};
|
};
|
||||||
|
@ -675,13 +677,20 @@ struct palette *custom_palette_from(const struct palette *orig) {
|
||||||
|
|
||||||
struct k_means_state k_means_init(const struct image *image, struct palette *starting_palette) {
|
struct k_means_state k_means_init(const struct image *image, struct palette *starting_palette) {
|
||||||
size_t item_count = image->w * image->h;
|
size_t item_count = image->w * image->h;
|
||||||
|
uint8_t cluster_count = starting_palette->count;
|
||||||
struct k_means_state state = {
|
struct k_means_state state = {
|
||||||
.items = image,
|
.items = image,
|
||||||
.clusters = starting_palette,
|
.clusters = starting_palette,
|
||||||
.predicted_cluster = calloc(image->w, image->h),
|
.predicted_cluster = calloc(image->w, image->h),
|
||||||
.centroid_intermediate = calloc(item_count, sizeof(struct k_means_centroid_intermediate)),
|
.centroid_intermediate = calloc(cluster_count, sizeof(struct k_means_centroid_intermediate)),
|
||||||
.item_count = item_count,
|
.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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,11 +705,16 @@ bool k_means_iteration(struct k_means_state *state) {
|
||||||
int closest_cluster = 0;
|
int closest_cluster = 0;
|
||||||
float closest_distance = 1e20;
|
float closest_distance = 1e20;
|
||||||
for (int cluster = 0; cluster < state->clusters->count; cluster++) {
|
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) {
|
if (dist <= closest_distance) {
|
||||||
closest_distance = dist;
|
closest_distance = dist;
|
||||||
closest_cluster = cluster;
|
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) {
|
if (!changed) {
|
||||||
changed = state->predicted_cluster[i] != closest_cluster;
|
changed = state->predicted_cluster[i] != closest_cluster;
|
||||||
|
@ -730,9 +744,10 @@ bool k_means_iteration(struct k_means_state *state) {
|
||||||
state->clusters->colors[i] = centroid;
|
state->clusters->colors[i] = centroid;
|
||||||
} else {
|
} else {
|
||||||
// No pixels are closest to this color
|
// 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;
|
return changed;
|
||||||
|
|
Loading…
Reference in New Issue