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

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