20
15
f_pixel vantage_point;
22
17
unsigned int num_candidates;
23
struct color_entry *candidates;
18
f_pixel *candidates_color;
19
unsigned short *candidates_index;
26
22
struct nearest_map {
28
23
const colormap *map;
29
24
float nearest_other_color_dist[256];
33
static int find_slow(const f_pixel px, const colormap *map)
29
static unsigned int find_slow(const f_pixel px, const colormap *map)
36
32
float bestdiff = colordifference(px, map->palette[0].acolor);
38
34
for(unsigned int i=1; i < map->colors; i++) {
83
79
num_candidates = MIN(colorsused, num_candidates);
86
.candidates = mempool_alloc(m, num_candidates * sizeof(h.candidates[0]), 0),
82
.candidates_color = mempool_alloc(m, num_candidates * sizeof(h.candidates_color[0]), 0),
83
.candidates_index = mempool_alloc(m, num_candidates * sizeof(h.candidates_index[0]), 0),
87
84
.vantage_point = px,
88
85
.num_candidates = num_candidates,
90
87
for(unsigned int i=0; i < num_candidates; i++) {
91
h.candidates[i] = (struct color_entry) {
92
.color = map->palette[colors[i].index].acolor,
93
.index = colors[i].index,
88
h.candidates_color[i] = map->palette[colors[i].index].acolor;
89
h.candidates_index[i] = colors[i].index;
96
91
// if all colors within this radius are included in candidates, then there cannot be any other better match
97
92
// farther away from the vantage point than half of the radius. Due to alpha channel must assume pessimistic radius.
98
h.radius = min_colordifference(px, h.candidates[num_candidates-1].color)/4.0f; // /4 = half of radius, but radius is squared
93
h.radius = min_colordifference(px, h.candidates_color[num_candidates-1])/4.0f; // /4 = half of radius, but radius is squared
100
95
for(unsigned int i=0; i < num_candidates; i++) {
101
96
// divide again as that's matching certain subset within radius-limited subset
127
122
LIQ_PRIVATE struct nearest_map *nearest_init(const colormap *map, bool fast)
129
124
colormap *subset_palette = get_subset_palette(map);
125
const unsigned int num_vantage_points = map->colors > 16 ? MIN(map->colors/4, subset_palette->colors) : 0;
126
const unsigned long heads_size = sizeof(struct head) * (num_vantage_points+1); // +1 is fallback head
131
const unsigned long mempool_size = sizeof(struct color_entry) * subset_palette->colors * map->colors/5 + (1<<14);
128
const unsigned long mempool_size = (sizeof(f_pixel) + sizeof(unsigned int)) * subset_palette->colors * map->colors/5 + (1<<14);
132
129
mempool m = NULL;
133
struct nearest_map *centroids = mempool_create(&m, sizeof(*centroids), mempool_size, map->malloc, map->free);
130
struct nearest_map *centroids = mempool_create(&m, sizeof(*centroids) + heads_size /* heads array is appended to it */, mempool_size, map->malloc, map->free);
134
131
centroids->mempool = m;
136
133
for(unsigned int i=0; i < map->colors; i++) {
144
141
assert(map->colors > 0);
145
142
bool skip_index[map->colors]; for(unsigned int j=0; j < map->colors; j++) skip_index[j]=false;
148
const unsigned int num_vantage_points = map->colors > 16 ? MIN(map->colors/4, subset_palette->colors) : 0;
149
centroids->heads = mempool_alloc(¢roids->mempool, sizeof(centroids->heads[0])*(num_vantage_points+1), mempool_size); // +1 is fallback head
151
144
// floats and colordifference calculations are not perfect
152
145
const float error_margin = fast ? 0 : 8.f/256.f/256.f;
153
146
unsigned int h=0;
216
209
if (vantage_point_dist <= heads[i].radius) {
217
210
assert(heads[i].num_candidates);
218
211
unsigned int ind=0;
219
float dist = colordifference(px, heads[i].candidates[0].color);
212
float dist = colordifference(px, heads[i].candidates_color[0]);
221
214
/* penalty for making holes in IE */
222
if (iebug && heads[i].candidates[0].color.a < 1) {
215
if (iebug && heads[i].candidates_color[0].a < 1) {
223
216
dist += 1.f/1024.f;
226
219
for(unsigned int j=1; j < heads[i].num_candidates; j++) {
227
float newdist = colordifference(px, heads[i].candidates[j].color);
220
float newdist = colordifference(px, heads[i].candidates_color[j]);
229
222
/* penalty for making holes in IE */
230
if (iebug && heads[i].candidates[j].color.a < 1) {
223
if (iebug && heads[i].candidates_color[j].a < 1) {
231
224
newdist += 1.f/1024.f;