color.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <X11/Xlib.h>
  4. #include <grass/gis.h>
  5. #include <grass/glocale.h>
  6. extern Display *dpy;
  7. extern int scrn;
  8. extern Window grwin;
  9. extern XWindowAttributes xwa;
  10. static int NCOLORS;
  11. static unsigned long *xpixels;
  12. static int Red[256], Grn[256], Blu[256];
  13. static int Gray[256];
  14. static int r_pos, g_pos, b_pos;
  15. static int r_size, g_size, b_size;
  16. static int r_scale, g_scale, b_scale;
  17. static void get_shifts(unsigned long mask, int *pos, int *size, int *scale)
  18. {
  19. int i, j;
  20. for (i = 0; (mask & 1) == 0; i++)
  21. mask >>= 1;
  22. if (pos)
  23. *pos = i;
  24. for (j = i; (mask & 1) != 0; j++)
  25. mask >>= 1;
  26. if (size)
  27. *size = j - i;
  28. if (scale)
  29. *scale = 8 - (j - i);
  30. }
  31. static int get_rgb_shifts(void)
  32. {
  33. get_shifts(xwa.visual->red_mask, &r_pos, &r_size, &r_scale);
  34. get_shifts(xwa.visual->green_mask, &g_pos, &g_size, &g_scale);
  35. get_shifts(xwa.visual->blue_mask, &b_pos, &b_size, &b_scale);
  36. return (1 << r_size) * (1 << g_size) * (1 << b_size);
  37. }
  38. static unsigned long
  39. find_color_gray(unsigned int r, unsigned int g, unsigned int b)
  40. {
  41. unsigned int y = (r + g + b) / 3;
  42. return xpixels[Gray[y]];
  43. }
  44. static unsigned long
  45. find_color_indexed(unsigned int r, unsigned int g, unsigned int b)
  46. {
  47. return xpixels[Red[r] + Grn[g] + Blu[b]];
  48. }
  49. static unsigned long
  50. find_color_rgb(unsigned int r, unsigned int g, unsigned int b)
  51. {
  52. unsigned int rr = r >> r_scale;
  53. unsigned int gg = g >> g_scale;
  54. unsigned int bb = b >> b_scale;
  55. return (rr << r_pos) + (gg << g_pos) + (bb << b_pos);
  56. }
  57. unsigned long find_color(unsigned int r, unsigned int g, unsigned int b)
  58. {
  59. switch (xwa.visual->class) {
  60. case StaticGray:
  61. case GrayScale:
  62. return find_color_gray(r, g, b);
  63. case StaticColor:
  64. case PseudoColor:
  65. return find_color_indexed(r, g, b);
  66. case TrueColor:
  67. case DirectColor:
  68. return find_color_rgb(r, g, b);
  69. default:
  70. G_fatal_error(_("Unknown visual class [%d]."), xwa.visual->class);
  71. return 0;
  72. }
  73. }
  74. static void get_max_levels(int n_colors, int *rr, int *gg, int *bb)
  75. {
  76. int r, g, b, i;
  77. for (i = 0; i * i * i < n_colors; i++) ;
  78. for (r = g = b = i;;) {
  79. if (r * g * b <= n_colors)
  80. break;
  81. b--;
  82. if (r * g * b <= n_colors)
  83. break;
  84. r--;
  85. if (r * g * b <= n_colors)
  86. break;
  87. g--;
  88. }
  89. *rr = r;
  90. *gg = g;
  91. *bb = b;
  92. }
  93. static int get_fewer_levels(int *rr, int *gg, int *bb)
  94. {
  95. int r = *rr;
  96. int g = *gg;
  97. int b = *bb;
  98. /* 888 -> 887 -> 787 -> 777 -> ... */
  99. if (r > b) /* 887 -> 787 */
  100. r--;
  101. else if (g > b) /* 787 -> 777 */
  102. g--;
  103. else /* 888 -> 888 */
  104. b--;
  105. *rr = r;
  106. *gg = g;
  107. *bb = b;
  108. return r >= 2 && g >= 2 && b >= 2;
  109. }
  110. static int try_get_colors(Colormap cmap, int nr, int ng, int nb)
  111. {
  112. XColor xcolor;
  113. int n_pixels;
  114. int r, g, b;
  115. xpixels = (unsigned long *)G_realloc(xpixels,
  116. nr * ng * nb *
  117. sizeof(unsigned long));
  118. n_pixels = 0;
  119. xcolor.flags = DoRed | DoGreen | DoBlue;
  120. for (r = 0; r < nr; r++) {
  121. for (g = 0; g < ng; g++) {
  122. for (b = 0; b < nb; b++) {
  123. xcolor.red = (unsigned short)(r * 0xFFFF / (nr - 1));
  124. xcolor.green = (unsigned short)(g * 0xFFFF / (ng - 1));
  125. xcolor.blue = (unsigned short)(b * 0xFFFF / (nb - 1));
  126. if (!XAllocColor(dpy, cmap, &xcolor)) {
  127. XFreeColors(dpy, cmap, xpixels, n_pixels,
  128. (unsigned long)0);
  129. return 0;
  130. }
  131. xpixels[n_pixels++] = xcolor.pixel;
  132. }
  133. }
  134. }
  135. return 1;
  136. }
  137. static int try_get_grays(Colormap cmap, int ny)
  138. {
  139. XColor xcolor;
  140. int n_pixels;
  141. int y;
  142. xpixels = (unsigned long *)G_realloc(xpixels, ny * sizeof(unsigned long));
  143. n_pixels = 0;
  144. xcolor.flags = DoRed | DoGreen | DoBlue;
  145. for (y = 0; y < ny; y++) {
  146. unsigned short v = (unsigned short)(y * 0xFFFF / (ny - 1));
  147. xcolor.red = v;
  148. xcolor.green = v;
  149. xcolor.blue = v;
  150. if (!XAllocColor(dpy, cmap, &xcolor)) {
  151. XFreeColors(dpy, cmap, xpixels, n_pixels, (unsigned long)0);
  152. return y;
  153. }
  154. xpixels[n_pixels++] = xcolor.pixel;
  155. }
  156. return ny;
  157. }
  158. static Colormap ramp_colormap(void)
  159. {
  160. int n_colors = xwa.visual->map_entries;
  161. Colormap cmap = XCreateColormap(dpy, RootWindow(dpy, scrn),
  162. xwa.visual, AllocAll);
  163. int i;
  164. for (i = 0; i < n_colors; i++) {
  165. unsigned int k = i * 65535 / (n_colors - 1);
  166. unsigned int l = i * 255 / (n_colors - 1);
  167. XColor xcolor;
  168. xcolor.flags = DoRed | DoGreen | DoBlue;
  169. xcolor.blue = k;
  170. xcolor.green = k;
  171. xcolor.red = k;
  172. xcolor.pixel = find_color_rgb(l, l, l);
  173. XStoreColor(dpy, cmap, &xcolor);
  174. }
  175. return cmap;
  176. }
  177. Colormap InitColorTableFixed(Colormap cmap)
  178. {
  179. int n_colors = xwa.visual->map_entries;
  180. int r, g, b, y, i;
  181. switch (xwa.visual->class) {
  182. case StaticGray:
  183. case GrayScale:
  184. /* determine how many levels of gray we can actually get */
  185. y = try_get_grays(cmap, n_colors);
  186. if (y > 2 && y < n_colors)
  187. y = try_get_grays(cmap, y);
  188. if (y < 2)
  189. G_fatal_error(_("Unable to get sufficient gray shades."));
  190. NCOLORS = y;
  191. for (i = 0; i < 256; i++)
  192. Gray[i] = i * y / 256;
  193. break;
  194. case StaticColor:
  195. case PseudoColor:
  196. /* determine how many levels of r, g, and b are possible */
  197. get_max_levels(n_colors, &r, &g, &b);
  198. /* now see how many we can actually get */
  199. while (!try_get_colors(cmap, r, g, b))
  200. if (!get_fewer_levels(&r, &g, &b))
  201. G_fatal_error(_("Unable to get sufficient colors."));
  202. NCOLORS = r * g * b;
  203. for (i = 0; i < 256; i++) {
  204. Red[i] = (i * r / 256) * g * b;
  205. Grn[i] = (i * g / 256) * b;
  206. Blu[i] = (i * b / 256);
  207. }
  208. break;
  209. case DirectColor:
  210. G_warning(_("Using private colormap for DirectColor visual."));
  211. /* free any previously-allocated Colormap */
  212. if (cmap != DefaultColormap(dpy, scrn))
  213. XFreeColormap(dpy, cmap);
  214. /* get shift factors for R,G,B masks */
  215. NCOLORS = get_rgb_shifts();
  216. /* create colormap (emulates TrueColor visual) */
  217. cmap = ramp_colormap();
  218. break;
  219. case TrueColor:
  220. /* get shift factors for R,G,B masks */
  221. NCOLORS = get_rgb_shifts();
  222. break;
  223. default:
  224. G_fatal_error(_("Unknown visual class [%d]."), xwa.visual->class);
  225. break;
  226. }
  227. return cmap;
  228. }