Palette.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. * The Python Imaging Library
  3. * $Id$
  4. *
  5. * imaging palette object
  6. *
  7. * history:
  8. * 1996-05-05 fl Added to library
  9. * 1996-05-27 fl Added colour mapping stuff
  10. * 1997-05-12 fl Support RGBA palettes
  11. * 2005-02-09 fl Removed grayscale entries from web palette
  12. *
  13. * Copyright (c) Secret Labs AB 1997-2005. All rights reserved.
  14. * Copyright (c) Fredrik Lundh 1995-1997.
  15. *
  16. * See the README file for information on usage and redistribution.
  17. */
  18. #include "Imaging.h"
  19. #include <math.h>
  20. ImagingPalette
  21. ImagingPaletteNew(const char *mode) {
  22. /* Create a palette object */
  23. int i;
  24. ImagingPalette palette;
  25. if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) {
  26. return (ImagingPalette)ImagingError_ModeError();
  27. }
  28. palette = calloc(1, sizeof(struct ImagingPaletteInstance));
  29. if (!palette) {
  30. return (ImagingPalette)ImagingError_MemoryError();
  31. }
  32. strncpy(palette->mode, mode, IMAGING_MODE_LENGTH - 1);
  33. palette->mode[IMAGING_MODE_LENGTH - 1] = 0;
  34. palette->size = 0;
  35. for (i = 0; i < 256; i++) {
  36. palette->palette[i * 4 + 3] = 255; /* opaque */
  37. }
  38. return palette;
  39. }
  40. ImagingPalette
  41. ImagingPaletteNewBrowser(void) {
  42. /* Create a standard "browser" palette object */
  43. int i, r, g, b;
  44. ImagingPalette palette;
  45. palette = ImagingPaletteNew("RGB");
  46. if (!palette) {
  47. return NULL;
  48. }
  49. /* FIXME: Add 10-level windows palette here? */
  50. /* Simple 6x6x6 colour cube */
  51. i = 10;
  52. for (b = 0; b < 256; b += 51) {
  53. for (g = 0; g < 256; g += 51) {
  54. for (r = 0; r < 256; r += 51) {
  55. palette->palette[i * 4 + 0] = r;
  56. palette->palette[i * 4 + 1] = g;
  57. palette->palette[i * 4 + 2] = b;
  58. i++;
  59. }
  60. }
  61. }
  62. palette->size = i;
  63. /* FIXME: add 30-level grayscale wedge here? */
  64. return palette;
  65. }
  66. ImagingPalette
  67. ImagingPaletteDuplicate(ImagingPalette palette) {
  68. /* Duplicate palette descriptor */
  69. ImagingPalette new_palette;
  70. if (!palette) {
  71. return NULL;
  72. }
  73. /* malloc check ok, small constant allocation */
  74. new_palette = malloc(sizeof(struct ImagingPaletteInstance));
  75. if (!new_palette) {
  76. return (ImagingPalette)ImagingError_MemoryError();
  77. }
  78. memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
  79. /* Don't share the cache */
  80. new_palette->cache = NULL;
  81. return new_palette;
  82. }
  83. void
  84. ImagingPaletteDelete(ImagingPalette palette) {
  85. /* Destroy palette object */
  86. if (palette) {
  87. if (palette->cache) {
  88. free(palette->cache);
  89. }
  90. free(palette);
  91. }
  92. }
  93. /* -------------------------------------------------------------------- */
  94. /* Colour mapping */
  95. /* -------------------------------------------------------------------- */
  96. /* This code is used to map RGB triplets to palette indices, using
  97. a palette index cache. */
  98. /*
  99. * This implementation is loosely based on the corresponding code in
  100. * the IJG JPEG library by Thomas G. Lane. Original algorithms by
  101. * Paul Heckbert and Spencer W. Thomas.
  102. *
  103. * The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */
  104. #define DIST(a, b, s) (a - b) * (a - b) * s
  105. /* Colour weights (no scaling, for now) */
  106. #define RSCALE 1
  107. #define GSCALE 1
  108. #define BSCALE 1
  109. /* Calculated scaled distances */
  110. #define RDIST(a, b) DIST(a, b, RSCALE *RSCALE)
  111. #define GDIST(a, b) DIST(a, b, GSCALE *GSCALE)
  112. #define BDIST(a, b) DIST(a, b, BSCALE *BSCALE)
  113. /* Incremental steps */
  114. #define RSTEP (4 * RSCALE)
  115. #define GSTEP (4 * GSCALE)
  116. #define BSTEP (4 * BSCALE)
  117. #define BOX 8
  118. #define BOXVOLUME BOX *BOX *BOX
  119. void
  120. ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) {
  121. int i, j;
  122. unsigned int dmin[256], dmax;
  123. int r0, g0, b0;
  124. int r1, g1, b1;
  125. int rc, gc, bc;
  126. unsigned int d[BOXVOLUME];
  127. UINT8 c[BOXVOLUME];
  128. /* Get box boundaries for the given (r,g,b)-triplet. Each box
  129. covers eight cache slots (32 colour values, that is). */
  130. r0 = r & 0xe0;
  131. r1 = r0 + 0x1f;
  132. rc = (r0 + r1) / 2;
  133. g0 = g & 0xe0;
  134. g1 = g0 + 0x1f;
  135. gc = (g0 + g1) / 2;
  136. b0 = b & 0xe0;
  137. b1 = b0 + 0x1f;
  138. bc = (b0 + b1) / 2;
  139. /* Step 1 -- Select relevant palette entries (after Heckbert) */
  140. /* For each palette entry, calculate the min and max distances to
  141. * any position in the box given by the colour we're looking for. */
  142. dmax = (unsigned int)~0;
  143. for (i = 0; i < palette->size; i++) {
  144. int r, g, b;
  145. unsigned int tmin, tmax;
  146. /* Find min and max distances to any point in the box */
  147. r = palette->palette[i * 4 + 0];
  148. tmin = (r < r0) ? RDIST(r, r0) : (r > r1) ? RDIST(r, r1) : 0;
  149. tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0);
  150. g = palette->palette[i * 4 + 1];
  151. tmin += (g < g0) ? GDIST(g, g0) : (g > g1) ? GDIST(g, g1) : 0;
  152. tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0);
  153. b = palette->palette[i * 4 + 2];
  154. tmin += (b < b0) ? BDIST(b, b0) : (b > b1) ? BDIST(b, b1) : 0;
  155. tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0);
  156. dmin[i] = tmin;
  157. if (tmax < dmax) {
  158. dmax = tmax; /* keep the smallest max distance only */
  159. }
  160. }
  161. /* Step 2 -- Incrementally update cache slot (after Thomas) */
  162. /* Find the box containing the nearest palette entry, and update
  163. * all slots in that box. We only check boxes for which the min
  164. * distance is less than or equal the smallest max distance */
  165. for (i = 0; i < BOXVOLUME; i++) {
  166. d[i] = (unsigned int)~0;
  167. }
  168. for (i = 0; i < palette->size; i++) {
  169. if (dmin[i] <= dmax) {
  170. int rd, gd, bd;
  171. int ri, gi, bi;
  172. int rx, gx, bx;
  173. ri = (r0 - palette->palette[i * 4 + 0]) * RSCALE;
  174. gi = (g0 - palette->palette[i * 4 + 1]) * GSCALE;
  175. bi = (b0 - palette->palette[i * 4 + 2]) * BSCALE;
  176. rd = ri * ri + gi * gi + bi * bi;
  177. ri = ri * (2 * RSTEP) + RSTEP * RSTEP;
  178. gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
  179. bi = bi * (2 * BSTEP) + BSTEP * BSTEP;
  180. rx = ri;
  181. for (r = j = 0; r < BOX; r++) {
  182. gd = rd;
  183. gx = gi;
  184. for (g = 0; g < BOX; g++) {
  185. bd = gd;
  186. bx = bi;
  187. for (b = 0; b < BOX; b++) {
  188. if ((unsigned int)bd < d[j]) {
  189. d[j] = bd;
  190. c[j] = (UINT8)i;
  191. }
  192. bd += bx;
  193. bx += 2 * BSTEP * BSTEP;
  194. j++;
  195. }
  196. gd += gx;
  197. gx += 2 * GSTEP * GSTEP;
  198. }
  199. rd += rx;
  200. rx += 2 * RSTEP * RSTEP;
  201. }
  202. }
  203. }
  204. /* Step 3 -- Update cache */
  205. /* The c array now contains the closest match for each
  206. * cache slot in the box. Update the cache. */
  207. j = 0;
  208. for (r = r0; r < r1; r += 4) {
  209. for (g = g0; g < g1; g += 4) {
  210. for (b = b0; b < b1; b += 4) {
  211. ImagingPaletteCache(palette, r, g, b) = c[j++];
  212. }
  213. }
  214. }
  215. }
  216. int
  217. ImagingPaletteCachePrepare(ImagingPalette palette) {
  218. /* Add a colour cache to a palette */
  219. int i;
  220. int entries = 64 * 64 * 64;
  221. if (palette->cache == NULL) {
  222. /* The cache is 512k. It might be a good idea to break it
  223. up into a pointer array (e.g. an 8-bit image?) */
  224. /* malloc check ok, small constant allocation */
  225. palette->cache = (INT16 *)malloc(entries * sizeof(INT16));
  226. if (!palette->cache) {
  227. (void)ImagingError_MemoryError();
  228. return -1;
  229. }
  230. /* Mark all entries as empty */
  231. for (i = 0; i < entries; i++) {
  232. palette->cache[i] = 0x100;
  233. }
  234. }
  235. return 0;
  236. }
  237. void
  238. ImagingPaletteCacheDelete(ImagingPalette palette) {
  239. /* Release the colour cache, if any */
  240. if (palette && palette->cache) {
  241. free(palette->cache);
  242. palette->cache = NULL;
  243. }
  244. }