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

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