source: libcaca/branches/0.7/src/bitmap.c @ 4104

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