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

Last change on this file since 198 was 198, checked in by Sam Hocevar, 19 years ago
  • src/io.c src/caca.h: + Interpret escape sequences for F1, F2, left, right, etc.
  • src/Makefile.am examples/Makefile.am: + Install caca.h in /usr/include. + Do not install example programs.
  • src/blit.c: + Minor improvements to grayscale colors.
  • Property svn:keywords set to Id
File size: 6.2 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 198 2003-11-17 16:11:34Z 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
86void caca_blit(int x1, int y1, int x2, int y2, void *pixels, int w, int h)
87{
88    static int white_colors[] = {CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE};
89    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};
90    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};
91    static char foo[] = { ' ', '.', ':', ';', '=', '%', '$', 'W', '#', '8', '@' };
92    int x, y, pitch;
93
94    if(x1 > x2)
95    {
96        int tmp = x2; x2 = x1; x1 = tmp;
97    }
98
99    if(y1 > y2)
100    {
101        int tmp = y2; y2 = y1; y1 = tmp;
102    }
103
104    //pitch = (3 * w + 3) / 4 * 4;
105    pitch = 4 * w;
106
107    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)caca_get_height(); y++)
108    {
109        /* Initialize dither tables for the current line */
110        _init_dither(y);
111
112        /* Dither the current line */
113        for(x = x1 > 0 ? x1 : 0; x <= x2 && x <= (int)caca_get_width(); x++)
114        {
115            int fromx = w * (x - x1) / (x2 - x1 + 1);
116            int fromy = h * (y - y1) / (y2 - y1 + 1);
117            //int r = ((unsigned char *)pixels)[3 * fromx + pitch * fromy];
118            //int g = ((unsigned char *)pixels)[3 * fromx + 1 + pitch * fromy];
119            //int b = ((unsigned char *)pixels)[3 * fromx + 2 + pitch * fromy];
120            int b = ((unsigned char *)pixels)[4 * fromx + pitch * fromy];
121            int g = ((unsigned char *)pixels)[4 * fromx + 1 + pitch * fromy];
122            int r = ((unsigned char *)pixels)[4 * fromx + 2 + pitch * fromy];
123            int hue, sat, val;
124
125            int min = r, max = r, delta;
126            if(min > g) min = g; if(max < g) max = g;
127            if(min > b) min = b; if(max < b) max = b;
128
129            delta = max - min;
130            val = max; /* 0 - 255 */
131            sat = max ? 256 * delta / max : 0; /* 0 - 255 */
132
133            if(sat > (_get_dither() + 24) * 4)
134            {
135                /* XXX: Values should be between 1 and 6, but since we
136                 * are dithering, there may be overflows, hence our bigger
137                 * *_colors[] tables. */
138                if( r == max )
139                    hue = 256 + 256 * (g - b) / delta;
140                else if( g == max )
141                    hue = 768 + 256 * (b - r) / delta;
142                else
143                    hue = 1280 + 256 * (r - g) / delta;
144
145                hue = (hue + 128 + 8 * _get_dither()) / 256;
146
147                if(val > (_get_dither() + 40) * 4)
148                    caca_set_color(light_colors[hue]);
149                else
150                    caca_set_color(dark_colors[hue]);
151            }
152            else
153            {
154                caca_set_color(white_colors[max * 3 / 256]);
155            }
156
157            caca_putchar(x, y, foo[(r + g + b + 2 * _get_dither()) / 3 / 25]);
158
159            _increment_dither();
160        }
161    }
162}
163
164/*
165 * XXX: The following functions are local.
166 */
167
168/*
169 * No dithering
170 */
171static void init_no_dither(int line)
172{
173    ;
174}
175
176static int get_no_dither(void)
177{
178    return 0;
179}
180
181static void increment_no_dither(void)
182{
183    return;
184}
185
186/*
187 * Ordered dithering
188 */
189static int dither4x4[] = {-8,  0, -6,  2,
190                           4, -4,  6, -2,
191                          -5,  3, -7,  1,
192                           7, -1,  5, -3};
193static int *dither_table;
194static int dither_index;
195
196static void init_ordered_dither(int line)
197{
198    dither_table = dither4x4 + (line % 4) * 4;
199    dither_index = 0;
200}
201
202static int get_ordered_dither(void)
203{
204    return dither_table[dither_index];
205}
206
207static void increment_ordered_dither(void)
208{
209    dither_index = (dither_index + 1) % 4;
210}
211
212/*
213 * Random dithering
214 */
215static void init_random_dither(int line)
216{
217    ;
218}
219
220static int get_random_dither(void)
221{
222    return caca_rand(-8, 7);
223}
224
225static void increment_random_dither(void)
226{
227    return;
228}
229
Note: See TracBrowser for help on using the repository browser.