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

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