/* * Copyright (C) 2025 sillysagiri * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "header.hpp" ImageMapped Quantize(const Image &image, Palette &palette_output, int num_colors, bool dither, uint8_t format) { liq_attr *attr = liq_attr_create(); liq_set_max_colors(attr, num_colors); liq_set_speed(attr, 1); liq_set_quality(attr, 0, 100); liq_image *liq_img = liq_image_create_rgba(attr, image.data.data(), image.width, image.height, 0); liq_result *result; if (LIQ_OK != liq_image_quantize(liq_img, attr, &result)) throw std::runtime_error("failed to quantize histogram"); if (dither) liq_set_dithering_level(result, 1.0f); else liq_set_dithering_level(result, 0.0f); ImageMapped output(image.width*image.height); if (LIQ_OK != liq_write_remapped_image(result, liq_img, output.data(), output.size())) throw std::runtime_error("failed to remap image"); const liq_palette *pal = liq_get_palette(result); palette_output.resize(pal->count); for (int i=0; icount; i++) { palette_output[i].r = pal->entries[i].r; palette_output[i].g = pal->entries[i].g; palette_output[i].b = pal->entries[i].b; palette_output[i].a = pal->entries[i].a; } liq_image_destroy(liq_img); liq_attr_destroy(attr); liq_result_destroy(result); // --- if (format == Format_INDEXED_4) { ImageMapped packed; packed.reserve((output.size()+3) / 4); for (int chunk_start=0; chunk_start> 3; current_byte |= (output[offset] & 0b111) | (alpha << 3); packed.push_back(current_byte); } return packed; } else if (format == Format_INDEXED_32A8) { ImageMapped packed(output.size()); packed.reserve((output.size()+3) / 4); for (int offset=0; offset> 5; current_byte |= (output[offset] & 0b11111) | (alpha << 5); packed.push_back(current_byte); } return packed; } return output; }