Palette.c 8.2 KB

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