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

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