Pillow/src/libImaging/QuantPngQuant.c
2021-01-03 14:17:51 +11:00

133 lines
3.1 KiB
C

/*
* The Python Imaging Library
* $Id$
*
* quantization using libimagequant, a part of pngquant.
*
* Copyright (c) 2016 Marcin Kurczewski <rr-@sakuya.pl>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "QuantPngQuant.h"
#ifdef HAVE_LIBIMAGEQUANT
#include "libimagequant.h"
int
quantize_pngquant(
Pixel *pixelData,
unsigned int width,
unsigned int height,
uint32_t quantPixels,
Pixel **palette,
uint32_t *paletteLength,
uint32_t **quantizedPixels,
int withAlpha) {
int result = 0;
liq_image *image = NULL;
liq_attr *attr = NULL;
liq_result *remap = NULL;
unsigned char *charMatrix = NULL;
unsigned char **charMatrixRows = NULL;
unsigned int i, y;
*palette = NULL;
*paletteLength = 0;
*quantizedPixels = NULL;
/* configure pngquant */
attr = liq_attr_create();
if (!attr) {
goto err;
}
if (quantPixels) {
liq_set_max_colors(attr, quantPixels);
}
/* prepare input image */
image = liq_image_create_rgba(attr, pixelData, width, height, 0.45455 /* gamma */);
if (!image) {
goto err;
}
/* quantize the image */
remap = liq_quantize_image(attr, image);
if (!remap) {
goto err;
}
liq_set_output_gamma(remap, 0.45455);
liq_set_dithering_level(remap, 1);
/* write output palette */
const liq_palette *l_palette = liq_get_palette(remap);
*paletteLength = l_palette->count;
*palette = malloc(sizeof(Pixel) * l_palette->count);
if (!*palette) {
goto err;
}
for (i = 0; i < l_palette->count; i++) {
(*palette)[i].c.b = l_palette->entries[i].b;
(*palette)[i].c.g = l_palette->entries[i].g;
(*palette)[i].c.r = l_palette->entries[i].r;
(*palette)[i].c.a = l_palette->entries[i].a;
}
/* write output pixels (pngquant uses char array) */
charMatrix = malloc(width * height);
if (!charMatrix) {
goto err;
}
charMatrixRows = malloc(height * sizeof(unsigned char *));
if (!charMatrixRows) {
goto err;
}
for (y = 0; y < height; y++) {
charMatrixRows[y] = &charMatrix[y * width];
}
if (LIQ_OK != liq_write_remapped_image_rows(remap, image, charMatrixRows)) {
goto err;
}
/* transcribe output pixels (pillow uses uint32_t array) */
*quantizedPixels = malloc(sizeof(uint32_t) * width * height);
if (!*quantizedPixels) {
goto err;
}
for (i = 0; i < width * height; i++) {
(*quantizedPixels)[i] = charMatrix[i];
}
result = 1;
err:
if (attr) {
liq_attr_destroy(attr);
}
if (image) {
liq_image_destroy(image);
}
if (remap) {
liq_result_destroy(remap);
}
free(charMatrix);
free(charMatrixRows);
if (!result) {
free(*quantizedPixels);
free(*palette);
}
return result;
}
const char *
ImagingImageQuantVersion(void) {
static char version[20];
int number = liq_version();
sprintf(version, "%d.%d.%d", number / 10000, (number / 100) % 100, number % 100);
return version;
}
#endif