QuantPngQuant.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * The Python Imaging Library
  3. * $Id$
  4. *
  5. * quantization using libimagequant, a part of pngquant.
  6. *
  7. * Copyright (c) 2016 Marcin Kurczewski <rr-@sakuya.pl>
  8. *
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "QuantPngQuant.h"
  14. #ifdef HAVE_LIBIMAGEQUANT
  15. #error #include "libimagequant.h"
  16. int
  17. quantize_pngquant(
  18. Pixel *pixelData,
  19. int width,
  20. int height,
  21. uint32_t quantPixels,
  22. Pixel **palette,
  23. uint32_t *paletteLength,
  24. uint32_t **quantizedPixels,
  25. int withAlpha)
  26. {
  27. int result = 0;
  28. liq_image *image = NULL;
  29. liq_attr *attr = NULL;
  30. liq_result *remap = NULL;
  31. unsigned char *charMatrix = NULL;
  32. unsigned char **charMatrixRows = NULL;
  33. unsigned int i, y;
  34. *palette = NULL;
  35. *paletteLength = 0;
  36. *quantizedPixels = NULL;
  37. /* configure pngquant */
  38. attr = liq_attr_create();
  39. if (!attr) { goto err; }
  40. if (quantPixels) {
  41. liq_set_max_colors(attr, quantPixels);
  42. }
  43. /* prepare input image */
  44. image = liq_image_create_rgba(
  45. attr,
  46. pixelData,
  47. width,
  48. height,
  49. 0.45455 /* gamma */);
  50. if (!image) { goto err; }
  51. /* quantize the image */
  52. remap = liq_quantize_image(attr, image);
  53. if (!remap) { goto err; }
  54. liq_set_output_gamma(remap, 0.45455);
  55. liq_set_dithering_level(remap, 1);
  56. /* write output palette */
  57. const liq_palette *l_palette = liq_get_palette(remap);
  58. *paletteLength = l_palette->count;
  59. *palette = malloc(sizeof(Pixel) * l_palette->count);
  60. if (!*palette) { goto err; }
  61. for (i = 0; i < l_palette->count; i++) {
  62. (*palette)[i].c.b = l_palette->entries[i].b;
  63. (*palette)[i].c.g = l_palette->entries[i].g;
  64. (*palette)[i].c.r = l_palette->entries[i].r;
  65. (*palette)[i].c.a = l_palette->entries[i].a;
  66. }
  67. /* write output pixels (pngquant uses char array) */
  68. charMatrix = malloc(width * height);
  69. if (!charMatrix) { goto err; }
  70. charMatrixRows = malloc(height * sizeof(unsigned char*));
  71. if (!charMatrixRows) { goto err; }
  72. for (y = 0; y < height; y++) {
  73. charMatrixRows[y] = &charMatrix[y * width];
  74. }
  75. if (LIQ_OK != liq_write_remapped_image_rows(remap, image, charMatrixRows)) {
  76. goto err;
  77. }
  78. /* transcribe output pixels (pillow uses uint32_t array) */
  79. *quantizedPixels = malloc(sizeof(uint32_t) * width * height);
  80. if (!*quantizedPixels) { goto err; }
  81. for (i = 0; i < width * height; i++) {
  82. (*quantizedPixels)[i] = charMatrix[i];
  83. }
  84. result = 1;
  85. err:
  86. if (attr) liq_attr_destroy(attr);
  87. if (image) liq_image_destroy(image);
  88. if (remap) liq_result_destroy(remap);
  89. free(charMatrix);
  90. free(charMatrixRows);
  91. if (!result) {
  92. free(*quantizedPixels);
  93. free(*palette);
  94. }
  95. return result;
  96. }
  97. #endif