You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
8.7 KiB

  1. /*
  2. * optipal S-Lang optimised palette generator for libcaca
  3. * Copyright (c) 2003 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  21. * 02111-1307 USA
  22. */
  23. #include "config.h"
  24. #include <stdio.h>
  25. #include "caca.h"
  26. static void base_colors(void);
  27. static void emulated_colors(void);
  28. static void unused_colors(void);
  29. static int slang_assoc[16*16], palette[16*16];
  30. /* 6 colours in hue order */
  31. static enum caca_color const hue_list[] =
  32. {
  33. CACA_COLOR_RED,
  34. CACA_COLOR_BROWN,
  35. CACA_COLOR_GREEN,
  36. CACA_COLOR_CYAN,
  37. CACA_COLOR_BLUE,
  38. CACA_COLOR_MAGENTA
  39. };
  40. #define SETPAIR(_fg, _bg, _n) \
  41. do \
  42. { \
  43. int fg = _fg, bg = _bg, n = _n; \
  44. slang_assoc[fg + 16 * bg] = n; \
  45. palette[n] = fg + 16 * bg; \
  46. } \
  47. while(0);
  48. int main(void)
  49. {
  50. int i;
  51. for(i = 0; i < 16 * 16; i++)
  52. {
  53. slang_assoc[i] = -1;
  54. palette[i] = -1;
  55. }
  56. /* The base colour pairs (0-127) */
  57. base_colors();
  58. /* Now the less important pairs that we can afford to emulate using
  59. * previously defined colour pairs. */
  60. emulated_colors();
  61. /* Fill the rest of the palette with equal colour pairs such as black
  62. * on black. They will never be used, but nevermind. */
  63. unused_colors();
  64. /* Output the palette */
  65. printf("static int const slang_palette[2*16*16] =\n{\n");
  66. for(i = 0; i < 16 * 16; i++)
  67. {
  68. if((i % 8) == 0) printf(" ");
  69. printf("%2i, %2i, ", palette[i] % 16, palette[i] / 16);
  70. if((i % 8) == 7) printf("\n");
  71. }
  72. printf("};\n\n");
  73. /* Output the association table */
  74. printf("static int const slang_assoc[16*16] =\n{\n");
  75. for(i = 0; i < 16 * 16; i++)
  76. {
  77. if((i % 16) == 0) printf(" ");
  78. printf("%i, ", slang_assoc[i]);
  79. if((i % 16) == 15) printf("\n");
  80. }
  81. printf("};\n");
  82. return 0;
  83. }
  84. /*
  85. * XXX: See the NOTES file for what follows
  86. */
  87. static void base_colors(void)
  88. {
  89. int i, cur = 0;
  90. /* black background colour pairs that are needed for the old renderer */
  91. for(i = 1; i < 16; i++)
  92. SETPAIR(i, CACA_COLOR_BLACK, cur++);
  93. /* gray combinations used for grayscale dithering */
  94. SETPAIR(CACA_COLOR_BLACK, CACA_COLOR_DARKGRAY, cur++);
  95. SETPAIR(CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, cur++);
  96. SETPAIR(CACA_COLOR_LIGHTGRAY, CACA_COLOR_DARKGRAY, cur++);
  97. SETPAIR(CACA_COLOR_WHITE, CACA_COLOR_LIGHTGRAY, cur++);
  98. SETPAIR(CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE, cur++);
  99. /* white/light, light/dark, lightgray/light, darkgray/dark, dark/black
  100. * combinations often used for saturation/value dithering (the two
  101. * other possible combinations, lightgray/dark and darkgray/light, are
  102. * not considered here) */
  103. for(i = 1; i < 7; i++)
  104. {
  105. SETPAIR(CACA_COLOR_WHITE, i + 8, cur++);
  106. SETPAIR(i + 8, CACA_COLOR_WHITE, cur++);
  107. SETPAIR(i, i + 8, cur++);
  108. SETPAIR(i + 8, i, cur++);
  109. SETPAIR(CACA_COLOR_LIGHTGRAY, i + 8, cur++);
  110. SETPAIR(i + 8, CACA_COLOR_LIGHTGRAY, cur++);
  111. SETPAIR(CACA_COLOR_DARKGRAY, i, cur++);
  112. SETPAIR(i, CACA_COLOR_DARKGRAY, cur++);
  113. SETPAIR(CACA_COLOR_BLACK, i, cur++);
  114. }
  115. /* next colour combinations for hue dithering (magenta/blue, blue/green
  116. * and so on) */
  117. for(i = 0; i < 6; i++)
  118. {
  119. SETPAIR(hue_list[i], hue_list[(i + 1) % 6], cur++);
  120. SETPAIR(hue_list[(i + 1) % 6], hue_list[i], cur++);
  121. SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6] + 8, cur++);
  122. SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i] + 8, cur++);
  123. }
  124. /* next colour combinations for hue/value dithering (blue/lightgreen,
  125. * green/lightblue and so on) */
  126. for(i = 0; i < 6; i++)
  127. {
  128. SETPAIR(hue_list[i], hue_list[(i + 1) % 6] + 8, cur++);
  129. SETPAIR(hue_list[(i + 1) % 6], hue_list[i] + 8, cur++);
  130. SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6], cur++);
  131. SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i], cur++);
  132. }
  133. /* black on light gray, black on white, white on dark gray, dark gray
  134. * on white, white on blue, light gray on blue (chosen arbitrarily) */
  135. SETPAIR(CACA_COLOR_BLACK, CACA_COLOR_LIGHTGRAY, cur++);
  136. SETPAIR(CACA_COLOR_BLACK, CACA_COLOR_WHITE, cur++);
  137. SETPAIR(CACA_COLOR_WHITE, CACA_COLOR_DARKGRAY, cur++);
  138. SETPAIR(CACA_COLOR_DARKGRAY, CACA_COLOR_WHITE, cur++);
  139. SETPAIR(CACA_COLOR_WHITE, CACA_COLOR_BLUE, cur++);
  140. SETPAIR(CACA_COLOR_LIGHTGRAY, CACA_COLOR_BLUE, cur++);
  141. }
  142. static void emulated_colors(void)
  143. {
  144. int i;
  145. /* light gray on dark colour: emulate with light colour on dark colour
  146. * white on dark colour: emulate with light gray on light colour
  147. * black on light colour: emulate with dark gray on dark colour
  148. * dark gray on light colour: emulate with dark colour on light colour
  149. * light colour on dark gray: emulate with dark colour on dark gray
  150. * dark colour on light gray: emulate with light colour on light gray
  151. * dark colour on white: emulate with light colour on white */
  152. for(i = 1; i < 7; i++)
  153. {
  154. if(i != CACA_COLOR_BLUE)
  155. {
  156. SETPAIR(CACA_COLOR_LIGHTGRAY, i, 128 +
  157. slang_assoc[i + 8 + 16 * i]);
  158. SETPAIR(CACA_COLOR_WHITE, i, 128 +
  159. slang_assoc[CACA_COLOR_LIGHTGRAY + 16 * (i + 8)]);
  160. }
  161. SETPAIR(CACA_COLOR_BLACK, i + 8,
  162. 128 + slang_assoc[CACA_COLOR_DARKGRAY + 16 * i]);
  163. SETPAIR(CACA_COLOR_DARKGRAY, i + 8,
  164. 128 + slang_assoc[i + 16 * (i + 8)]);
  165. SETPAIR(i + 8, CACA_COLOR_DARKGRAY,
  166. 128 + slang_assoc[i + 16 * CACA_COLOR_DARKGRAY]);
  167. SETPAIR(i, CACA_COLOR_LIGHTGRAY,
  168. 128 + slang_assoc[i + 8 + 16 * CACA_COLOR_LIGHTGRAY]);
  169. SETPAIR(i, CACA_COLOR_WHITE,
  170. 128 + slang_assoc[i + 8 + 16 * CACA_COLOR_WHITE]);
  171. }
  172. /* 120 degree hue pairs can be emulated as well; for instance blue on
  173. * red can be emulated using magenta on red, and blue on green using
  174. * cyan on green */
  175. for(i = 0; i < 6; i++)
  176. {
  177. SETPAIR(hue_list[(i + 2) % 6], hue_list[i],
  178. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i]]);
  179. SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i] + 8,
  180. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 136]);
  181. SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i],
  182. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 8]);
  183. SETPAIR(hue_list[(i + 2) % 6], hue_list[i] + 8,
  184. 128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 128]);
  185. SETPAIR(hue_list[(i + 4) % 6], hue_list[i],
  186. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i]]);
  187. SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i] + 8,
  188. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 136]);
  189. SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i],
  190. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 8]);
  191. SETPAIR(hue_list[(i + 4) % 6], hue_list[i] + 8,
  192. 128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 128]);
  193. }
  194. /* dark opposite on dark: emulate with dark opposite on black
  195. * light opposite on dark: emulate with light opposite on black
  196. * dark opposite on light: emulate with black on dark
  197. * light opposite on light: emulate with white on light */
  198. for(i = 0; i < 6; i++)
  199. {
  200. SETPAIR(hue_list[i], hue_list[(i + 3) % 6],
  201. 128 + slang_assoc[hue_list[i] + 16 * CACA_COLOR_BLACK]);
  202. SETPAIR(hue_list[i] + 8, hue_list[(i + 3) % 6],
  203. 128 + slang_assoc[hue_list[i] + 8 + 16 * CACA_COLOR_BLACK]);
  204. SETPAIR(hue_list[(i + 3) % 6], hue_list[i] + 8,
  205. 128 + slang_assoc[CACA_COLOR_BLACK + 16 * hue_list[i]]);
  206. SETPAIR(hue_list[(i + 3) % 6] + 8, hue_list[i] + 8,
  207. 128 + slang_assoc[CACA_COLOR_WHITE + 16 * (hue_list[i] + 8)]);
  208. }
  209. }
  210. static void unused_colors(void)
  211. {
  212. int i, j;
  213. for(i = 0, j = 0; i < 16 * 16; i++)
  214. {
  215. if(palette[i] == -1)
  216. {
  217. SETPAIR(j, j, i);
  218. j++;
  219. }
  220. }
  221. }