source: libcaca/trunk/tools/optipal.c @ 2821

Last change on this file since 2821 was 2821, checked in by Sam Hocevar, 11 years ago

Starting refactoring to get rid of libcucul. The initial reason for the
split is rendered moot by the plugin system: when enabled, binaries do
not link directly with libX11 or libGL. I hope this is a step towards
more consisteny and clarity.

  • Property svn:keywords set to Id
File size: 11.6 KB
Line 
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: optipal.c 2821 2008-09-27 13:12:46Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#if !defined(__KERNEL__)
18#   include <stdio.h>
19#endif
20
21#include "caca.h" /* Only necessary for CACA_* macros */
22
23static void base_colors(void);
24static void emulated_colors(void);
25static void unused_colors(void);
26
27static int slang_assoc[16*16], palette[16*16];
28
29/* 6 colours in hue order */
30static unsigned int const hue_list[] =
31{
32    CACA_RED, CACA_BROWN, CACA_GREEN,
33    CACA_CYAN, CACA_BLUE, CACA_MAGENTA
34};
35
36#define SETPAIR(_fg, _bg, _n) \
37    do \
38    { \
39        int fg = _fg, bg = _bg, n = _n; \
40        slang_assoc[fg + 16 * bg] = n; \
41        palette[n] = fg + 16 * bg; \
42    } \
43    while(0);
44
45int main(int argc, char *argv[])
46{
47    int i;
48
49    for(i = 0; i < 16 * 16; i++)
50    {
51        slang_assoc[i] = -1;
52        palette[i] = -1;
53    }
54
55    /* The base colour pairs (0-127) */
56    base_colors();
57
58    /* Now the less important pairs that we can afford to emulate using
59     * previously defined colour pairs. */
60    emulated_colors();
61
62    /* Fill the rest of the palette with equal colour pairs such as black
63     * on black. They will never be used, but nevermind. */
64    unused_colors();
65
66    /* Output the palette */
67    printf("static int const slang_palette[2*16*16] =\n{\n");
68    for(i = 0; i < 16 * 16; i++)
69    {
70        if((i % 8) == 0) printf("    ");
71        printf("%2i, %2i,  ", palette[i] % 16, palette[i] / 16);
72        if((i % 8) == 7) printf("\n");
73    }
74    printf("};\n\n");
75
76    /* Output the association table */
77    printf("static int const slang_assoc[16*16] =\n{\n");
78    for(i = 0; i < 16 * 16; i++)
79    {
80        if((i % 16) == 0) printf("    ");
81        printf("%i, ", slang_assoc[i]);
82        if((i % 16) == 15) printf("\n");
83    }
84    printf("};\n");
85
86    return 0;
87}
88
89/*
90 *  256 character pairs are definable, but only 128 can be used. This is
91 *  because slsmg.c's This_Color variable uses its 8th bit to indicate an
92 *  alternate character set. Replacing a few 0x7F with 0xFF in sldisply.c
93 *  works around the problem but gets rid of the alternate charset.
94 *
95 *  We can work around this problem. See this usage grid:
96 *
97 *                  bg                         1 1 1 1 1 1
98 *    fg                  0 1 2 3 4 5 6 7  8 9 0 1 2 3 4 5
99 *
100 *    0 (black)             C C C C C C F  B c c c c c c F
101 *    1 (blue)            A   h D h D i f  C C h E h E k g
102 *    2 (green)           A h   D h i D f  C h C E h k E g
103 *    3 (cyan)            A D D   i h h f  C E E C k h h g
104 *    4 (red)             A h h i   D D f  C h h k C E E g
105 *    5 (magenta)         A D i h D   h f  C E k h E C h g
106 *    6 (brown)           A i D h D h   f  C k E h E h C g
107 *    7 (light gray)      A F a a a a a    B C C C C C C B
108 *
109 *    8 (dark gray)       A C C C C C C B    d d d d d d F
110 *    9 (light blue)      A C h E h E j C  e   h D h D l C
111 *    10 (light green)    A h C E h j E C  e h   D h l D C
112 *    11 (light cyan)     A E E C j h h C  e D D   l h h C
113 *    12 (light red)      A h h j C E E C  e h h l   D D C
114 *    13 (light magenta)  A E j h E C h C  e D l h D   h C
115 *    14 (yellow)         A j E h E h C C  e l D h D h   C
116 *    15 (white)          A F b b b b b B  F C C C C C C
117 *
118 *  ' ': useless colour pairs that can be emulated by printing a space in
119 *       any other colour pair that has the same background
120 *  'A': black background colour pairs that are needed for the old renderer
121 *  'B': gray combinations used for grayscale dithering
122 *  'C': white/light, light/dark, lightgray/light, darkgray/dark, dark/black
123 *       combinations often used for saturation/value dithering (the two
124 *       other possible combinations, lightgray/dark and darkgray/light, are
125 *       not considered here)
126 *  'D': next colour combinations for hue dithering (magenta/blue, blue/green
127 *       and so on)
128 *  'E': next colour combinations for hue/value dithering (blue/lightgreen,
129 *       green/lightblue and so on)
130 *  'F': black on light gray, black on white, white on dark gray, dark gray
131 *       on white, white on blue, light gray on blue (chosen arbitrarily)
132 *
133 *  'A': 15 colour pairs
134 *  'A'+'B': 20 colour pairs
135 *  'A'+'B'+'C': 74 colour pairs
136 *  'A'+'B'+'C'+'D': 98 colour pairs
137 *  'A'+'B'+'C'+'D'+'E': 122 colour pairs
138 *  'A'+'B'+'C'+'D'+'E'+'F': 128 colour pairs
139 *
140 *  The remaining slightly important colour pairs are:
141 *
142 *  'a': light gray on dark colour: emulate with light colour on dark colour
143 *  'b': white on dark colour: emulate with light gray on light colour
144 *  'c': black on light colour: emulate with dark gray on dark colour
145 *  'd': dark gray on light colour: emulate with dark colour on light colour
146 *  'e': light colour on dark gray: emulate with dark colour on dark gray
147 *  'f': dark colour on light gray: emulate with light colour on light gray
148 *  'g': dark colour on white: emulate with light colour on white
149 *
150 *  And now the seldom used pairs:
151 *
152 *  'h': 120 degree hue pairs can be emulated as well; for instance blue on
153 *       red can be emulated using magenta on red, and blue on green using
154 *       cyan on green
155 *
156 *  And the almost never used pairs:
157 *
158 *  'i': dark opposite on dark: emulate with dark opposite on black
159 *  'j': light opposite on dark: emulate with light opposite on black
160 *  'k': dark opposite on light: emulate with black on dark
161 *  'l': light opposite on light: emulate with white on light
162 */
163
164static void base_colors(void)
165{
166    int i, cur = 0;
167
168    /* black background colour pairs that are needed for the old renderer */
169    for(i = 1; i < 16; i++)
170        SETPAIR(i, CACA_BLACK, cur++);
171
172    /* gray combinations used for grayscale dithering */
173    SETPAIR(CACA_BLACK, CACA_DARKGRAY, cur++);
174    SETPAIR(CACA_DARKGRAY, CACA_LIGHTGRAY, cur++);
175    SETPAIR(CACA_LIGHTGRAY, CACA_DARKGRAY, cur++);
176    SETPAIR(CACA_WHITE, CACA_LIGHTGRAY, cur++);
177    SETPAIR(CACA_LIGHTGRAY, CACA_WHITE, cur++);
178
179    /* white/light, light/dark, lightgray/light, darkgray/dark, dark/black
180     * combinations often used for saturation/value dithering (the two
181     * other possible combinations, lightgray/dark and darkgray/light, are
182     * not considered here) */
183    for(i = 1; i < 7; i++)
184    {
185        SETPAIR(CACA_WHITE, i + 8, cur++);
186        SETPAIR(i + 8, CACA_WHITE, cur++);
187        SETPAIR(i, i + 8, cur++);
188        SETPAIR(i + 8, i, cur++);
189        SETPAIR(CACA_LIGHTGRAY, i + 8, cur++);
190        SETPAIR(i + 8, CACA_LIGHTGRAY, cur++);
191        SETPAIR(CACA_DARKGRAY, i, cur++);
192        SETPAIR(i, CACA_DARKGRAY, cur++);
193        SETPAIR(CACA_BLACK, i, cur++);
194    }
195
196    /* next colour combinations for hue dithering (magenta/blue, blue/green
197     * and so on) */
198    for(i = 0; i < 6; i++)
199    {
200        SETPAIR(hue_list[i], hue_list[(i + 1) % 6], cur++);
201        SETPAIR(hue_list[(i + 1) % 6], hue_list[i], cur++);
202        SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6] + 8, cur++);
203        SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i] + 8, cur++);
204    }
205
206    /* next colour combinations for hue/value dithering (blue/lightgreen,
207     * green/lightblue and so on) */
208    for(i = 0; i < 6; i++)
209    {
210        SETPAIR(hue_list[i], hue_list[(i + 1) % 6] + 8, cur++);
211        SETPAIR(hue_list[(i + 1) % 6], hue_list[i] + 8, cur++);
212        SETPAIR(hue_list[i] + 8, hue_list[(i + 1) % 6], cur++);
213        SETPAIR(hue_list[(i + 1) % 6] + 8, hue_list[i], cur++);
214    }
215
216    /* black on light gray, black on white, white on dark gray, dark gray
217     * on white, white on blue, light gray on blue (chosen arbitrarily) */
218    SETPAIR(CACA_BLACK, CACA_LIGHTGRAY, cur++);
219    SETPAIR(CACA_BLACK, CACA_WHITE, cur++);
220    SETPAIR(CACA_WHITE, CACA_DARKGRAY, cur++);
221    SETPAIR(CACA_DARKGRAY, CACA_WHITE, cur++);
222    SETPAIR(CACA_WHITE, CACA_BLUE, cur++);
223    SETPAIR(CACA_LIGHTGRAY, CACA_BLUE, cur++);
224}
225
226static void emulated_colors(void)
227{
228    int i;
229
230    /* light gray on dark colour: emulate with light colour on dark colour
231     * white on dark colour: emulate with light gray on light colour
232     * black on light colour: emulate with dark gray on dark colour
233     * dark gray on light colour: emulate with dark colour on light colour
234     * light colour on dark gray: emulate with dark colour on dark gray
235     * dark colour on light gray: emulate with light colour on light gray
236     * dark colour on white: emulate with light colour on white */
237    for(i = 1; i < 7; i++)
238    {
239        if(i != CACA_BLUE)
240        {
241            SETPAIR(CACA_LIGHTGRAY, i, 128 +
242                    slang_assoc[i + 8 + 16 * i]);
243            SETPAIR(CACA_WHITE, i, 128 +
244                    slang_assoc[CACA_LIGHTGRAY + 16 * (i + 8)]);
245        }
246        SETPAIR(CACA_BLACK, i + 8,
247                128 + slang_assoc[CACA_DARKGRAY + 16 * i]);
248        SETPAIR(CACA_DARKGRAY, i + 8,
249                128 + slang_assoc[i + 16 * (i + 8)]);
250        SETPAIR(i + 8, CACA_DARKGRAY,
251                128 + slang_assoc[i + 16 * CACA_DARKGRAY]);
252        SETPAIR(i, CACA_LIGHTGRAY,
253                128 + slang_assoc[i + 8 + 16 * CACA_LIGHTGRAY]);
254        SETPAIR(i, CACA_WHITE,
255                128 + slang_assoc[i + 8 + 16 * CACA_WHITE]);
256    }
257
258    /* 120 degree hue pairs can be emulated as well; for instance blue on
259     * red can be emulated using magenta on red, and blue on green using
260     * cyan on green */
261    for(i = 0; i < 6; i++)
262    {
263        SETPAIR(hue_list[(i + 2) % 6], hue_list[i],
264            128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i]]);
265        SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i] + 8,
266            128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 136]);
267        SETPAIR(hue_list[(i + 2) % 6] + 8, hue_list[i],
268            128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 8]);
269        SETPAIR(hue_list[(i + 2) % 6], hue_list[i] + 8,
270            128 + slang_assoc[hue_list[(i + 1) % 6] + 16 * hue_list[i] + 128]);
271
272        SETPAIR(hue_list[(i + 4) % 6], hue_list[i],
273            128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i]]);
274        SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i] + 8,
275            128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 136]);
276        SETPAIR(hue_list[(i + 4) % 6] + 8, hue_list[i],
277            128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 8]);
278        SETPAIR(hue_list[(i + 4) % 6], hue_list[i] + 8,
279            128 + slang_assoc[hue_list[(i + 5) % 6] + 16 * hue_list[i] + 128]);
280    }
281
282    /* dark opposite on dark: emulate with dark opposite on black
283     * light opposite on dark: emulate with light opposite on black
284     * dark opposite on light: emulate with black on dark
285     * light opposite on light: emulate with white on light */
286    for(i = 0; i < 6; i++)
287    {
288        SETPAIR(hue_list[i], hue_list[(i + 3) % 6],
289                128 + slang_assoc[hue_list[i] + 16 * CACA_BLACK]);
290        SETPAIR(hue_list[i] + 8, hue_list[(i + 3) % 6],
291                128 + slang_assoc[hue_list[i] + 8 + 16 * CACA_BLACK]);
292        SETPAIR(hue_list[(i + 3) % 6], hue_list[i] + 8,
293                128 + slang_assoc[CACA_BLACK + 16 * hue_list[i]]);
294        SETPAIR(hue_list[(i + 3) % 6] + 8, hue_list[i] + 8,
295                128 + slang_assoc[CACA_WHITE + 16 * (hue_list[i] + 8)]);
296    }
297}
298
299static void unused_colors(void)
300{
301    int i, j;
302
303    for(i = 0, j = 0; i < 16 * 16; i++)
304    {
305        if(palette[i] == -1)
306        {
307            SETPAIR(j, j, i);
308            j++;
309        }
310    }
311}
312
Note: See TracBrowser for help on using the repository browser.