source: libcaca/branches/0.9/src/bitmap.c @ 3583

Last change on this file since 3583 was 351, checked in by Sam Hocevar, 18 years ago
  • src/event.c: + Make sure the mouse coordinates stay within the screen boundaries even

if the window was resized.

  • src/bitmap.c: + Fixed a buffer underflow in the rendering routine that caused the bottom

and rightmost pixels to be missed in certain conditions.

+ Minor speed optimisation.

  • Property svn:keywords set to Id
File size: 22.4 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 351 2004-01-14 10:34:20Z 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, deltax, deltay;
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    deltax = x2 - x1 + 1;
479    deltay = y2 - y1 + 1;
480
481    switch(_caca_dithering)
482    {
483    case CACA_DITHERING_NONE:
484        _init_dither = init_no_dither;
485        _get_dither = get_no_dither;
486        _increment_dither = increment_no_dither;
487        break;
488
489    case CACA_DITHERING_ORDERED2:
490        _init_dither = init_ordered2_dither;
491        _get_dither = get_ordered2_dither;
492        _increment_dither = increment_ordered2_dither;
493        break;
494
495    case CACA_DITHERING_ORDERED4:
496        _init_dither = init_ordered4_dither;
497        _get_dither = get_ordered4_dither;
498        _increment_dither = increment_ordered4_dither;
499        break;
500
501    case CACA_DITHERING_ORDERED8:
502        _init_dither = init_ordered8_dither;
503        _get_dither = get_ordered8_dither;
504        _increment_dither = increment_ordered8_dither;
505        break;
506
507    case CACA_DITHERING_RANDOM:
508        _init_dither = init_random_dither;
509        _get_dither = get_random_dither;
510        _increment_dither = increment_random_dither;
511        break;
512
513    default:
514        /* Something wicked happened! */
515        return;
516    }
517
518    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++)
519        for(x = x1 > 0 ? x1 : 0, _init_dither(y);
520            x <= x2 && x <= (int)_caca_width;
521            x++)
522    {
523        int ch;
524        unsigned int r, g, b, a;
525        int hue, sat, val;
526        int fromx, fromy, tox, toy, myx, myy, dots;
527        enum caca_color outfg, outbg;
528        char outch;
529
530        r = g = b = a = 0;
531
532        /* First get RGB */
533        if(_caca_antialiasing == CACA_ANTIALIASING_PREFILTER)
534        {
535            fromx = (x - x1) * w / deltax;
536            fromy = (y - y1) * h / deltay;
537            tox = (x - x1 + 1) * w / deltax;
538            toy = (y - y1 + 1) * h / deltay;
539
540            /* We want at least one pixel */
541            if(tox == fromx) tox++;
542            if(toy == fromy) toy++;
543
544            dots = 0;
545
546            for(myx = fromx; myx < tox; myx++)
547                for(myy = fromy; myy < toy; myy++)
548            {
549                dots++;
550                get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
551            }
552
553            /* Normalize */
554            r /= dots;
555            g /= dots;
556            b /= dots;
557            a /= dots;
558        }
559        else
560        {
561            fromx = (x - x1) * w / deltax;
562            fromy = (y - y1) * h / deltay;
563            tox = (x - x1 + 1) * w / deltax;
564            toy = (y - y1 + 1) * h / deltay;
565
566            /* tox and toy can overflow the screen, but they cannot overflow
567             * when averaged with fromx and fromy because these are guaranteed
568             * to be within the pixel boundaries. */
569            myx = (fromx + tox) / 2;
570            myy = (fromy + toy) / 2;
571
572            get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
573        }
574
575        if(bitmap->has_alpha && a < 0x800)
576            continue;
577
578        /* Now get HSV from RGB */
579        rgb2hsv_default(r, g, b, &hue, &sat, &val);
580
581        /* The hard work: calculate foreground and background colours,
582         * as well as the most appropriate character to output. */
583        if(_caca_background == CACA_BACKGROUND_SOLID)
584        {
585            unsigned char point;
586            int distfg, distbg;
587
588            lookup_colors[4] = dark_colors[1 + hue / 0x1000];
589            lookup_colors[5] = light_colors[1 + hue / 0x1000];
590            lookup_colors[6] = dark_colors[hue / 0x1000];
591            lookup_colors[7] = light_colors[hue / 0x1000];
592
593            point = hsv_distances[(val + _get_dither() * (0x1000 / LOOKUP_VAL)
594                                    / 0x100) * (LOOKUP_VAL - 1) / 0x1000]
595                                 [(sat + _get_dither() * (0x1000 / LOOKUP_SAT)
596                                    / 0x100) * (LOOKUP_SAT - 1) / 0x1000]
597                                 [((hue & 0xfff) + _get_dither()
598                                            * (0x1000 / LOOKUP_HUE) / 0x100)
599                                            * (LOOKUP_HUE - 1) / 0x1000];
600
601            distfg = HSV_DISTANCE(hue % 0xfff, sat, val, (point >> 4));
602            distbg = HSV_DISTANCE(hue % 0xfff, sat, val, (point & 0xf));
603
604            /* Sanity check due to the lack of precision in hsv_distances,
605             * and distbg can be > distfg because of dithering fuzziness. */
606            if(distbg > distfg)
607                distbg = distfg;
608
609            outfg = lookup_colors[(point >> 4)];
610            outbg = lookup_colors[(point & 0xf)];
611
612            ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
613            ch = 4 * ch + _get_dither() / 0x40;
614            outch = density_chars[ch];
615        }
616        else
617        {
618            outbg = CACA_COLOR_BLACK;
619            if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
620                outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10)
621                                       / 0x1000];
622            else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
623                outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
624            else
625                outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
626
627            ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
628            ch = 4 * ch + _get_dither() / 0x40;
629            outch = density_chars[ch];
630        }
631
632        /* Now output the character */
633        caca_set_color(outfg, outbg);
634        caca_putchar(x, y, outch);
635
636        _increment_dither();
637    }
638}
639
640#if !defined(_DOXYGEN_SKIP_ME)
641int _caca_init_bitmap(void)
642{
643    unsigned int v, s, h;
644
645    /* These ones are constant */
646    lookup_colors[0] = CACA_COLOR_BLACK;
647    lookup_colors[1] = CACA_COLOR_DARKGRAY;
648    lookup_colors[2] = CACA_COLOR_LIGHTGRAY;
649    lookup_colors[3] = CACA_COLOR_WHITE;
650
651    /* These ones will be overwritten */
652    lookup_colors[4] = CACA_COLOR_MAGENTA;
653    lookup_colors[5] = CACA_COLOR_LIGHTMAGENTA;
654    lookup_colors[6] = CACA_COLOR_RED;
655    lookup_colors[7] = CACA_COLOR_LIGHTRED;
656
657    for(v = 0; v < LOOKUP_VAL; v++)
658        for(s = 0; s < LOOKUP_SAT; s++)
659            for(h = 0; h < LOOKUP_HUE; h++)
660    {
661        int i, distbg, distfg, dist;
662        int val, sat, hue;
663        unsigned char outbg, outfg;
664
665        val = 0xfff * v / (LOOKUP_VAL - 1);
666        sat = 0xfff * s / (LOOKUP_SAT - 1);
667        hue = 0xfff * h / (LOOKUP_HUE - 1);
668
669        /* Initialise distances to the distance between pure black HSV
670         * coordinates and our white colour (3) */
671        outbg = outfg = 3;
672        distbg = distfg = HSV_DISTANCE(0, 0, 0, 3);
673
674        /* Calculate distances to eight major colour values and store the
675         * two nearest points in our lookup table. */
676        for(i = 0; i < 8; i++)
677        {
678            dist = HSV_DISTANCE(hue, sat, val, i);
679            if(dist <= distbg)
680            {
681                outfg = outbg;
682                distfg = distbg;
683                outbg = i;
684                distbg = dist;
685            }
686            else if(dist <= distfg)
687            {
688                outfg = i;
689                distfg = dist;
690            }
691        }
692
693        hsv_distances[v][s][h] = (outfg << 4) | outbg;
694    }
695
696    return 0;
697}
698
699int _caca_end_bitmap(void)
700{
701    return 0;
702}
703#endif /* _DOXYGEN_SKIP_ME */
704
705/*
706 * XXX: The following functions are local.
707 */
708
709/*
710 * No dithering
711 */
712static void init_no_dither(int line)
713{
714    ;
715}
716
717static unsigned int get_no_dither(void)
718{
719    return 0x80;
720}
721
722static void increment_no_dither(void)
723{
724    return;
725}
726
727/*
728 * Ordered 2 dithering
729 */
730static unsigned int *ordered2_table;
731static unsigned int ordered2_index;
732
733static void init_ordered2_dither(int line)
734{
735    static unsigned int dither2x2[] =
736    {
737        0x00, 0x80,
738        0xc0, 0x40,
739    };
740
741    ordered2_table = dither2x2 + (line % 2) * 2;
742    ordered2_index = 0;
743}
744
745static unsigned int get_ordered2_dither(void)
746{
747    return ordered2_table[ordered2_index];
748}
749
750static void increment_ordered2_dither(void)
751{
752    ordered2_index = (ordered2_index + 1) % 2;
753}
754
755/*
756 * Ordered 4 dithering
757 */
758/*static int dither4x4[] = { 5,  0,  1,  6,
759                          -1, -6, -5,  2,
760                          -2, -7, -8,  3,
761                           4, -3, -4, -7};*/
762static unsigned int *ordered4_table;
763static unsigned int ordered4_index;
764
765static void init_ordered4_dither(int line)
766{
767    static unsigned int dither4x4[] =
768    {
769        0x00, 0x80, 0x20, 0xa0,
770        0xc0, 0x40, 0xe0, 0x60,
771        0x30, 0xb0, 0x10, 0x90,
772        0xf0, 0x70, 0xd0, 0x50
773    };
774
775    ordered4_table = dither4x4 + (line % 4) * 4;
776    ordered4_index = 0;
777}
778
779static unsigned int get_ordered4_dither(void)
780{
781    return ordered4_table[ordered4_index];
782}
783
784static void increment_ordered4_dither(void)
785{
786    ordered4_index = (ordered4_index + 1) % 4;
787}
788
789/*
790 * Ordered 8 dithering
791 */
792static unsigned int *ordered8_table;
793static unsigned int ordered8_index;
794
795static void init_ordered8_dither(int line)
796{
797    static unsigned int dither8x8[] =
798    {
799        0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8,
800        0xc0, 0x40, 0xe0, 0x60, 0xc8, 0x48, 0xe8, 0x68,
801        0x30, 0xb0, 0x10, 0x90, 0x38, 0xb8, 0x18, 0x98,
802        0xf0, 0x70, 0xd0, 0x50, 0xf8, 0x78, 0xd8, 0x58,
803        0x0c, 0x8c, 0x2c, 0xac, 0x04, 0x84, 0x24, 0xa4,
804        0xcc, 0x4c, 0xec, 0x6c, 0xc4, 0x44, 0xe4, 0x64,
805        0x3c, 0xbc, 0x1c, 0x9c, 0x34, 0xb4, 0x14, 0x94,
806        0xfc, 0x7c, 0xdc, 0x5c, 0xf4, 0x74, 0xd4, 0x54,
807    };
808
809    ordered8_table = dither8x8 + (line % 8) * 8;
810    ordered8_index = 0;
811}
812
813static unsigned int get_ordered8_dither(void)
814{
815    return ordered8_table[ordered8_index];
816}
817
818static void increment_ordered8_dither(void)
819{
820    ordered8_index = (ordered8_index + 1) % 8;
821}
822
823/*
824 * Random dithering
825 */
826static void init_random_dither(int line)
827{
828    ;
829}
830
831static unsigned int get_random_dither(void)
832{
833    return caca_rand(0x00, 0xff);
834}
835
836static void increment_random_dither(void)
837{
838    return;
839}
840
Note: See TracBrowser for help on using the repository browser.