/* See LICENSE file for copyright and license details. */ #include "liblss16.h" #include #if defined(__clang__) # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" #endif void liblss16_optimise(struct liblss16_header *header, uint8_t *pixels) { uint8_t remap[16], unmap[16], ncolours = 0, colour, preferred, dummy = 0; unsigned x, y, count, width; size_t p, n; int32_t zero[16], nonzero[16]; int32_t zero_penalty, least; for (x = 0; x < 16U; x++) { remap[x] = (uint8_t)x; unmap[x] = 0; } memset(zero, 0, sizeof(zero)); memset(nonzero, 0, sizeof(nonzero)); for (x = 0; x < 15U; x++) { if (unmap[x]) continue; header->colour_map[ncolours++] = header->colour_map[x]; for (y = x + 1U; y < 16U; y++) { if (header->colour_map[y].r != header->colour_map[x].r || header->colour_map[y].g != header->colour_map[x].g || header->colour_map[y].b != header->colour_map[x].b) continue; unmap[y] = 1; remap[y] = ncolours; } } width = (unsigned)header->width; width = width < 17U ? width : 17U; for (y = 0, p = 0; y < (unsigned)header->height; y++) { #ifdef HARDEN for (x = 0; x < (unsigned)header->width; x++) pixels[p + x] &= 15U; #endif colour = remap[pixels[p]]; count = 1U; for (x = 1U; x < width; x++, p++) { if (remap[pixels[p]] != colour) break; count += 1U; } p += (size_t)header->width - (size_t)x; zero[colour] += count < 16U ? 2 : 3; nonzero[colour] += count == 1 ? 1 : count < 17 ? 3 : 4; } least = zero[0] - nonzero[0]; preferred = 0U; if (ncolours < 16U) dummy = ncolours++; for (x = 1U; x < (unsigned)ncolours; x++) { zero_penalty = zero[x] - nonzero[x]; if (zero_penalty < least) { least = zero_penalty; preferred = (uint8_t)x; } } if (preferred) { struct liblss16_colour tc; uint8_t t8; tc = header->colour_map[preferred]; header->colour_map[preferred] = header->colour_map[0]; header->colour_map[0] = tc; t8 = remap[preferred]; remap[preferred] = remap[0]; remap[0] = t8; if (preferred == dummy) { header->colour_map[0].r = header->colour_map[1].r; header->colour_map[0].g = header->colour_map[1].r; header->colour_map[0].b = header->colour_map[1].r; } } n = p; for (n = p, p = 0; p < n; p++) pixels[p] = remap[pixels[p]]; memset(&header->colour_map[ncolours], header->colour_map[ncolours - 1U].b, (16U - ncolours) * sizeof(*header->colour_map)); }