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

Last change on this file since 246 was 246, checked in by Sam Hocevar, 17 years ago
  • src/graphics.c: + Internally cache screen width and height.
  • src/bitmap.c: + Added alpha support to caca_draw_bitmap(). For now, we only treat 0%

alpha as fully transparent, and any other value as fully opaque.

+ Slightly tuned colour weights in the renderer.
+ caca_set_bitmap_palette() takes unsigned ints.

  • examples/demo.c: + Added a crap render demo.
  • examples/aafire.c: + Set a 20ms delay. + Added alpha values to the palette.
  • examples/view.c: + Draw a gray checkered grid below the image so that transparent images

look a lot nicer.

+ 'f' toggles "fullscreen" mode.

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