1 | /* $Id: quantize.c,v 1.2 2001-09-05 14:30:46 bird Exp $ */
|
---|
2 |
|
---|
3 | /*
|
---|
4 | ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
|
---|
5 | ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
|
---|
6 | ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
|
---|
7 | ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
|
---|
8 | ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
|
---|
9 | ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
---|
10 | ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
|
---|
11 | ** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
|
---|
12 | **
|
---|
13 | ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
|
---|
14 | ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
|
---|
15 | ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
|
---|
16 | ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
|
---|
17 | ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
|
---|
18 | ** THE UNITED STATES.
|
---|
19 | **
|
---|
20 | ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
|
---|
21 | **
|
---|
22 | ** $Revision: 1.2 $
|
---|
23 | ** $Date: 2001-09-05 14:30:46 $
|
---|
24 | */
|
---|
25 |
|
---|
26 | #include <stdio.h>
|
---|
27 | #include <stdlib.h>
|
---|
28 | #include <string.h>
|
---|
29 | #include <math.h>
|
---|
30 |
|
---|
31 | #include "texusint.h"
|
---|
32 |
|
---|
33 | static int
|
---|
34 | dithmat[4][4] = { 0, 8, 2, 10,
|
---|
35 | 12, 4, 14, 6,
|
---|
36 | 3, 11, 1, 9,
|
---|
37 | 15, 7, 13, 5 };
|
---|
38 |
|
---|
39 | // for error diffusion.
|
---|
40 | static int errR[MAX_TEXWIDTH], errG[MAX_TEXWIDTH], errB[MAX_TEXWIDTH];
|
---|
41 |
|
---|
42 | static int
|
---|
43 | _txPixQuantize_RGB332( unsigned long argb, int x, int y, int w)
|
---|
44 | {
|
---|
45 | return (
|
---|
46 | (((argb>>16) & 0xE0) |
|
---|
47 | ((argb>>11) & 0x1C) |
|
---|
48 | ((argb>> 6) & 0x03) ) );
|
---|
49 | }
|
---|
50 |
|
---|
51 | static int
|
---|
52 | _txPixQuantize_RGB332_D4x4( unsigned long argb, int x, int y, int w)
|
---|
53 | {
|
---|
54 | int d = dithmat[y&3][x&3];
|
---|
55 | int n, t;
|
---|
56 |
|
---|
57 | n = (int) (((argb >> 16) & 0xFF) * 0x70/255.0f + 0.5f) + d;
|
---|
58 | t = (n>>4)<<5;
|
---|
59 | n = (int) (((argb >> 8) & 0xFF) * 0x70/255.0f + 0.5f) + d;
|
---|
60 | t |= (n>>4)<<2;
|
---|
61 | n = (int) (((argb ) & 0xFF) * 0x30/255.0f + 0.5f) + d;
|
---|
62 | t |= (n>>4)<<0;
|
---|
63 | return t & 0xFF;
|
---|
64 | }
|
---|
65 |
|
---|
66 | static int
|
---|
67 | _txPixQuantize_RGB332_DErr( unsigned long argb, int x, int y, int w)
|
---|
68 | {
|
---|
69 | static unsigned char a3[] = {0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff};
|
---|
70 | static unsigned char a2[] = {0x00,0x55,0xaa,0xff};
|
---|
71 | static int qr, qg, qb; // quantized incoming values.
|
---|
72 | int ir, ig, ib; // incoming values.
|
---|
73 | int t;
|
---|
74 |
|
---|
75 | ir = (argb >> 16) & 0xFF; // incoming pixel values.
|
---|
76 | ig = (argb >> 8) & 0xFF;
|
---|
77 | ib = (argb ) & 0xFF;
|
---|
78 |
|
---|
79 | if (x == 0) qr = qg = qb = 0;
|
---|
80 |
|
---|
81 | ir += errR[x] + qr;
|
---|
82 | ig += errG[x] + qg;
|
---|
83 | ib += errB[x] + qb;
|
---|
84 |
|
---|
85 | qr = ir; // quantized pixel values.
|
---|
86 | qg = ig; // qR is error from pixel to left, errR is
|
---|
87 | qb = ib; // error from pixel to the top & top left.
|
---|
88 |
|
---|
89 | if (qr < 0) qr = 0; if (qr > 255) qr = 255; // clamp.
|
---|
90 | if (qg < 0) qg = 0; if (qg > 255) qg = 255;
|
---|
91 | if (qb < 0) qb = 0; if (qb > 255) qb = 255;
|
---|
92 |
|
---|
93 | // To RGB332.
|
---|
94 | qr = (int) (qr * 0x7ff/255.0f); qr >>= 8;
|
---|
95 | qg = (int) (qg * 0x7ff/255.0f); qg >>= 8;
|
---|
96 | qb = (int) (qb * 0x3ff/255.0f); qb >>= 8;
|
---|
97 |
|
---|
98 | t = (qr << 5) | (qg << 2) | qb; // this is the value to be returned.
|
---|
99 |
|
---|
100 | // Now dequantize the input, and compute & distribute the errors.
|
---|
101 | qr = a3[qr]; qr = ir - qr;
|
---|
102 | qg = a3[qg]; qg = ig - qg;
|
---|
103 | qb = a2[qb]; qb = ib - qb;
|
---|
104 |
|
---|
105 | // 3/8 (=0.375) to the EAST, 3/8 to the SOUTH, 1/4 (0.25) to the SOUTH-EAST.
|
---|
106 | errR[x] = ((x == 0) ? 0 : errR[x]) + ((int) (qr * 0.375f));
|
---|
107 | errG[x] = ((x == 0) ? 0 : errG[x]) + ((int) (qg * 0.375f));
|
---|
108 | errB[x] = ((x == 0) ? 0 : errB[x]) + ((int) (qb * 0.375f));
|
---|
109 |
|
---|
110 | errR[x+1] = (int) (qr * 0.250f);
|
---|
111 | errG[x+1] = (int) (qg * 0.250f);
|
---|
112 | errB[x+1] = (int) (qb * 0.250f);
|
---|
113 |
|
---|
114 | qr = (int) (qr * 0.375f); // Carried to the pixel on the right.
|
---|
115 | qg = (int) (qg * 0.375f);
|
---|
116 | qb = (int) (qb * 0.375f);
|
---|
117 |
|
---|
118 | return t & 0xFF;
|
---|
119 | }
|
---|
120 |
|
---|
121 | /* YIQ422 done elsewhere */
|
---|
122 |
|
---|
123 | static int
|
---|
124 | _txPixQuantize_A8( unsigned long argb, int x, int y, int w)
|
---|
125 | {
|
---|
126 | return (argb >> 24);
|
---|
127 | }
|
---|
128 |
|
---|
129 | static int
|
---|
130 | _txPixQuantize_I8( unsigned long argb, int x, int y, int w)
|
---|
131 | {
|
---|
132 | return (
|
---|
133 | ((int) (((argb >>16) & 0xFF) * .30F +
|
---|
134 | ((argb >> 8) & 0xFF) * .59F +
|
---|
135 | ((argb ) & 0xFF) * .11F + 0.5f )) & 0xFF);
|
---|
136 | }
|
---|
137 |
|
---|
138 | static int
|
---|
139 | _txPixQuantize_AI44( unsigned long argb, int x, int y, int w)
|
---|
140 | {
|
---|
141 | return(
|
---|
142 | (int) (( ((argb>>16) & 0xFF) * .30F +
|
---|
143 | ((argb>> 8) & 0xFF) * .59F +
|
---|
144 | ((argb ) & 0xFF) * .11F + 0.5f ) * 0.0625f) |
|
---|
145 | (int) ((argb>>24) & 0xF0));
|
---|
146 | }
|
---|
147 |
|
---|
148 | static int
|
---|
149 | _txPixQuantize_AI44_D4x4( unsigned long argb, int x, int y, int w)
|
---|
150 | {
|
---|
151 | int d = dithmat[y&3][x&3];
|
---|
152 | int n, t;
|
---|
153 |
|
---|
154 | /* Don't dither alpha channel */
|
---|
155 | n = (int) ( ((argb>>16) & 0xFF) * .30F +
|
---|
156 | ((argb>> 8) & 0xFF) * .59F +
|
---|
157 | ((argb ) & 0xFF) * .11F + 0.5f);
|
---|
158 |
|
---|
159 |
|
---|
160 | n = (int) (n * 0xF0/255.0f + 0.5f) + d;
|
---|
161 | t = (n>>4);
|
---|
162 | t |= (int) ((argb>>24) & 0xF0);
|
---|
163 | return t & 0xFF;
|
---|
164 | }
|
---|
165 |
|
---|
166 | static int
|
---|
167 | _txPixQuantize_AI44_DErr( unsigned long argb, int x, int y, int w)
|
---|
168 | {
|
---|
169 | int ii, t;
|
---|
170 | static int qi;
|
---|
171 |
|
---|
172 | /* Don't dither alpha channel */
|
---|
173 | ii = (int) ( ((argb>>16) & 0xFF) * .30F +
|
---|
174 | ((argb>> 8) & 0xFF) * .59F +
|
---|
175 | ((argb ) & 0xFF) * .11F + 0.5f);
|
---|
176 |
|
---|
177 |
|
---|
178 | if (x == 0) qi = 0;
|
---|
179 | ii += errR[x] + qi;
|
---|
180 | qi = ii;
|
---|
181 | if (qi < 0) qi = 0; if (qi > 255) qi = 255; // clamp.
|
---|
182 | qi = (int) (qi * 0xfff/255.0f); qi >>= 8;
|
---|
183 |
|
---|
184 | t = qi;
|
---|
185 | t |= (int) ((argb>>24) & 0xF0);
|
---|
186 |
|
---|
187 |
|
---|
188 | // Now dequantize the input, and compute & distribute the errors.
|
---|
189 | qi = (qi << 4) | qi;
|
---|
190 | qi = ii - qi;
|
---|
191 |
|
---|
192 | // 3/8 (=0.375) to the EAST, 3/8 to the SOUTH, 1/4 (0.25) to the SOUTH-EAST.
|
---|
193 | errR[x] = ((x == 0) ? 0 : errR[x]) + ((int) (qi * 0.375f));
|
---|
194 | errR[x+1] = (int) (qi * 0.250f);
|
---|
195 | qi = (int) (qi * 0.375f); // Carried to the pixel on the right.
|
---|
196 |
|
---|
197 | return t & 0xFF;
|
---|
198 | }
|
---|
199 |
|
---|
200 |
|
---|
201 | static int
|
---|
202 | _txPixQuantize_ARGB8332 ( unsigned long argb, int x, int y, int w)
|
---|
203 | {
|
---|
204 | return (
|
---|
205 | ((argb>>16) & 0xE0) |
|
---|
206 | ((argb>>11) & 0x1C) |
|
---|
207 | ((argb>> 6) & 0x03) |
|
---|
208 | ((argb>>16) & 0xFF00) );
|
---|
209 | }
|
---|
210 |
|
---|
211 |
|
---|
212 | static int
|
---|
213 | _txPixQuantize_ARGB8332_D4x4( unsigned long argb, int x, int y, int w)
|
---|
214 | {
|
---|
215 | int d = dithmat[y&3][x&3];
|
---|
216 | int n, t;
|
---|
217 |
|
---|
218 | n = (int) (((argb >> 16) & 0xFF) * 0x70/255.0f + 0.5f) + d;
|
---|
219 | t = (n>>4)<<5;
|
---|
220 | n = (int) (((argb >> 8) & 0xFF) * 0x70/255.0f + 0.5f) + d;
|
---|
221 | t |= (n>>4)<<2;
|
---|
222 | n = (int) (((argb ) & 0xFF) * 0x30/255.0f + 0.5f) + d;
|
---|
223 | t |= (n>>4)<<0;
|
---|
224 | t |= ((argb >> 16) & 0xFF00);
|
---|
225 | return t & 0xFFFF;
|
---|
226 | }
|
---|
227 |
|
---|
228 | static int
|
---|
229 | _txPixQuantize_ARGB8332_DErr( unsigned long argb, int x, int y, int w)
|
---|
230 | {
|
---|
231 | int t;
|
---|
232 |
|
---|
233 | t = _txPixQuantize_RGB332_DErr(argb, x, y, w);
|
---|
234 | t |= ((argb >> 16) & 0xFF00);
|
---|
235 | return t & 0xFFFF;
|
---|
236 | }
|
---|
237 |
|
---|
238 | /* AYIQ8422 done elsewhere */
|
---|
239 |
|
---|
240 | static int
|
---|
241 | _txPixQuantize_RGB565( unsigned long argb, int x, int y, int w)
|
---|
242 | {
|
---|
243 | return (
|
---|
244 | ((argb >> 8) & 0xF800) |
|
---|
245 | ((argb >> 5) & 0x07E0) |
|
---|
246 | ((argb >> 3) & 0x001F) );
|
---|
247 | }
|
---|
248 |
|
---|
249 | static int
|
---|
250 | _txPixQuantize_RGB565_D4x4 ( unsigned long argb, int x, int y, int w)
|
---|
251 | {
|
---|
252 | int d = dithmat[y&3][x&3];
|
---|
253 | int n, t;
|
---|
254 |
|
---|
255 | n = (int) (((argb >> 16) & 0xFF) * 0x1F0/255.0f + 0.5f) + d;
|
---|
256 | t = (n>>4)<<11;
|
---|
257 | n = (int) (((argb >> 8) & 0xFF) * 0x3F0/255.0f + 0.5f) + d;
|
---|
258 | t |= (n>>4)<<5;
|
---|
259 | n = (int) (((argb ) & 0xFF) * 0x1F0/255.0f + 0.5f) + d;
|
---|
260 | t |= (n>>4)<<0;
|
---|
261 | return t & 0xFFFF;
|
---|
262 | }
|
---|
263 |
|
---|
264 |
|
---|
265 | static int
|
---|
266 | _txPixQuantize_RGB565_DErr ( unsigned long argb, int x, int y, int w)
|
---|
267 | {
|
---|
268 | static int qr, qg, qb; // quantized incoming values.
|
---|
269 | int ir, ig, ib; // incoming values.
|
---|
270 | int t;
|
---|
271 |
|
---|
272 | ir = (argb >> 16) & 0xFF; // incoming pixel values.
|
---|
273 | ig = (argb >> 8) & 0xFF;
|
---|
274 | ib = (argb ) & 0xFF;
|
---|
275 |
|
---|
276 | if (x == 0) qr = qg = qb = 0;
|
---|
277 |
|
---|
278 | ir += errR[x] + qr;
|
---|
279 | ig += errG[x] + qg;
|
---|
280 | ib += errB[x] + qb;
|
---|
281 |
|
---|
282 | qr = ir; // quantized pixel values.
|
---|
283 | qg = ig; // qR is error from pixel to left, errR is
|
---|
284 | qb = ib; // error from pixel to the top & top left.
|
---|
285 |
|
---|
286 | if (qr < 0) qr = 0; if (qr > 255) qr = 255; // clamp.
|
---|
287 | if (qg < 0) qg = 0; if (qg > 255) qg = 255;
|
---|
288 | if (qb < 0) qb = 0; if (qb > 255) qb = 255;
|
---|
289 |
|
---|
290 | // To RGB565.
|
---|
291 | qr = (int) (qr * 0x1FFF/255.0f); qr >>= 8;
|
---|
292 | qg = (int) (qg * 0x3FFF/255.0f); qg >>= 8;
|
---|
293 | qb = (int) (qb * 0x1FFF/255.0f); qb >>= 8;
|
---|
294 |
|
---|
295 | t = (qr << 11) | (qg << 5) | qb; // this is the value to be returned.
|
---|
296 |
|
---|
297 | // Now dequantize the input, and compute & distribute the errors.
|
---|
298 | qr = (qr << 3) | (qr >> 2);
|
---|
299 | qg = (qg << 2) | (qg >> 4);
|
---|
300 | qb = (qb << 3) | (qb >> 2);
|
---|
301 | qr = ir - qr;
|
---|
302 | qg = ig - qg;
|
---|
303 | qb = ib - qb;
|
---|
304 |
|
---|
305 | // 3/8 (=0.375) to the EAST, 3/8 to the SOUTH, 1/4 (0.25) to the SOUTH-EAST.
|
---|
306 | errR[x] = ((x == 0) ? 0 : errR[x]) + ((int) (qr * 0.375f));
|
---|
307 | errG[x] = ((x == 0) ? 0 : errG[x]) + ((int) (qg * 0.375f));
|
---|
308 | errB[x] = ((x == 0) ? 0 : errB[x]) + ((int) (qb * 0.375f));
|
---|
309 |
|
---|
310 | errR[x+1] = (int) (qr * 0.250f);
|
---|
311 | errG[x+1] = (int) (qg * 0.250f);
|
---|
312 | errB[x+1] = (int) (qb * 0.250f);
|
---|
313 |
|
---|
314 | qr = (int) (qr * 0.375f); // Carried to the pixel on the right.
|
---|
315 | qg = (int) (qg * 0.375f);
|
---|
316 | qb = (int) (qb * 0.375f);
|
---|
317 |
|
---|
318 | return t & 0xFFFF;
|
---|
319 | }
|
---|
320 |
|
---|
321 | static int
|
---|
322 | _txPixQuantize_ARGB1555( unsigned long argb, int x, int y, int w)
|
---|
323 | {
|
---|
324 | return (
|
---|
325 | ((argb >> 9) & 0x7C00) |
|
---|
326 | ((argb >> 6) & 0x03E0) |
|
---|
327 | ((argb >> 3) & 0x001F) |
|
---|
328 | ((argb >> 24) ? 0x8000 : 0) );
|
---|
329 | }
|
---|
330 |
|
---|
331 | static int
|
---|
332 | _txPixQuantize_ARGB1555_D4x4 ( unsigned long argb, int x, int y, int w)
|
---|
333 | {
|
---|
334 | int d = dithmat[y&3][x&3];
|
---|
335 | int n, t;
|
---|
336 |
|
---|
337 | n = (int) (((argb >> 16) & 0xFF) * 0x1F0/255.0f + 0.5f) + d;
|
---|
338 | t = (n>>4)<<10;
|
---|
339 | n = (int) (((argb >> 8) & 0xFF) * 0x1F0/255.0f + 0.5f) + d;
|
---|
340 | t |= (n>>4)<<5;
|
---|
341 | n = (int) (((argb ) & 0xFF) * 0x1F0/255.0f + 0.5f) + d;
|
---|
342 | t |= (n>>4)<<0;
|
---|
343 | t |= ((argb >> 24) ? 0x8000 : 0);
|
---|
344 | return t & 0xFFFF;
|
---|
345 | }
|
---|
346 |
|
---|
347 | static int
|
---|
348 | _txPixQuantize_ARGB1555_DErr ( unsigned long argb, int x, int y, int w)
|
---|
349 | {
|
---|
350 | static int qr, qg, qb; // quantized incoming values.
|
---|
351 | int ir, ig, ib; // incoming values.
|
---|
352 | int t;
|
---|
353 |
|
---|
354 | ir = (argb >> 16) & 0xFF; // incoming pixel values.
|
---|
355 | ig = (argb >> 8) & 0xFF;
|
---|
356 | ib = (argb ) & 0xFF;
|
---|
357 |
|
---|
358 | if (x == 0) qr = qg = qb = 0;
|
---|
359 |
|
---|
360 | ir += errR[x] + qr;
|
---|
361 | ig += errG[x] + qg;
|
---|
362 | ib += errB[x] + qb;
|
---|
363 |
|
---|
364 | qr = ir; // quantized pixel values.
|
---|
365 | qg = ig; // qR is error from pixel to left, errR is
|
---|
366 | qb = ib; // error from pixel to the top & top left.
|
---|
367 |
|
---|
368 | if (qr < 0) qr = 0; if (qr > 255) qr = 255; // clamp.
|
---|
369 | if (qg < 0) qg = 0; if (qg > 255) qg = 255;
|
---|
370 | if (qb < 0) qb = 0; if (qb > 255) qb = 255;
|
---|
371 |
|
---|
372 | // To RGB565.
|
---|
373 | qr = (int) (qr * 0x1FFF/255.0f); qr >>= 8;
|
---|
374 | qg = (int) (qg * 0x1FFF/255.0f); qg >>= 8;
|
---|
375 | qb = (int) (qb * 0x1FFF/255.0f); qb >>= 8;
|
---|
376 |
|
---|
377 | t = (qr << 10) | (qg << 5) | qb; // this is the value to be returned.
|
---|
378 | t |= ((argb >> 24) ? 0x8000 : 0);
|
---|
379 |
|
---|
380 | // Now dequantize the input, and compute & distribute the errors.
|
---|
381 | qr = (qr << 3) | (qr >> 2);
|
---|
382 | qg = (qg << 3) | (qg >> 2);
|
---|
383 | qb = (qb << 3) | (qb >> 2);
|
---|
384 | qr = ir - qr;
|
---|
385 | qg = ig - qg;
|
---|
386 | qb = ib - qb;
|
---|
387 |
|
---|
388 | // 3/8 (=0.375) to the EAST, 3/8 to the SOUTH, 1/4 (0.25) to the SOUTH-EAST.
|
---|
389 | errR[x] = ((x == 0) ? 0 : errR[x]) + ((int) (qr * 0.375f));
|
---|
390 | errG[x] = ((x == 0) ? 0 : errG[x]) + ((int) (qg * 0.375f));
|
---|
391 | errB[x] = ((x == 0) ? 0 : errB[x]) + ((int) (qb * 0.375f));
|
---|
392 |
|
---|
393 | errR[x+1] = (int) (qr * 0.250f);
|
---|
394 | errG[x+1] = (int) (qg * 0.250f);
|
---|
395 | errB[x+1] = (int) (qb * 0.250f);
|
---|
396 |
|
---|
397 | qr = (int) (qr * 0.375f); // Carried to the pixel on the right.
|
---|
398 | qg = (int) (qg * 0.375f);
|
---|
399 | qb = (int) (qb * 0.375f);
|
---|
400 |
|
---|
401 | return t & 0xFFFF;
|
---|
402 | }
|
---|
403 |
|
---|
404 | static int
|
---|
405 | _txPixQuantize_ARGB4444 (unsigned long argb, int x, int y, int w)
|
---|
406 | {
|
---|
407 | return (
|
---|
408 | ((argb >> 12) & 0x0F00) |
|
---|
409 | ((argb >> 8) & 0x00F0) |
|
---|
410 | ((argb >> 4) & 0x000F) |
|
---|
411 | ((argb >> 16) & 0xF000) );
|
---|
412 | }
|
---|
413 |
|
---|
414 | static int
|
---|
415 | _txPixQuantize_ARGB4444_D4x4 (unsigned long argb, int x, int y, int w)
|
---|
416 | {
|
---|
417 | int d = dithmat[y&3][x&3];
|
---|
418 | int n, t;
|
---|
419 |
|
---|
420 | n = (int) (((argb >> 16) & 0xFF) * 0xF0/255.0f + 0.5f) + d;
|
---|
421 | t = (n>>4)<<8;
|
---|
422 | n = (int) (((argb >> 8) & 0xFF) * 0xF0/255.0f + 0.5f) + d;
|
---|
423 | t |= (n>>4)<<4;
|
---|
424 | n = (int) (((argb ) & 0xFF) * 0xF0/255.0f + 0.5f) + d;
|
---|
425 | t |= (n>>4)<<0;
|
---|
426 | t |= (argb >> 16) & 0xF000;
|
---|
427 | return t & 0xFFFF;
|
---|
428 | }
|
---|
429 |
|
---|
430 | static int
|
---|
431 | _txPixQuantize_ARGB4444_DErr (unsigned long argb, int x, int y, int w)
|
---|
432 | {
|
---|
433 | static int qr, qg, qb; // quantized incoming values.
|
---|
434 | int ir, ig, ib; // incoming values.
|
---|
435 | int t;
|
---|
436 |
|
---|
437 | ir = (argb >> 16) & 0xFF; // incoming pixel values.
|
---|
438 | ig = (argb >> 8) & 0xFF;
|
---|
439 | ib = (argb ) & 0xFF;
|
---|
440 |
|
---|
441 | if (x == 0) qr = qg = qb = 0;
|
---|
442 |
|
---|
443 | ir += errR[x] + qr;
|
---|
444 | ig += errG[x] + qg;
|
---|
445 | ib += errB[x] + qb;
|
---|
446 |
|
---|
447 | qr = ir; // quantized pixel values.
|
---|
448 | qg = ig; // qR is error from pixel to left, errR is
|
---|
449 | qb = ib; // error from pixel to the top & top left.
|
---|
450 |
|
---|
451 | if (qr < 0) qr = 0; if (qr > 255) qr = 255; // clamp.
|
---|
452 | if (qg < 0) qg = 0; if (qg > 255) qg = 255;
|
---|
453 | if (qb < 0) qb = 0; if (qb > 255) qb = 255;
|
---|
454 |
|
---|
455 | // To RGB565.
|
---|
456 | qr = (int) (qr * 0xFFF/255.0f); qr >>= 8;
|
---|
457 | qg = (int) (qg * 0xFFF/255.0f); qg >>= 8;
|
---|
458 | qb = (int) (qb * 0xFFF/255.0f); qb >>= 8;
|
---|
459 |
|
---|
460 | t = (qr << 8) | (qg << 4) | qb; // this is the value to be returned.
|
---|
461 | t |= (argb >> 16) & 0xF000;
|
---|
462 |
|
---|
463 | // Now dequantize the input, and compute & distribute the errors.
|
---|
464 | qr = (qr << 4) | (qr >> 0);
|
---|
465 | qg = (qg << 4) | (qg >> 0);
|
---|
466 | qb = (qb << 4) | (qb >> 0);
|
---|
467 | qr = ir - qr;
|
---|
468 | qg = ig - qg;
|
---|
469 | qb = ib - qb;
|
---|
470 |
|
---|
471 | // 3/8 (=0.375) to the EAST, 3/8 to the SOUTH, 1/4 (0.25) to the SOUTH-EAST.
|
---|
472 | errR[x] = ((x == 0) ? 0 : errR[x]) + ((int) (qr * 0.375f));
|
---|
473 | errG[x] = ((x == 0) ? 0 : errG[x]) + ((int) (qg * 0.375f));
|
---|
474 | errB[x] = ((x == 0) ? 0 : errB[x]) + ((int) (qb * 0.375f));
|
---|
475 |
|
---|
476 | errR[x+1] = (int) (qr * 0.250f);
|
---|
477 | errG[x+1] = (int) (qg * 0.250f);
|
---|
478 | errB[x+1] = (int) (qb * 0.250f);
|
---|
479 |
|
---|
480 | qr = (int) (qr * 0.375f); // Carried to the pixel on the right.
|
---|
481 | qg = (int) (qg * 0.375f);
|
---|
482 | qb = (int) (qb * 0.375f);
|
---|
483 |
|
---|
484 | return t & 0xFFFF;
|
---|
485 | }
|
---|
486 |
|
---|
487 | static int
|
---|
488 | _txPixQuantize_AI88( unsigned long argb, int x, int y, int w)
|
---|
489 | {
|
---|
490 | return (
|
---|
491 | (((int) (((argb >>16) & 0xFF) * .30F +
|
---|
492 | ((argb >> 8) & 0xFF) * .59F +
|
---|
493 | ((argb ) & 0xFF) * .11F + 0.5f )) & 0xFF) |
|
---|
494 |
|
---|
495 | ((argb >>16) & 0xFF00) );
|
---|
496 | }
|
---|
497 |
|
---|
498 |
|
---|
499 | static void
|
---|
500 | _txImgQuantize(char *dst, char *src, int w, int h, FxU32 format, FxU32 dither)
|
---|
501 | {
|
---|
502 | int (*quantizer)(unsigned long argb, int x, int y, int w);
|
---|
503 | int x, y;
|
---|
504 |
|
---|
505 | dither &= TX_DITHER_MASK;
|
---|
506 |
|
---|
507 | if (dither == TX_DITHER_ERR) { // Error diffusion, floyd-steinberg
|
---|
508 | int i;
|
---|
509 |
|
---|
510 | // Clear error diffusion accumulators.
|
---|
511 | for (i=0; i<w; i++) errR[i] = errG[i] = errB[i] = 0;
|
---|
512 |
|
---|
513 | switch(format) {
|
---|
514 | case GR_TEXFMT_RGB_332: quantizer = _txPixQuantize_RGB332_DErr;
|
---|
515 | break;
|
---|
516 | case GR_TEXFMT_A_8: quantizer = _txPixQuantize_A8;
|
---|
517 | break;
|
---|
518 | case GR_TEXFMT_I_8: quantizer = _txPixQuantize_I8;
|
---|
519 | break;
|
---|
520 | case GR_TEXFMT_AI_44: quantizer = _txPixQuantize_AI44_DErr;
|
---|
521 | break;
|
---|
522 | case GR_TEXFMT_ARGB_8332: quantizer = _txPixQuantize_ARGB8332_DErr;
|
---|
523 | break;
|
---|
524 | case GR_TEXFMT_RGB_565: quantizer = _txPixQuantize_RGB565_DErr;
|
---|
525 | break;
|
---|
526 | case GR_TEXFMT_ARGB_1555: quantizer = _txPixQuantize_ARGB1555_DErr;
|
---|
527 | break;
|
---|
528 | case GR_TEXFMT_ARGB_4444: quantizer = _txPixQuantize_ARGB4444_DErr;
|
---|
529 | break;
|
---|
530 | case GR_TEXFMT_AI_88: quantizer = _txPixQuantize_AI88;
|
---|
531 | break;
|
---|
532 |
|
---|
533 | default: txPanic("Bad case in txQuantize()\n"); break;
|
---|
534 | }
|
---|
535 | }else if (dither == TX_DITHER_4x4) { // 4x4 ordered dithering.
|
---|
536 |
|
---|
537 | switch(format) {
|
---|
538 | case GR_TEXFMT_RGB_332: quantizer = _txPixQuantize_RGB332_D4x4;
|
---|
539 | break;
|
---|
540 | case GR_TEXFMT_A_8: quantizer = _txPixQuantize_A8;
|
---|
541 | break;
|
---|
542 | case GR_TEXFMT_I_8: quantizer = _txPixQuantize_I8;
|
---|
543 | break;
|
---|
544 | case GR_TEXFMT_AI_44: quantizer = _txPixQuantize_AI44_D4x4;
|
---|
545 | break;
|
---|
546 |
|
---|
547 | case GR_TEXFMT_ARGB_8332: quantizer = _txPixQuantize_ARGB8332_D4x4;
|
---|
548 | break;
|
---|
549 | case GR_TEXFMT_RGB_565: quantizer = _txPixQuantize_RGB565_D4x4;
|
---|
550 | break;
|
---|
551 | case GR_TEXFMT_ARGB_1555: quantizer = _txPixQuantize_ARGB1555_D4x4;
|
---|
552 | break;
|
---|
553 | case GR_TEXFMT_ARGB_4444: quantizer = _txPixQuantize_ARGB4444_D4x4;
|
---|
554 | break;
|
---|
555 | case GR_TEXFMT_AI_88: quantizer = _txPixQuantize_AI88;
|
---|
556 | break;
|
---|
557 |
|
---|
558 | default: txPanic("Bad case in txQuantize()\n");
|
---|
559 | break;
|
---|
560 | }
|
---|
561 | } else { // No dithering.
|
---|
562 |
|
---|
563 | switch(format) {
|
---|
564 | case GR_TEXFMT_RGB_332: quantizer = _txPixQuantize_RGB332;
|
---|
565 | break;
|
---|
566 | case GR_TEXFMT_A_8: quantizer = _txPixQuantize_A8;
|
---|
567 | break;
|
---|
568 | case GR_TEXFMT_I_8: quantizer = _txPixQuantize_I8;
|
---|
569 | break;
|
---|
570 | case GR_TEXFMT_AI_44: quantizer = _txPixQuantize_AI44;
|
---|
571 | break;
|
---|
572 |
|
---|
573 | case GR_TEXFMT_ARGB_8332: quantizer = _txPixQuantize_ARGB8332;
|
---|
574 | break;
|
---|
575 | case GR_TEXFMT_RGB_565: quantizer = _txPixQuantize_RGB565;
|
---|
576 | break;
|
---|
577 | case GR_TEXFMT_ARGB_1555: quantizer = _txPixQuantize_ARGB1555;
|
---|
578 | break;
|
---|
579 | case GR_TEXFMT_ARGB_4444: quantizer = _txPixQuantize_ARGB4444;
|
---|
580 | break;
|
---|
581 | case GR_TEXFMT_AI_88: quantizer = _txPixQuantize_AI88;
|
---|
582 | break;
|
---|
583 |
|
---|
584 | default: txPanic("Bad case in txQuantize()\n");
|
---|
585 | break;
|
---|
586 | }
|
---|
587 | }
|
---|
588 |
|
---|
589 | if (format < GR_TEXFMT_16BIT) {
|
---|
590 | // 8 bit dst
|
---|
591 | for (y=0; y<h; y++) {
|
---|
592 | for (x=0; x<w; x++) {
|
---|
593 | *dst++ = (*quantizer)(*(unsigned long *)src, x, y, w);
|
---|
594 | src += 4;
|
---|
595 | }
|
---|
596 | }
|
---|
597 | } else {
|
---|
598 | // 16 bit dst.
|
---|
599 | unsigned short *dst16 = (unsigned short *) dst;
|
---|
600 |
|
---|
601 | for (y=0; y<h; y++) {
|
---|
602 | for (x=0; x<w; x++) {
|
---|
603 | *dst16++ = (*quantizer)(*(unsigned long *)src, x, y, w);
|
---|
604 | src += 4;
|
---|
605 | }
|
---|
606 | }
|
---|
607 | }
|
---|
608 | }
|
---|
609 |
|
---|
610 | /*
|
---|
611 | * Reduce an ARGB8888 image to 16bits or 8bits/pixel, possibly dithering
|
---|
612 | * the resulting image using either ordered 4x4 or error-diffusion dithering.
|
---|
613 | *
|
---|
614 | * For the special cases of YIQ image, you also get the choice of 2 different
|
---|
615 | * quality levels in each of the compression cases.
|
---|
616 | */
|
---|
617 | void
|
---|
618 | txMipQuantize(TxMip *pxMip, TxMip *txMip, int format, FxU32 dither, FxU32 compression)
|
---|
619 | {
|
---|
620 | int i, w, h;
|
---|
621 |
|
---|
622 | if( txVerbose )
|
---|
623 | {
|
---|
624 | printf("Quantizing: (to %s)", Format_Name[format]);
|
---|
625 | }
|
---|
626 | pxMip->format = format;
|
---|
627 | pxMip->width = txMip->width;
|
---|
628 | pxMip->height = txMip->height;
|
---|
629 |
|
---|
630 | switch(format) {
|
---|
631 | // Special cases.
|
---|
632 | case GR_TEXFMT_YIQ_422:
|
---|
633 | case GR_TEXFMT_AYIQ_8422:
|
---|
634 | if( txVerbose )
|
---|
635 | printf(".\n");
|
---|
636 | txMipNcc(pxMip, txMip, format, dither, compression);
|
---|
637 | return;
|
---|
638 |
|
---|
639 | case GR_TEXFMT_ARGB_8888:
|
---|
640 | // Copy source to destination, and be done.
|
---|
641 | if( txVerbose )
|
---|
642 | printf(".\n");
|
---|
643 | memcpy(pxMip->data[0], txMip->data[0], txMip->size);
|
---|
644 | return;
|
---|
645 |
|
---|
646 | case GR_TEXFMT_P_8:
|
---|
647 | case GR_TEXFMT_AP_88:
|
---|
648 | if( txVerbose )
|
---|
649 | printf(".\n");
|
---|
650 | txMipPal256(pxMip, txMip, format, dither, compression);
|
---|
651 | return;
|
---|
652 |
|
---|
653 | // Normal cases
|
---|
654 | case GR_TEXFMT_A_8:
|
---|
655 | case GR_TEXFMT_I_8:
|
---|
656 | case GR_TEXFMT_AI_44:
|
---|
657 | case GR_TEXFMT_RGB_332:
|
---|
658 | case GR_TEXFMT_RGB_565:
|
---|
659 | case GR_TEXFMT_ARGB_8332:
|
---|
660 | case GR_TEXFMT_ARGB_1555:
|
---|
661 | case GR_TEXFMT_ARGB_4444:
|
---|
662 | case GR_TEXFMT_AI_88:
|
---|
663 | break;
|
---|
664 |
|
---|
665 | // Bad cases
|
---|
666 | default:
|
---|
667 | txPanic("Bad data format in Quantize\n");
|
---|
668 | return;
|
---|
669 |
|
---|
670 | }
|
---|
671 |
|
---|
672 | // We deal with rest of them here one mipmap level at a time.
|
---|
673 |
|
---|
674 | w = txMip->width;
|
---|
675 | h = txMip->height;
|
---|
676 |
|
---|
677 | for (i=0; i< pxMip->depth; i++) {
|
---|
678 | if( txVerbose )
|
---|
679 | printf(" %dx%d", w, h);
|
---|
680 |
|
---|
681 | _txImgQuantize(pxMip->data[i], txMip->data[i], w, h, format, dither);
|
---|
682 | w >>= 1; if (w == 0) w = 1;
|
---|
683 | h >>= 1; if (h == 0) h = 1;
|
---|
684 | }
|
---|
685 | if( txVerbose )
|
---|
686 | printf(".\n");
|
---|
687 | }
|
---|