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

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

Large source code cleanup, getting rid of spaces, tabs, and svn keywords.

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