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

Last change on this file since 249 was 249, checked in by Sam Hocevar, 19 years ago
  • src/bitmap.c: + Added antialiasing support. + Dithering, antialiasing and background mode can now be selected at

runtime.

  • src/caca.c src/caca.h: + Renamed caca_dithering into caca_feature and extended the type to

express background colour and antialiasing mode.

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