source: libcaca/trunk/tools/sortchars.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: 6.6 KB
Line 
1/*
2 *  sortchars     analyse ASCII characters
3 *  Copyright (c) 2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: sortchars.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#   include <string.h>
20#   include <stdlib.h>
21#endif
22
23#include "caca.h"
24
25#define GLYPHS 0x7f
26#define FONT 0 /* 0 or 1 */
27#define DX 2
28#define DY 3
29#define RANGEBITS 2
30#define RANGE (1 << RANGEBITS)
31#define FULLRANGE (1 << (RANGEBITS * DX * DY))
32
33int total[GLYPHS][DX][DY];
34int16_t allbits[GLYPHS];
35int bestchar[FULLRANGE];
36
37static int curve[17] = /* 17 instead of 16 */
38{
39    0, 4, 6, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15
40    //0, 3, 5, 7, 8, 9, 10, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15
41    //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15
42};
43
44static int distance(uint16_t, uint16_t);
45static void testcircle(void);
46
47int main(int argc, char *argv[])
48{
49    int count[DX][DY];
50    char utf8[7];
51    caca_canvas_t *cv;
52    caca_font_t *f;
53    char const * const * fonts;
54    uint8_t *img;
55    unsigned int w, h, x, y;
56    int ret, i, max;
57
58    /* Load a libcaca internal font */
59    fonts = caca_get_font_list();
60    if(fonts[FONT] == NULL)
61    {
62        fprintf(stderr, "error: libcaca was compiled without any fonts\n");
63        return -1;
64    }
65    f = caca_load_font(fonts[FONT], 0);
66    if(f == NULL)
67    {
68        fprintf(stderr, "error: could not load font \"%s\"\n", fonts[0]);
69        return -1;
70    }
71
72    cv = caca_create_canvas(1, 1);
73    caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK);
74
75    /* Create our bitmap buffer (32-bit ARGB) */
76    w = caca_get_font_width(f);
77    h = caca_get_font_height(f);
78    img = malloc(4 * w * h);
79
80    /* Zero our structures */
81    for(y = 0; y < DY; y++)
82        for(x = 0; x < DX; x++)
83            count[x][y] = 0;
84
85    for(y = 0; y < h; y++)
86        for(x = 0; x < w; x++)
87            count[x * DX / w][y * DY / h]++;
88
89    for(i = 0x20; i < GLYPHS; i++)
90        for(y = 0; y < DY; y++)
91            for(x = 0; x < DX; x++)
92                total[i][x][y] = 0;
93
94    /* Draw all glyphs and count their pixels */
95    for(i = 0x20; i < GLYPHS; i++)
96    {
97        caca_put_char(cv, 0, 0, i);
98
99        /* Render the canvas onto our image buffer */
100        caca_render_canvas(cv, f, img, w, h, 4 * w);
101
102        for(y = 0; y < h * DY; y++)
103            for(x = 0; x < w * DX; x++)
104                total[i][x / w][y / h]
105                  += img[(w * (y / DY) + (x / DX)) * 4 + 1];
106    }
107
108    /* Compute max pixel value */
109    max = 0;
110    for(i = 0x20; i < GLYPHS; i++)
111        for(y = 0; y < DY; y++)
112            for(x = 0; x < DX; x++)
113            {
114                int val = total[i][x][y] * 256 / count[x][y];
115                if(val > max)
116                    max = val;
117            }
118
119    /* Compute bits for all glyphs */
120    for(i = 0x20; i < GLYPHS; i++)
121    {
122        int bits = 0;
123
124        if(i >= 0x7f && i <= 0x9f)
125        {
126            allbits[i] = 0;
127            continue;
128        }
129
130        for(y = 0; y < DY; y++)
131        {
132            for(x = 0; x < DX; x++)
133            {
134                int t = total[i][x][y] * 16 * 256 / (count[x][y] * max);
135                bits *= RANGE;
136                bits |= curve[t] / (16 / RANGE);
137            }
138        }
139
140        allbits[i] = bits;
141    }
142
143    /* Find a glyph for all combinations */
144    for(i = 0; i < FULLRANGE; i++)
145    {
146        int j, mindist = 0x1000, best = 0;
147
148        for(j = 0x20; j < GLYPHS; j++)
149        {
150            int d = distance(i, allbits[j]);
151            if(d < mindist)
152            {
153                best = j;
154                mindist = d;
155                if(d == 0)
156                    break;
157            }
158        }
159
160        bestchar[i] = best;
161    }
162
163    /* Print results */
164    printf("/* Generated by sortchars.c */\n");
165    printf("static char const cells_to_ascii[%i] =\n{\n    ", FULLRANGE);
166    for(i = 0; i < FULLRANGE; i++)
167    {
168        ret = caca_utf32_to_utf8(utf8, bestchar[i]);
169        utf8[ret] = '\0';
170        printf("%i, ", bestchar[i]);
171        if((i % 16) == 15 && i != FULLRANGE - 1)
172            printf("\n    ");
173    }
174    printf("\n};\n\n");
175    printf("static uint16_t const ascii_to_cells[%i] =\n{\n    ", GLYPHS);
176    for(i = 0; i < GLYPHS; i++)
177    {
178        ret = caca_utf32_to_utf8(utf8, bestchar[i]);
179        utf8[ret] = '\0';
180        printf("0x%03x, ", allbits[i]);
181        if((i % 8) == 7 && i != GLYPHS - 1)
182            printf("\n    ");
183    }
184    printf("\n};\n");
185
186    caca_free_canvas(cv);
187
188    testcircle();
189
190    return 0;
191}
192
193static int distance(uint16_t mychar, uint16_t x)
194{
195    int i, d = 0;
196
197    for(i = 0; i < DX * DY; i++)
198    {
199        int t = (int)(mychar & (RANGE - 1)) - (int)(x & (RANGE - 1));
200        d += t > 0 ? 1 * t : -2 * t;
201        mychar /= RANGE;
202        x /= RANGE;
203    }
204
205    return d;
206}
207
208#define WIDTH 40
209#define HEIGHT 18
210
211static void testcircle(void)
212{
213    char utf8[7];
214    uint8_t *buf = malloc(256 * 256);
215    uint16_t *dst = malloc(WIDTH * DX * HEIGHT * DY * sizeof(uint16_t));
216    int x, y, ret;
217
218    memset(buf, 0, 256 * 256);
219    memset(dst, 0, WIDTH * DX * HEIGHT * DY);
220
221    /* Fill image */
222    for(y = 0; y < 256; y++)
223        for(x = 0; x < 256; x++)
224        {
225            int dist2 = (x - 128) * (x - 128) + (y - 128) * (y - 128);
226            if(dist2 < 25000 && dist2 > 18000)
227                buf[y * 256 + x] = 255;
228            else if(dist2 < 14000 && dist2 > 9000)
229                buf[y * 256 + x] = 204;
230            else if(dist2 < 6000 && dist2 > 3000)
231                buf[y * 256 + x] = 153;
232            else if(dist2 < 1600 && dist2 > 300)
233                buf[y * 256 + x] = 102;
234        }
235
236    /* Parse image */
237    for(y = 0; y < HEIGHT * DY; y++)
238        for(x = 0; x < WIDTH * DX; x++)
239            dst[y * WIDTH * DX + x] = (int)buf[(y * 256 / (HEIGHT * DY)) * 256 + (x * 256 / (WIDTH * DX))] * RANGE / 256;
240
241    printf("/* example:\n");
242    for(y = 0; y < HEIGHT; y++)
243    {
244        for(x = 0; x < WIDTH; x++)
245        {
246            uint16_t bits = 0;
247            int i, j;
248            for(j = 0; j < DY; j++)
249                for(i = 0; i < DX; i++)
250                {
251                    bits *= RANGE;
252                    bits |= dst[(y * DY + j) * WIDTH * DX + x * DX + i];
253                }
254
255            ret = caca_utf32_to_utf8(utf8, bestchar[bits]);
256            utf8[ret] = '\0';
257            printf("%s", utf8);
258        }
259
260        printf("\n");
261    }
262    printf("*/\n");
263}
264
Note: See TracBrowser for help on using the repository browser.