diff options
author | Bad Diode <bd@badd10de.dev> | 2021-04-20 11:36:16 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-04-20 11:36:16 +0200 |
commit | e649308594354a6fc3553e9faeb733e3776d3c26 (patch) | |
tree | ae832937faa6a98a104d8c321a6e7891305bac2f | |
parent | c2080e499ab119c70f3fc7c6122bdf0751153986 (diff) | |
download | gba-dev-tools-e649308594354a6fc3553e9faeb733e3776d3c26.tar.gz gba-dev-tools-e649308594354a6fc3553e9faeb733e3776d3c26.zip |
Add similarity search for colors when palette is full
-rw-r--r-- | src/main.c | 42 |
1 files changed, 32 insertions, 10 deletions
@@ -105,14 +105,39 @@ extract_tile(Tiles *tiles, Palette *palette, Image *img, | |||
105 | 105 | ||
106 | Color clr = rgb15(red, green, blue); | 106 | Color clr = rgb15(red, green, blue); |
107 | bool found = false; | 107 | bool found = false; |
108 | // TODO: If the palette is full, find the closest perceived | 108 | // Brute force search, but since the palette size will likely be |
109 | // color instead. | 109 | // small, shouldn't be a big problem. |
110 | for (size_t p = 0; p < palette->capacity; ++p) { | 110 | if (palette->size < palette->capacity) { |
111 | if (clr == palette->data[p]) { | 111 | // If the palette is not full try to find if the color is |
112 | pal_index = p; | 112 | // already stored. |
113 | found = true; | 113 | for (size_t p = 0; p < palette->capacity; ++p) { |
114 | break; | 114 | if (clr == palette->data[p]) { |
115 | pal_index = p; | ||
116 | found = true; | ||
117 | break; | ||
118 | } | ||
115 | } | 119 | } |
120 | } else { | ||
121 | // If the palette is full, find the closest perceived color | ||
122 | // instead. | ||
123 | size_t best_index = 0; | ||
124 | double best_distance = 1e99; | ||
125 | for (size_t p = 0; p < palette->capacity; ++p) { | ||
126 | Color pal_clr = palette->data[p]; | ||
127 | int pal_red = pal_clr & 0x1F; | ||
128 | int pal_green = (pal_clr >> 5) & 0x1F; | ||
129 | int pal_blue = (pal_clr >> 10) & 0x1F; | ||
130 | double r = (pal_red - red); | ||
131 | double g = (pal_green - green); | ||
132 | double b = (pal_blue - blue); | ||
133 | double distance = r * r * 0.3 + g * g * 0.59 + b * b * 0.11; | ||
134 | if (distance < best_distance) { | ||
135 | best_distance = distance; | ||
136 | best_index = p; | ||
137 | } | ||
138 | } | ||
139 | pal_index = best_index; | ||
140 | found = true; | ||
116 | } | 141 | } |
117 | if (!found) { | 142 | if (!found) { |
118 | palette->data[palette->size++] = clr; | 143 | palette->data[palette->size++] = clr; |
@@ -217,9 +242,6 @@ main(int argc, char *argv[]) { | |||
217 | .capacity = n_tiles, | 242 | .capacity = n_tiles, |
218 | }; | 243 | }; |
219 | 244 | ||
220 | // NOTE: We are going to brute-force this for now. Checking if the color is | ||
221 | // in the palette and add it to the next slot if possible. In the future we | ||
222 | // may want to use a hash-table instead. | ||
223 | int pal_idx = 1; | 245 | int pal_idx = 1; |
224 | int offset_x = 0; | 246 | int offset_x = 0; |
225 | int offset_y = 0; | 247 | int offset_y = 0; |