QuantPngQuant.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. #include "libimagequant.h"
  16. int
  17. quantize_pngquant(
  18. Pixel *pixelData,
  19. unsigned int width,
  20. unsigned int height,
  21. uint32_t quantPixels,
  22. Pixel **palette,
  23. uint32_t *paletteLength,
  24. uint32_t **quantizedPixels,
  25. int withAlpha) {
  26. int result = 0;
  27. liq_image *image = NULL;
  28. liq_attr *attr = NULL;
  29. liq_result *remap = NULL;
  30. unsigned char *charMatrix = NULL;
  31. unsigned char **charMatrixRows = NULL;
  32. unsigned int i, y;
  33. *palette = NULL;
  34. *paletteLength = 0;
  35. *quantizedPixels = NULL;
  36. /* configure pngquant */
  37. attr = liq_attr_create();
  38. if (!attr) {
  39. goto err;
  40. }
  41. if (quantPixels) {
  42. liq_set_max_colors(attr, quantPixels);
  43. }
  44. /* prepare input image */
  45. image = liq_image_create_rgba(attr, pixelData, width, height, 0.45455 /* gamma */);
  46. if (!image) {
  47. goto err;
  48. }
  49. /* quantize the image */
  50. remap = liq_quantize_image(attr, image);
  51. if (!remap) {
  52. goto err;
  53. }
  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) {
  61. goto err;
  62. }
  63. for (i = 0; i < l_palette->count; i++) {
  64. (*palette)[i].c.b = l_palette->entries[i].b;
  65. (*palette)[i].c.g = l_palette->entries[i].g;
  66. (*palette)[i].c.r = l_palette->entries[i].r;
  67. (*palette)[i].c.a = l_palette->entries[i].a;
  68. }
  69. /* write output pixels (pngquant uses char array) */
  70. charMatrix = malloc(width * height);
  71. if (!charMatrix) {
  72. goto err;
  73. }
  74. charMatrixRows = malloc(height * sizeof(unsigned char *));
  75. if (!charMatrixRows) {
  76. goto err;
  77. }
  78. for (y = 0; y < height; y++) {
  79. charMatrixRows[y] = &charMatrix[y * width];
  80. }
  81. if (LIQ_OK != liq_write_remapped_image_rows(remap, image, charMatrixRows)) {
  82. goto err;
  83. }
  84. /* transcribe output pixels (pillow uses uint32_t array) */
  85. *quantizedPixels = malloc(sizeof(uint32_t) * width * height);
  86. if (!*quantizedPixels) {
  87. goto err;
  88. }
  89. for (i = 0; i < width * height; i++) {
  90. (*quantizedPixels)[i] = charMatrix[i];
  91. }
  92. result = 1;
  93. err:
  94. if (attr) {
  95. liq_attr_destroy(attr);
  96. }
  97. if (image) {
  98. liq_image_destroy(image);
  99. }
  100. if (remap) {
  101. liq_result_destroy(remap);
  102. }
  103. free(charMatrix);
  104. free(charMatrixRows);
  105. if (!result) {
  106. free(*quantizedPixels);
  107. free(*palette);
  108. }
  109. return result;
  110. }
  111. const char *
  112. ImagingImageQuantVersion(void) {
  113. static char version[20];
  114. int number = liq_version();
  115. sprintf(version, "%d.%d.%d", number / 10000, (number / 100) % 100, number % 100);
  116. return version;
  117. }
  118. #endif