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

Last change on this file since 322 was 322, checked in by Sam Hocevar, 17 years ago
  • libcaca.spec debian/control: + Updated the package descriptions to include cacaball.
  • doc/cacademo.1 doc/Makefile.am: + Use the cacademo manpage as the cacaball manpage.
  • src/: + Added #ifdef _DOXYGEN_SKIP_ME here and there to prvent Doxygen from

documenting bizarre stuff.

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