source: libcaca/trunk/src/blit.c @ 204

Last change on this file since 204 was 204, checked in by Sam Hocevar, 19 years ago
  • TODO: + A few updates.
  • src/blit.c: + Split blit() into caca_create_bitmap() and caca_draw_bitmap(). + Started removing hardcoded bitmask and pitch values.
  • examples/demo.c: + Do something with mouse clicks.
  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/*
2 *   libcaca       ASCII-Art library
3 *   Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
4 *                 All Rights Reserved
5 *
6 *   $Id: blit.c 204 2003-11-21 14:34:07Z sam $
7 *
8 *   This library is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU Lesser General Public
10 *   License as published by the Free Software Foundation; either
11 *   version 2 of the License, or (at your option) any later version.
12 *
13 *   This library is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *   Lesser General Public License for more details.
17 *
18 *   You should have received a copy of the GNU Lesser General Public
19 *   License along with this library; if not, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 *   02111-1307  USA
22 */
23
24#include "config.h"
25
26#ifdef HAVE_INTTYPES_H
27#   include <inttypes.h>
28#else
29typedef unsigned char uint8_t;
30#endif
31
32#include <stdlib.h>
33
34#include "caca.h"
35#include "caca_internals.h"
36
37/* Dithering methods */
38static void init_no_dither(int);
39static int get_no_dither(void);
40static void increment_no_dither(void);
41
42static void init_ordered_dither(int);
43static int get_ordered_dither(void);
44static void increment_ordered_dither(void);
45
46static void init_random_dither(int);
47static int get_random_dither(void);
48static void increment_random_dither(void);
49
50/* Current dithering method */
51static enum caca_dithering _caca_dithering = CACA_DITHER_NONE;
52
53static void (*_init_dither) (int) = init_no_dither;
54static int (*_get_dither) (void) = get_no_dither;
55static void (*_increment_dither) (void) = increment_no_dither;
56
57void caca_set_dithering(enum caca_dithering dither)
58{
59    switch(dither)
60    {
61    case CACA_DITHER_NONE:
62        _init_dither = init_no_dither;
63        _get_dither = get_no_dither;
64        _increment_dither = increment_no_dither;
65        break;
66
67    case CACA_DITHER_ORDERED:
68        _init_dither = init_ordered_dither;
69        _get_dither = get_ordered_dither;
70        _increment_dither = increment_ordered_dither;
71        break;
72
73    case CACA_DITHER_RANDOM:
74        _init_dither = init_random_dither;
75        _get_dither = get_random_dither;
76        _increment_dither = increment_random_dither;
77        break;
78
79    default:
80        return;
81    }
82
83    _caca_dithering = dither;
84}
85
86struct caca_bitmap
87{
88    int bpp;
89    int w, h, pitch;
90    int rmask, gmask, bmask;
91};
92
93struct caca_bitmap *caca_create_bitmap(int bpp, int w, int h, int pitch,
94                                       int rmask, int gmask, int bmask)
95{
96    struct caca_bitmap *bitmap;
97
98    /* Currently only this format is supported. Will improve later. */
99    if(!w || !h || !pitch || bpp != 32 ||
100       rmask != 0x00ff0000 || gmask != 0x0000ff00 || bmask != 0x000000ff)
101        return NULL;
102
103    bitmap = malloc(sizeof(struct caca_bitmap));
104    if(!bitmap)
105        return NULL;
106
107    bitmap->bpp = bpp;
108
109    bitmap->w = w;
110    bitmap->h = h;
111    bitmap->pitch = pitch;
112
113    bitmap->rmask = rmask;
114    bitmap->gmask = gmask;
115    bitmap->bmask = bmask;
116
117    return bitmap;
118}
119
120void caca_free_bitmap(struct caca_bitmap *bitmap)
121{
122    if(!bitmap)
123        return;
124
125    free(bitmap);
126}
127
128void caca_draw_bitmap(int x1, int y1, int x2, int y2,
129                      struct caca_bitmap *bitmap, char *pixels)
130{
131    /* FIXME: this code is shite! */
132    static int white_colors[] = {CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE};
133    static int light_colors[] = {CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, CACA_COLOR_YELLOW, CACA_COLOR_LIGHTGREEN, CACA_COLOR_LIGHTCYAN, CACA_COLOR_LIGHTBLUE, CACA_COLOR_LIGHTMAGENTA};
134    static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN, CACA_COLOR_GREEN, CACA_COLOR_CYAN, CACA_COLOR_BLUE, CACA_COLOR_MAGENTA};
135    static char foo[] = { ' ', '.', ':', ';', '=', '%', '$', 'W', '#', '8', '@' };
136    int x, y, w, h, pitch;
137
138    if(!bitmap || !pixels)
139        return;
140
141    w = bitmap->w;
142    h = bitmap->h;
143    pitch = bitmap->pitch;
144
145    if(x1 > x2)
146    {
147        int tmp = x2; x2 = x1; x1 = tmp;
148    }
149
150    if(y1 > y2)
151    {
152        int tmp = y2; y2 = y1; y1 = tmp;
153    }
154
155    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)caca_get_height(); y++)
156    {
157        /* Initialize dither tables for the current line */
158        _init_dither(y);
159
160        /* Dither the current line */
161        for(x = x1 > 0 ? x1 : 0; x <= x2 && x <= (int)caca_get_width(); x++)
162        {
163            int fromx = w * (x - x1) / (x2 - x1 + 1);
164            int fromy = h * (y - y1) / (y2 - y1 + 1);
165            /* FIXME: bwahaaa, we don't even respect masks */
166            int b = ((unsigned char *)pixels)[4 * fromx + pitch * fromy];
167            int g = ((unsigned char *)pixels)[4 * fromx + 1 + pitch * fromy];
168            int r = ((unsigned char *)pixels)[4 * fromx + 2 + pitch * fromy];
169            int hue, sat, val;
170
171            int min = r, max = r, delta;
172            if(min > g) min = g; if(max < g) max = g;
173            if(min > b) min = b; if(max < b) max = b;
174
175            delta = max - min;
176            val = max; /* 0 - 255 */
177            sat = max ? 256 * delta / max : 0; /* 0 - 255 */
178
179            if(sat > (_get_dither() + 24) * 4)
180            {
181                /* XXX: Values should be between 1 and 6, but since we
182                 * are dithering, there may be overflows, hence our bigger
183                 * *_colors[] tables. */
184                if( r == max )
185                    hue = 256 + 256 * (g - b) / delta;
186                else if( g == max )
187                    hue = 768 + 256 * (b - r) / delta;
188                else
189                    hue = 1280 + 256 * (r - g) / delta;
190
191                hue = (hue + 128 + 16 * _get_dither()) / 256;
192
193                if(val > (_get_dither() + 40) * 4)
194                    caca_set_color(light_colors[hue]);
195                else
196                    caca_set_color(dark_colors[hue]);
197            }
198            else
199            {
200                caca_set_color(white_colors[max * 3 / 256]);
201            }
202
203            caca_putchar(x, y, foo[(r + g + b + 2 * _get_dither()) / 3 / 25]);
204
205            _increment_dither();
206        }
207    }
208}
209
210/*
211 * XXX: The following functions are local.
212 */
213
214/*
215 * No dithering
216 */
217static void init_no_dither(int line)
218{
219    ;
220}
221
222static int get_no_dither(void)
223{
224    return 0;
225}
226
227static void increment_no_dither(void)
228{
229    return;
230}
231
232/*
233 * Ordered dithering
234 */
235static int dither4x4[] = {-8,  0, -6,  2,
236                           4, -4,  6, -2,
237                          -5,  3, -7,  1,
238                           7, -1,  5, -3};
239static int *dither_table;
240static int dither_index;
241
242static void init_ordered_dither(int line)
243{
244    dither_table = dither4x4 + (line % 4) * 4;
245    dither_index = 0;
246}
247
248static int get_ordered_dither(void)
249{
250    return dither_table[dither_index];
251}
252
253static void increment_ordered_dither(void)
254{
255    dither_index = (dither_index + 1) % 4;
256}
257
258/*
259 * Random dithering
260 */
261static void init_random_dither(int line)
262{
263    ;
264}
265
266static int get_random_dither(void)
267{
268    return caca_rand(-8, 7);
269}
270
271static void increment_random_dither(void)
272{
273    return;
274}
275
Note: See TracBrowser for help on using the repository browser.