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

Last change on this file since 4148 was 4148, checked in by sam, 5 years ago

Update my e-mail address everywhere.

  • 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 *  $Id$
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.