TinyGL 0.4.1 for MinGW
zdither.c
Go to the documentation of this file.
1/*
2 * Highly optimised dithering 16 bits -> 8 bits.
3 * The formulas were taken in Mesa (Bob Mercier mercier@hollywood.cinenet.net).
4 */
5
6#include <stdlib.h>
7#include <stdio.h>
8#include "zbuffer.h"
9#include <assert.h>
10
11#if defined(TGL_FEATURE_8_BITS)
12
13#if TGL_FEATURE_RENDER_BITS != 16
14#error TGL_FEATURE_8_BITS is not supported for this value of TGL_FEATURE_RENDER_BITS
15#endif
16
17#define _R 5
18#define _G 9
19#define _B 5
20#define _DX 4
21#define _DY 4
22#define _D (_DX*_DY)
23#define _MIX(r,g,b) ( ((g)<<6) | ((b)<<3) | (r) )
24
25#define DITHER_TABLE_SIZE (1 << 15)
26
27#define DITHER_INDEX(r,g,b) ((b) + (g) * _B + (r) * (_B * _G))
28
29#define MAXC 256
30static int kernel8[_DY*_DX] = {
31 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC,
32 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC,
33 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC,
34 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC,
35};
36
37/* we build the color table and the lookup table */
38
39void ZB_initDither(ZBuffer *zb,int nb_colors,
40 unsigned char *color_indexes,int *color_table)
41{
42 int c,r,g,b,i,index,r1,g1,b1;
43
44 if (nb_colors < (_R * _G * _B)) {
45 fprintf(stderr,"zdither: not enough colors\n");
46 exit(1);
47 }
48
49 for(i=0;i<nb_colors;i++) color_table[i]=0;
50
51 zb->nb_colors=nb_colors;
52 zb->ctable=gl_malloc(nb_colors * sizeof(int));
53
54 for (r = 0; r < _R; r++) {
55 for (g = 0; g < _G; g++) {
56 for (b = 0; b < _B; b++) {
57 r1=(r*255) / (_R - 1);
58 g1=(g*255) / (_G - 1);
59 b1=(b*255) / (_B - 1);
60 index=DITHER_INDEX(r,g,b);
61 c=(r1 << 16) | (g1 << 8) | b1;
62 zb->ctable[index]=c;
63 color_table[index]=c;
64 }
65 }
66 }
67
69
70 for(i=0;i<DITHER_TABLE_SIZE;i++) {
71 r=(i >> 12) & 0x7;
72 g=(i >> 8) & 0xF;
73 b=(i >> 3) & 0x7;
74 index=DITHER_INDEX(r,g,b);
75 zb->dctable[i]=color_indexes[index];
76 }
77}
78
80{
81 gl_free(zb->ctable);
82 gl_free(zb->dctable);
83}
84
85#if 0
86int ZDither_lookupColor(int r,int g,int b)
87{
88 unsigned char *ctable=zdither_color_table;
89 return ctable[_MIX(_DITH0(_R, r), _DITH0(_G, g),_DITH0(_B, b))];
90}
91#endif
92
93
94#define DITHER_PIXEL2(a) \
95{ \
96 register int v,t,r,g,c; \
97 v=*(unsigned int *)(pp+(a)); \
98 g=(v & 0x07DF07DF) + g_d; \
99 r=(((v & 0xF800F800) >> 2) + r_d) & 0x70007000; \
100 t=r | g; \
101 c=ctable[t & 0xFFFF] | (ctable[t >> 16] << 8); \
102 *(unsigned short *)(dest+(a))=c; \
103}
104
105/* NOTE: all the memory access are 16 bit aligned, so if buf or
106 linesize are not multiple of 2, it cannot work efficiently (or
107 hang!) */
108
109void ZB_ditherFrameBuffer(ZBuffer *zb,unsigned char *buf,
110 int linesize)
111{
112 int xk,yk,x,y,c1,c2;
113 unsigned char *dest1;
114 unsigned short *pp1;
115 int r_d,g_d,b_d;
116 unsigned char *ctable=zb->dctable;
117 register unsigned char *dest;
118 register unsigned short *pp;
119
120 assert( ((long)buf & 1) == 0 && (linesize & 1) == 0);
121
122 for(yk=0;yk<4;yk++) {
123 for(xk=0;xk<4;xk+=2) {
124#if BYTE_ORDER == BIG_ENDIAN
125 c1=kernel8[yk*4+xk+1];
126 c2=kernel8[yk*4+xk];
127#else
128 c1=kernel8[yk*4+xk];
129 c2=kernel8[yk*4+xk+1];
130#endif
131 r_d=((c1 << 2) & 0xF800) >> 2;
132 g_d=(c1 >> 4) & 0x07C0;
133 b_d=(c1 >> 9) & 0x001F;
134
135 r_d|=(((c2 << 2) & 0xF800) >> 2) << 16;
136 g_d|=((c2 >> 4) & 0x07C0) << 16;
137 b_d|=((c2 >> 9) & 0x001F) << 16;
138 g_d=b_d | g_d;
139
140 dest1=buf + (yk * linesize) + xk;
141 pp1=zb->pbuf + (yk * zb->xsize) + xk;
142
143 for(y=yk;y<zb->ysize;y+=4) {
144 dest=dest1;
145 pp=pp1;
146 for(x=xk;x<zb->xsize;x+=16) {
147
148 DITHER_PIXEL2(0);
149 DITHER_PIXEL2(1*4);
150 DITHER_PIXEL2(2*4);
151 DITHER_PIXEL2(3*4);
152
153 pp+=16;
154 dest+=16;
155 }
156 dest1+=linesize*4;
157 pp1+=zb->xsize*4;
158 }
159 }
160 }
161}
162
163#endif /* TGL_FEATURE_8_BITS */
void gl_free(void *p)
Definition: memory.c:8
void * gl_malloc(int size)
Definition: memory.c:13
int nb_colors
Definition: zbuffer.h:83
int * ctable
Definition: zbuffer.h:85
PIXEL * pbuf
Definition: zbuffer.h:80
int ysize
Definition: zbuffer.h:75
unsigned char * dctable
Definition: zbuffer.h:84
int xsize
Definition: zbuffer.h:75
#define DITHER_INDEX(r, g, b)
Definition: zdither.c:27
#define _MIX(r, g, b)
Definition: zdither.c:23
#define _DX
Definition: zdither.c:20
void ZB_initDither(ZBuffer *zb, int nb_colors, unsigned char *color_indexes, int *color_table)
Definition: zdither.c:39
#define _R
Definition: zdither.c:17
#define MAXC
Definition: zdither.c:29
void ZB_ditherFrameBuffer(ZBuffer *zb, unsigned char *buf, int linesize)
Definition: zdither.c:109
#define _DY
Definition: zdither.c:21
#define _B
Definition: zdither.c:19
#define DITHER_TABLE_SIZE
Definition: zdither.c:25
#define DITHER_PIXEL2(a)
Definition: zdither.c:94
#define _G
Definition: zdither.c:18
void ZB_closeDither(ZBuffer *zb)
Definition: zdither.c:79
register PIXEL * pp
Definition: zline.h:4
PIXEL * pp1
Definition: ztriangle.h:9