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

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