source: libcaca/trunk/src/bitmap.c @ 306

Last change on this file since 306 was 306, checked in by Sam Hocevar, 17 years ago
  • src/bitmap.c: + Fixed a minor overflow in the saturation computation. + Use a global lookup table for foreground/background colour selection

in the bitmap rendering routine. This broke dithering, sorry.

  • Property svn:keywords set to Id
File size: 22.9 KB
Line 
1/*
2 *  libcaca       ASCII-Art library
3 *  Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2 of the License, or (at your option) any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 *  02111-1307  USA
20 */
21
22/** \file bitmap.c
23 *  \version \$Id: bitmap.c 306 2004-01-02 18:09:29Z sam $
24 *  \author Sam Hocevar <sam@zoy.org>
25 *  \brief Bitmap blitting
26 *
27 *  This file contains bitmap blitting functions.
28 */
29
30#include "config.h"
31
32#if defined(HAVE_INTTYPES_H)
33#   include <inttypes.h>
34#else
35typedef unsigned char uint8_t;
36typedef unsigned short uint16_t;
37typedef unsigned int uint32_t;
38#endif
39
40#if defined(HAVE_ENDIAN_H)
41#   include <endian.h>
42#endif
43
44#include <stdlib.h>
45
46#include "caca.h"
47#include "caca_internals.h"
48
49/*
50 * Global variables
51 */
52enum caca_feature _caca_background;
53enum caca_feature _caca_dithering;
54enum caca_feature _caca_antialiasing;
55
56/*
57 * Local variables
58 */
59#define LOOKUP_VAL 32
60#define LOOKUP_SAT 32
61#define LOOKUP_HUE 16
62static unsigned char lookup_table[LOOKUP_VAL][LOOKUP_SAT][LOOKUP_HUE];
63static enum caca_color lookup_colors[8];
64
65static int const hsv_palette[] =
66{
67    /* hue, saturation, value */
68    0x0,    0x0,    0x0,   /* black */
69    0x0,    0x0,    0x5ff, /* 30% */
70    0x0,    0x0,    0x9ff, /* 70% */
71    0x0,    0x0,    0xfff, /* white */
72    0x1000, 0xfff,  0x5ff, /* dark yellow */
73    0x1000, 0xfff,  0xfff, /* light yellow */
74    0x0,    0xfff,  0x5ff, /* dark red */
75    0x0,    0xfff,  0xfff  /* light red */
76};
77
78#define HSV_XRATIO (5*5)
79#define HSV_YRATIO (3*3)
80#define HSV_HRATIO (2*2)
81
82#define HSV_DISTANCE(h, s, v, index) \
83    ((HSV_XRATIO * ((v) - hsv_palette[index * 3 + 2]) \
84                 * ((v) - hsv_palette[index * 3 + 2])) \
85    + (hsv_palette[index * 3 + 2] \
86        ? (HSV_YRATIO * ((s) - hsv_palette[index * 3 + 1]) \
87                      * ((s) - hsv_palette[index * 3 + 1])) \
88        : 0) \
89    + (hsv_palette[index * 3 + 1] \
90        ? (HSV_HRATIO * ((h) - hsv_palette[index * 3 + 0]) \
91                      * ((h) - hsv_palette[index * 3 + 0])) \
92        : 0))
93
94/*
95 * Local prototypes
96 */
97static void mask2shift(unsigned int, int *, int *);
98
99static void get_rgba_default(struct caca_bitmap const *, uint8_t *, int, int,
100                             unsigned int *, unsigned int *, unsigned int *,
101                             unsigned int *);
102static inline void rgb2hsv_default(int, int, int, int *, int *, int *);
103
104/* Dithering methods */
105static void init_no_dither(int);
106static unsigned int get_no_dither(void);
107static void increment_no_dither(void);
108
109static void init_ordered2_dither(int);
110static unsigned int get_ordered2_dither(void);
111static void increment_ordered2_dither(void);
112
113static void init_ordered4_dither(int);
114static unsigned int get_ordered4_dither(void);
115static void increment_ordered4_dither(void);
116
117static void init_ordered8_dither(int);
118static unsigned int get_ordered8_dither(void);
119static void increment_ordered8_dither(void);
120
121static void init_random_dither(int);
122static unsigned int get_random_dither(void);
123static void increment_random_dither(void);
124
125struct caca_bitmap
126{
127    int bpp, has_palette, has_alpha;
128    int w, h, pitch;
129    int rmask, gmask, bmask, amask;
130    int rright, gright, bright, aright;
131    int rleft, gleft, bleft, aleft;
132    void (*get_hsv)(struct caca_bitmap *, char *, int, int);
133    int red[256], green[256], blue[256], alpha[256];
134};
135
136static void mask2shift(unsigned int mask, int *right, int *left)
137{
138    int rshift = 0, lshift = 0;
139
140    if(!mask)
141    {
142        *right = *left = 0;
143        return;
144    }
145
146    while(!(mask & 1))
147    {
148        mask >>= 1;
149        rshift++;
150    }
151    *right = rshift;
152
153    while(mask & 1)
154    {
155        mask >>= 1;
156        lshift++;
157    }
158    *left = 12 - lshift;
159}
160
161/**
162 * \brief Create an internal bitmap object.
163 *
164 * \param bpp The bitmap depth in bits per pixel.
165 * \param w The bitmap width in pixels.
166 * \param h The bitmap height in pixels.
167 * \param pitch The bitmap pitch in bytes.
168 * \param rmask The bitmask for red values.
169 * \param gmask The bitmask for green values.
170 * \param bmask The bitmask for blue values.
171 * \param amask The bitmask for alpha values.
172 * \return A bitmap object or NULL upon error.
173 */
174struct caca_bitmap *caca_create_bitmap(unsigned int bpp, unsigned int w,
175                                       unsigned int h, unsigned int pitch,
176                                       unsigned int rmask, unsigned int gmask,
177                                       unsigned int bmask, unsigned int amask)
178{
179    struct caca_bitmap *bitmap;
180
181    /* Minor sanity test */
182    if(!w || !h || !pitch || bpp > 32 || bpp < 8)
183        return NULL;
184
185    bitmap = malloc(sizeof(struct caca_bitmap));
186    if(!bitmap)
187        return NULL;
188
189    bitmap->bpp = bpp;
190    bitmap->has_palette = 0;
191    bitmap->has_alpha = amask ? 1 : 0;
192
193    bitmap->w = w;
194    bitmap->h = h;
195    bitmap->pitch = pitch;
196
197    bitmap->rmask = rmask;
198    bitmap->gmask = gmask;
199    bitmap->bmask = bmask;
200    bitmap->amask = amask;
201
202    /* Load bitmasks */
203    if(rmask || gmask || bmask || amask)
204    {
205        mask2shift(rmask, &bitmap->rright, &bitmap->rleft);
206        mask2shift(gmask, &bitmap->gright, &bitmap->gleft);
207        mask2shift(bmask, &bitmap->bright, &bitmap->bleft);
208        mask2shift(amask, &bitmap->aright, &bitmap->aleft);
209    }
210
211    /* In 8 bpp mode, default to a grayscale palette */
212    if(bpp == 8)
213    {
214        int i;
215        bitmap->has_palette = 1;
216        bitmap->has_alpha = 0;
217        for(i = 0; i < 256; i++)
218        {
219            bitmap->red[i] = i * 0xfff / 256;
220            bitmap->green[i] = i * 0xfff / 256;
221            bitmap->blue[i] = i * 0xfff / 256;
222        }
223    }
224
225    return bitmap;
226}
227
228/**
229 * \brief Set the palette of an 8bpp bitmap object.
230 *
231 * \param bpp The bitmap object.
232 * \param red An array of 256 red values.
233 * \param green An array of 256 green values.
234 * \param blue An array of 256 blue values.
235 * \param alpha An array of 256 alpha values.
236 * \return void
237 */
238void caca_set_bitmap_palette(struct caca_bitmap *bitmap,
239                             unsigned int red[], unsigned int green[],
240                             unsigned int blue[], unsigned int alpha[])
241{
242    int i, has_alpha = 0;
243
244    if(bitmap->bpp != 8)
245        return;
246
247    for(i = 0; i < 256; i++)
248    {
249        if(red[i] >= 0 && red[i] < 0x1000 &&
250           green[i] >= 0 && green[i] < 0x1000 &&
251           blue[i] >= 0 && blue[i] < 0x1000 &&
252           alpha[i] >= 0 && alpha[i] < 0x1000)
253        {
254            bitmap->red[i] = red[i];
255            bitmap->green[i] = green[i];
256            bitmap->blue[i] = blue[i];
257            if(alpha[i])
258            {
259                bitmap->alpha[i] = alpha[i];
260                has_alpha = 1;
261            }
262        }
263    }
264
265    bitmap->has_alpha = has_alpha;
266}
267
268/**
269 * \brief Free the memory associated with a bitmap.
270 *
271 * \param bitmap The bitmap object to be freed.
272 * \return void
273 */
274void caca_free_bitmap(struct caca_bitmap *bitmap)
275{
276    if(!bitmap)
277        return;
278
279    free(bitmap);
280}
281
282static void get_rgba_default(struct caca_bitmap const *bitmap, uint8_t *pixels,
283                             int x, int y, unsigned int *r, unsigned int *g,
284                             unsigned int *b, unsigned int *a)
285{
286    uint32_t bits;
287
288    pixels += (bitmap->bpp / 8) * x + bitmap->pitch * y;
289
290    switch(bitmap->bpp / 8)
291    {
292        case 4:
293            bits = *(uint32_t *)pixels;
294            break;
295        case 3:
296        {
297#if defined(HAVE_ENDIAN_H)
298            if(__BYTE_ORDER == __BIG_ENDIAN)
299#else
300            /* This is compile-time optimised with at least -O1 or -Os */
301            uint32_t const rmask = 0x12345678;
302            if(*(uint8_t const *)&rmask == 0x12)
303#endif
304                bits = ((uint32_t)pixels[0] << 16) |
305                       ((uint32_t)pixels[1] << 8) |
306                       ((uint32_t)pixels[2]);
307            else
308                bits = ((uint32_t)pixels[2] << 16) |
309                       ((uint32_t)pixels[1] << 8) |
310                       ((uint32_t)pixels[0]);
311            break;
312        }
313        case 2:
314            bits = *(uint16_t *)pixels;
315            break;
316        case 1:
317        default:
318            bits = pixels[0];
319            break;
320    }
321
322    if(bitmap->has_palette)
323    {
324        *r += bitmap->red[bits];
325        *g += bitmap->green[bits];
326        *b += bitmap->blue[bits];
327        *a += bitmap->alpha[bits];
328    }
329    else
330    {
331        *r += ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;
332        *g += ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;
333        *b += ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;
334        *a += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft;
335    }
336}
337
338static inline void rgb2hsv_default(int r, int g, int b,
339                                   int *hue, int *sat, int *val)
340{
341    int min, max, delta;
342
343    min = r; max = r;
344    if(min > g) min = g; if(max < g) max = g;
345    if(min > b) min = b; if(max < b) max = b;
346
347    delta = max - min; /* 0 - 0xfff */
348    *val = max; /* 0 - 0xfff */
349
350    if(delta)
351    {
352        *sat = 0xfff * delta / max; /* 0 - 0xfff */
353
354        /* Generate *hue between 0 and 0x5fff */
355        if( r == max )
356            *hue = 0x1000 + 0x1000 * (g - b) / delta;
357        else if( g == max )
358            *hue = 0x3000 + 0x1000 * (b - r) / delta;
359        else
360            *hue = 0x5000 + 0x1000 * (r - g) / delta;
361    }
362    else
363    {
364        *sat = 0;
365        *hue = 0;
366    }
367}
368
369/**
370 * \brief Draw a bitmap on the screen.
371 *
372 * \param x1 X coordinate of the upper-left corner of the drawing area.
373 * \param y1 Y coordinate of the upper-left corner of the drawing area.
374 * \param x2 X coordinate of the lower-right corner of the drawing area.
375 * \param y2 Y coordinate of the lower-right corner of the drawing area.
376 * \param bitmap The bitmap object to be drawn.
377 * \param pixels A pointer to the bitmap's pixels.
378 * \return void
379 */
380void caca_draw_bitmap(int x1, int y1, int x2, int y2,
381                      struct caca_bitmap const *bitmap, void *pixels)
382{
383    /* Current dithering method */
384    void (*_init_dither) (int);
385    unsigned int (*_get_dither) (void);
386    void (*_increment_dither) (void);
387
388    /* Only used when background is black */
389    static int const white_colors[] =
390    {
391        CACA_COLOR_BLACK,
392        CACA_COLOR_DARKGRAY,
393        CACA_COLOR_LIGHTGRAY,
394        CACA_COLOR_WHITE
395    };
396
397    static int const light_colors[] =
398    {
399        CACA_COLOR_LIGHTMAGENTA,
400        CACA_COLOR_LIGHTRED,
401        CACA_COLOR_YELLOW,
402        CACA_COLOR_LIGHTGREEN,
403        CACA_COLOR_LIGHTCYAN,
404        CACA_COLOR_LIGHTBLUE,
405        CACA_COLOR_LIGHTMAGENTA
406    };
407
408    static int const dark_colors[] =
409    {
410        CACA_COLOR_MAGENTA,
411        CACA_COLOR_RED,
412        CACA_COLOR_BROWN,
413        CACA_COLOR_GREEN,
414        CACA_COLOR_CYAN,
415        CACA_COLOR_BLUE,
416        CACA_COLOR_MAGENTA
417    };
418
419    /* FIXME: choose better characters! */
420#   define DENSITY_CHARS 13
421    static char const density_chars[] =
422        "    "
423        ".   "
424        "..  "
425        "...."
426        "::::"
427        ";=;="
428        "tftf"
429        "%$%$"
430        "&KSZ"
431        "WXGM"
432        "@@@@"
433        "8888"
434        "####"
435        "????";
436
437    int x, y, w, h, pitch;
438
439    if(!bitmap || !pixels)
440        return;
441
442    w = bitmap->w;
443    h = bitmap->h;
444    pitch = bitmap->pitch;
445
446    if(x1 > x2)
447    {
448        int tmp = x2; x2 = x1; x1 = tmp;
449    }
450
451    if(y1 > y2)
452    {
453        int tmp = y2; y2 = y1; y1 = tmp;
454    }
455
456    switch(_caca_dithering)
457    {
458    case CACA_DITHERING_NONE:
459        _init_dither = init_no_dither;
460        _get_dither = get_no_dither;
461        _increment_dither = increment_no_dither;
462        break;
463
464    case CACA_DITHERING_ORDERED2:
465        _init_dither = init_ordered2_dither;
466        _get_dither = get_ordered2_dither;
467        _increment_dither = increment_ordered2_dither;
468        break;
469
470    case CACA_DITHERING_ORDERED4:
471        _init_dither = init_ordered4_dither;
472        _get_dither = get_ordered4_dither;
473        _increment_dither = increment_ordered4_dither;
474        break;
475
476    case CACA_DITHERING_ORDERED8:
477        _init_dither = init_ordered8_dither;
478        _get_dither = get_ordered8_dither;
479        _increment_dither = increment_ordered8_dither;
480        break;
481
482    case CACA_DITHERING_RANDOM:
483        _init_dither = init_random_dither;
484        _get_dither = get_random_dither;
485        _increment_dither = increment_random_dither;
486        break;
487
488    default:
489        /* Something wicked happened! */
490        return;
491    }
492
493    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++)
494        for(x = x1 > 0 ? x1 : 0, _init_dither(y);
495            x <= x2 && x <= (int)_caca_width;
496            x++)
497    {
498        int ch;
499        unsigned int r, g, b, a;
500        int hue, sat, val;
501        int fromx, fromy, tox, toy, myx, myy, dots;
502        enum caca_color outfg, outbg;
503        char outch;
504
505        r = g = b = a = 0;
506
507        /* First get RGB */
508        if(_caca_antialiasing == CACA_ANTIALIASING_PREFILTER)
509        {
510            fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1);
511            fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1);
512            tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1);
513            toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1);
514            dots = 0;
515
516            for(myx = fromx; myx <= tox; myx++)
517                for(myy = fromy; myy <= toy; myy++)
518            {
519                dots++;
520                get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
521            }
522
523            /* Normalize */
524            r /= dots;
525            g /= dots;
526            b /= dots;
527            a /= dots;
528        }
529        else
530        {
531            fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1);
532            fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1);
533            tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1);
534            toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1);
535
536            myx = (fromx + tox) / 2;
537            myy = (fromy + toy) / 2;
538
539            get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
540        }
541
542        if(bitmap->has_alpha && a < 0x800)
543            continue;
544
545        /* Now get HSV from RGB */
546        rgb2hsv_default(r, g, b, &hue, &sat, &val);
547
548        /* The hard work: calculate foreground and background colours,
549         * as well as the most appropriate character to output. */
550        if(_caca_background == CACA_BACKGROUND_SOLID)
551        {
552            unsigned char point;
553            int distfg, distbg;
554
555            lookup_colors[4] = dark_colors[1 + hue / 0x1000];
556            lookup_colors[5] = light_colors[1 + hue / 0x1000];
557            lookup_colors[6] = dark_colors[hue / 0x1000];
558            lookup_colors[7] = light_colors[hue / 0x1000];
559
560            point = lookup_table[val * LOOKUP_VAL / 0x1000]
561                                [sat * LOOKUP_SAT / 0x1000]
562                                [(hue & 0xfff) * LOOKUP_HUE / 0x1000];
563
564try_again:
565            distfg = HSV_DISTANCE(hue % 0xfff, sat, val, (point >> 4));
566            distbg = HSV_DISTANCE(hue % 0xfff, sat, val, (point & 0xf));
567
568            /* Sanity check due to the lack of precision in lookup_table */
569#if 0
570            if(distbg > distfg)
571            {
572                point = ((point & 0xf) << 4) | (point >> 4);
573                goto try_again;
574            }
575#endif
576            if(distbg > distfg)
577                distbg = distfg;
578
579            outfg = lookup_colors[(point >> 4)];
580            outbg = lookup_colors[(point & 0xf)];
581
582            outch = density_chars[4 * (distbg * (DENSITY_CHARS - 1) / distfg)];
583        }
584        else
585        {
586            outbg = CACA_COLOR_BLACK;
587            if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
588                outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10)
589                                       / 0x1000];
590            else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
591                outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
592            else
593                outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
594
595            ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
596            ch = 4 * ch + _get_dither() / 0x40;
597            outch = density_chars[ch];
598        }
599
600        /* Now output the character */
601        caca_set_color(outfg, outbg);
602        caca_putchar(x, y, outch);
603
604        _increment_dither();
605    }
606}
607
608int _caca_init_bitmap(void)
609{
610    unsigned int v, s, h;
611
612    /* These ones are constant */
613    lookup_colors[0] = CACA_COLOR_BLACK;
614    lookup_colors[1] = CACA_COLOR_DARKGRAY;
615    lookup_colors[2] = CACA_COLOR_LIGHTGRAY;
616    lookup_colors[3] = CACA_COLOR_WHITE;
617
618    /* These ones will be overwritten */
619    lookup_colors[4] = CACA_COLOR_MAGENTA;
620    lookup_colors[5] = CACA_COLOR_LIGHTMAGENTA;
621    lookup_colors[6] = CACA_COLOR_RED;
622    lookup_colors[7] = CACA_COLOR_LIGHTRED;
623
624    for(v = 0; v < LOOKUP_VAL; v++)
625        for(s = 0; s < LOOKUP_SAT; s++)
626            for(h = 0; h < LOOKUP_HUE; h++)
627    {
628        int distbg, distfg, dist;
629        int val, sat, hue;
630        unsigned char outbg, outfg;
631
632        val = 0x1000 * v / LOOKUP_VAL;
633        sat = 0x1000 * s / LOOKUP_SAT;
634        hue = 0x1000 * h / LOOKUP_HUE;
635
636        /* distance to black */
637        distbg = HSV_DISTANCE(hue, sat, val, 0);
638        distbg = distbg * 2 / 4;
639        outbg = 0;
640
641        /* distance to 30% */
642        dist = HSV_DISTANCE(hue, sat, val, 1);
643        dist = dist * 3 / 2;
644        if(dist <= distbg)
645        {
646            outfg = outbg;
647            distfg = distbg;
648            outbg = 1;
649            distbg = dist;
650        }
651        else
652        {
653            outfg = 1;
654            distfg = dist;
655        }
656
657        /* check dist to 70% */
658        dist = HSV_DISTANCE(hue, sat, val, 2);
659        dist = dist * 3 / 2;
660        if(dist <= distbg)
661        {
662            outfg = outbg;
663            distfg = distbg;
664            outbg = 2;
665            distbg = dist;
666        }
667        else if(dist <= distfg)
668        {
669            outfg = 2;
670            distfg = dist;
671        }
672
673        /* check dist to white */
674        dist = HSV_DISTANCE(hue, sat, val, 3);
675        if(dist <= distbg)
676        {
677            outfg = outbg;
678            distfg = distbg;
679            outbg = 3;
680            distbg = dist;
681        }
682        else if(dist <= distfg)
683        {
684            outfg = 3;
685            distfg = dist;
686        }
687
688        /* check dist to 2nd closest dark color */
689        dist = HSV_DISTANCE(hue, sat, val, 4);
690        //dist = dist * 3 / 4;
691        dist = dist * 3 / 4;
692        if(dist <= distbg)
693        {
694            outfg = outbg;
695            distfg = distbg;
696            outbg = 4;
697            distbg = dist;
698        }
699        else if(dist <= distfg)
700        {
701            outfg = 4;
702            distfg = dist;
703        }
704
705        /* check dist to 2nd closest light color */
706        dist = HSV_DISTANCE(hue, sat, val, 5);
707        dist = dist / 2;
708        //dist = dist * 3 / 4;
709        //dist = dist / 2;
710        if(dist <= distbg)
711        {
712            outfg = outbg;
713            distfg = distbg;
714            outbg = 5;
715            distbg = dist;
716        }
717        else if(dist <= distfg)
718        {
719            outfg = 5;
720            distfg = dist;
721        }
722
723        /* check dist to closest dark color */
724        dist = HSV_DISTANCE(hue, sat, val, 6);
725        dist = dist * 3 / 4;
726        if(dist <= distbg)
727        {
728            outfg = outbg;
729            distfg = distbg;
730            outbg = 6;
731            distbg = dist;
732        }
733        else if(dist <= distfg)
734        {
735            outfg = 6;
736            distfg = dist;
737        }
738
739        /* check dist to closest light color */
740        dist = HSV_DISTANCE(hue, sat, val, 7);
741        dist = dist / 2;
742        if(dist <= distbg)
743        {
744            outfg = outbg;
745            distfg = distbg;
746            outbg = 7;
747            distbg = dist;
748        }
749        else if(dist <= distfg)
750        {
751            outfg = 7;
752            distfg = dist;
753        }
754
755        lookup_table[v][s][h] = (outfg << 4) | outbg;
756    }
757
758    return 0;
759}
760
761int _caca_end_bitmap(void)
762{
763    return 0;
764}
765
766/*
767 * XXX: The following functions are local.
768 */
769
770/*
771 * No dithering
772 */
773static void init_no_dither(int line)
774{
775    ;
776}
777
778static unsigned int get_no_dither(void)
779{
780    return 0x80;
781}
782
783static void increment_no_dither(void)
784{
785    return;
786}
787
788/*
789 * Ordered 2 dithering
790 */
791static unsigned int *ordered2_table;
792static unsigned int ordered2_index;
793
794static void init_ordered2_dither(int line)
795{
796    static unsigned int dither2x2[] =
797    {
798        0x00, 0x80,
799        0xc0, 0x40,
800    };
801
802    ordered2_table = dither2x2 + (line % 2) * 2;
803    ordered2_index = 0;
804}
805
806static unsigned int get_ordered2_dither(void)
807{
808    return ordered2_table[ordered2_index];
809}
810
811static void increment_ordered2_dither(void)
812{
813    ordered2_index = (ordered2_index + 1) % 2;
814}
815
816/*
817 * Ordered 4 dithering
818 */
819/*static int dither4x4[] = { 5,  0,  1,  6,
820                          -1, -6, -5,  2,
821                          -2, -7, -8,  3,
822                           4, -3, -4, -7};*/
823static unsigned int *ordered4_table;
824static unsigned int ordered4_index;
825
826static void init_ordered4_dither(int line)
827{
828    static unsigned int dither4x4[] =
829    {
830        0x00, 0x80, 0x20, 0xa0,
831        0xc0, 0x40, 0xe0, 0x60,
832        0x30, 0xb0, 0x10, 0x90,
833        0xf0, 0x70, 0xd0, 0x50
834    };
835
836    ordered4_table = dither4x4 + (line % 4) * 4;
837    ordered4_index = 0;
838}
839
840static unsigned int get_ordered4_dither(void)
841{
842    return ordered4_table[ordered4_index];
843}
844
845static void increment_ordered4_dither(void)
846{
847    ordered4_index = (ordered4_index + 1) % 4;
848}
849
850/*
851 * Ordered 8 dithering
852 */
853static unsigned int *ordered8_table;
854static unsigned int ordered8_index;
855
856static void init_ordered8_dither(int line)
857{
858    static unsigned int dither8x8[] =
859    {
860        0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8,
861        0xc0, 0x40, 0xe0, 0x60, 0xc8, 0x48, 0xe8, 0x68,
862        0x30, 0xb0, 0x10, 0x90, 0x38, 0xb8, 0x18, 0x98,
863        0xf0, 0x70, 0xd0, 0x50, 0xf8, 0x78, 0xd8, 0x58,
864        0x0c, 0x8c, 0x2c, 0xac, 0x04, 0x84, 0x24, 0xa4,
865        0xcc, 0x4c, 0xec, 0x6c, 0xc4, 0x44, 0xe4, 0x64,
866        0x3c, 0xbc, 0x1c, 0x9c, 0x34, 0xb4, 0x14, 0x94,
867        0xfc, 0x7c, 0xdc, 0x5c, 0xf4, 0x74, 0xd4, 0x54,
868    };
869
870    ordered8_table = dither8x8 + (line % 8) * 8;
871    ordered8_index = 0;
872}
873
874static unsigned int get_ordered8_dither(void)
875{
876    return ordered8_table[ordered8_index];
877}
878
879static void increment_ordered8_dither(void)
880{
881    ordered8_index = (ordered8_index + 1) % 8;
882}
883
884/*
885 * Random dithering
886 */
887static void init_random_dither(int line)
888{
889    ;
890}
891
892static unsigned int get_random_dither(void)
893{
894    return caca_rand(0x00, 0xff);
895}
896
897static void increment_random_dither(void)
898{
899    return;
900}
901
Note: See TracBrowser for help on using the repository browser.