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

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