source: trunk/src/testing/app/ishare/FastDXT/dxt.cpp @ 4

Revision 4, 19.0 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1/******************************************************************************
2 * SAGE - Scalable Adaptive Graphics Environment
3 *
4 * Copyright (C) 2004 Electronic Visualization Laboratory,
5 * University of Illinois at Chicago
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above
15 *    copyright notice, this list of conditions and the following disclaimer
16 *    in the documentation and/or other materials provided with the distribution.
17 *  * Neither the name of the University of Illinois at Chicago nor
18 *    the names of its contributors may be used to endorse or promote
19 *    products derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Direct questions, comments etc about SAGE to http://www.evl.uic.edu/cavern/forum/
34 *
35 *****************************************************************************/
36
37// From:
38//    Real-Time DXT Compression
39//    May 20th 2006 J.M.P. van Waveren
40//    (c) 2006, Id Software, Inc.
41
42#include "dxt.h"
43#include "util.h"
44
45
46#define DXT_INTR 1
47
48void ExtractBlock( const byte *inPtr, int width, byte *colorBlock );
49void ExtractBlock_Intrinsics( const byte *inPtr, int width, byte *colorBlock );
50
51void GetMinMaxColors( const byte *colorBlock, byte *minColor, byte *maxColor );
52void GetMinMaxColorsByLuminance( const byte *colorBlock, byte *minColor, byte *maxColor );
53void GetMinMaxColorsByBBox( const byte *colorBlock, byte *minColor, byte *maxColor );
54void GetMinMaxColors_Intrinsics( const byte *colorBlock, byte *minColor, byte *maxColor );
55
56// for DXT5
57void GetMinMaxColorsAlpha(  byte *colorBlock, byte *minColor, byte *maxColor );
58
59
60word ColorTo565( const byte *color );
61
62void EmitByte( byte b, byte*& );
63void EmitWord( word s, byte*& );
64void EmitDoubleWord( dword i, byte*& );
65
66void EmitColorIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor, byte *&outData );
67void EmitColorIndicesFast( const byte *colorBlock, const byte *minColor, const byte *maxColor, byte *&outData );
68void EmitColorIndices_Intrinsics( const byte *colorBlock, const byte *minColor, const byte *maxColor, byte *&outData);
69
70// Emit indices for DXT5
71void EmitAlphaIndices( const byte *colorBlock, const byte minAlpha, const byte maxAlpha, byte *&outData);
72void EmitAlphaIndicesFast( const byte *colorBlock, const byte minAlpha, const byte maxAlpha, byte *&outData);
73void EmitAlphaIndices_Intrinsics( const byte *colorBlock, const byte minAlpha, const byte maxAlpha, byte *&outData);
74
75
76void CompressImageDXT1( const byte *inBuf, byte *outBuf,
77                        int width, int height, int &outputBytes )
78{
79  ALIGN16( byte *outData );
80  ALIGN16( byte block[64] );
81  ALIGN16( byte minColor[4] );
82  ALIGN16( byte maxColor[4] );
83
84  outData = outBuf;
85  for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
86    for ( int i = 0; i < width; i += 4 ) {
87
88#if defined(DXT_INTR)
89        ExtractBlock_Intrinsics( inBuf + i * 4, width, block );
90#else
91        ExtractBlock( inBuf + i * 4, width, block );
92#endif
93
94#if defined(DXT_INTR)
95      GetMinMaxColors_Intrinsics( block, minColor, maxColor );
96#else
97      GetMinMaxColorsByBBox( block, minColor, maxColor );
98#endif
99
100      EmitWord( ColorTo565( maxColor ), outData );
101      EmitWord( ColorTo565( minColor ), outData );
102
103#if defined(DXT_INTR)
104      EmitColorIndices_Intrinsics( block, minColor, maxColor, outData );
105#else
106      EmitColorIndicesFast( block, minColor, maxColor, outData );
107#endif
108    }
109  }
110  outputBytes = (int) ( outData - outBuf );
111}
112
113void RGBAtoYCoCg(const byte *inBuf, byte *outBuf, int width, int height)
114{
115  for ( int j = 0; j < width*height; j++ ) {
116    byte R = inBuf[j*4+0];
117    byte G = inBuf[j*4+1];
118    byte B = inBuf[j*4+2];
119    byte A = inBuf[j*4+3];
120    int Co = R-B;
121    int t = B + (Co/2);
122    int Cg = G-t;
123    int Y = t + (Cg/2);
124
125    Co += 128;
126    Cg += 96;
127
128//     if (Co < 0 || Co > 255)
129//       fprintf(stderr, "Co: %d\n", Co);
130//     if (Cg < 0 || Cg > 255)
131//       fprintf(stderr, "Cg: %d\n", Cg);
132//     if ( Y < 0 ||  Y > 255)
133//       fprintf(stderr, "Y: %d\n", Y);
134
135    if (Co < 0)   Co=0;
136    if (Co > 255) Co=255;
137    if (Cg < 0)   Cg=0;
138    if (Cg > 255) Cg=255;
139
140    outBuf[j*4+0] = Co;
141    outBuf[j*4+1] = Cg;
142    outBuf[j*4+2] = 0;
143    outBuf[j*4+3] = Y;
144  }
145}
146
147void CompressImageDXT5YCoCg( const byte *inBuf, byte *outBuf, int width, int height,
148                             int &outputBytes )
149{
150  byte *tmpBuf;
151  tmpBuf = (byte*)memalign(16, width*height*4);
152  memset(tmpBuf, 0, width*height*4);
153  RGBAtoYCoCg(inBuf, tmpBuf, width, height);
154  CompressImageDXT5(tmpBuf, outBuf, width, height, outputBytes);
155  memfree(tmpBuf);
156}
157
158
159void CompressImageDXT5( const byte *inBuf, byte *outBuf, int width, int height,
160                        int &outputBytes )
161{
162  ALIGN16( byte *outData );
163
164  ALIGN16( byte block[64] );
165  ALIGN16( byte minColor[4] );
166  ALIGN16( byte maxColor[4] );
167
168  outData = outBuf;
169  for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
170    for ( int i = 0; i < width; i += 4 ) {
171
172#if defined(DXT_INTR)
173      ExtractBlock_Intrinsics( inBuf + i * 4, width, block );
174#else
175      ExtractBlock( inBuf + i * 4, width, block );
176#endif
177
178#if defined(DXT_INTR)
179      GetMinMaxColors_Intrinsics( block, minColor, maxColor );
180#else
181      GetMinMaxColorsAlpha( block, minColor, maxColor );
182#endif
183
184      EmitByte( maxColor[3], outData);
185      EmitByte( minColor[3], outData);
186
187#if defined(DXT_INTR)
188          // Not Yet Implemented
189      //EmitAlphaIndices_Intrinsics( block, minColor[3], maxColor[3], outData );
190
191      EmitAlphaIndicesFast( block, minColor[3], maxColor[3], outData );
192#else
193      EmitAlphaIndicesFast( block, minColor[3], maxColor[3], outData );
194#endif
195
196      EmitWord( ColorTo565( maxColor ), outData);
197      EmitWord( ColorTo565( minColor ), outData);
198
199#if defined(DXT_INTR)
200      EmitColorIndices_Intrinsics( block, minColor, maxColor, outData );
201#else
202      EmitColorIndicesFast( block, minColor, maxColor, outData );
203#endif
204    }
205  }
206  outputBytes = int( outData - outBuf );
207}
208
209
210
211
212void ExtractBlock( const byte *inPtr, int width, byte *colorBlock )
213{
214  for ( int j = 0; j < 4; j++ ) {
215    memcpy( &colorBlock[j*4*4], inPtr, 4*4 );
216    inPtr += width * 4;
217  }
218}
219
220word ColorTo565( const byte *color )
221{
222  return ( ( color[ 0 ] >> 3 ) << 11 ) |
223         ( ( color[ 1 ] >> 2 ) <<  5 ) |
224         (   color[ 2 ] >> 3 );
225}
226
227void EmitByte( byte b, byte *&outData)
228{
229  outData[0] = b;
230  outData += 1;
231}
232
233void EmitWord( word s, byte *&outData)
234{
235  outData[0] = ( s >> 0 ) & 255;
236  outData[1] = ( s >> 8 ) & 255;
237  outData += 2;
238}
239
240void EmitDoubleWord( dword i, byte *&outData)
241{
242  outData[0] = ( i >> 0 ) & 255;
243  outData[1] = ( i >> 8 ) & 255;
244  outData[2] = ( i >> 16 ) & 255;
245  outData[3] = ( i >> 24 ) & 255;
246  outData += 4;
247}
248
249
250int ColorDistance( const byte *c1, const byte *c2 )
251{
252  return ( ( c1[0] - c2[0] ) * ( c1[0] - c2[0] ) ) +
253    ( ( c1[1] - c2[1] ) * ( c1[1] - c2[1] ) ) +
254    ( ( c1[2] - c2[2] ) * ( c1[2] - c2[2] ) );
255}
256
257void SwapColors( byte *c1, byte *c2 )
258{
259  byte tm[3];
260  memcpy( tm, c1, 3 );
261  memcpy( c1, c2, 3 );
262  memcpy( c2, tm, 3 );
263}
264
265void GetMinMaxColors( const byte *colorBlock, byte *minColor, byte *maxColor )
266{
267  int maxDistance = -1;
268  for ( int i = 0; i < 64 - 4; i += 4 ) {
269    for ( int j = i + 4; j < 64; j += 4 ) {
270      int distance = ColorDistance( &colorBlock[i], &colorBlock[j] );
271      if ( distance > maxDistance ) {
272        maxDistance = distance;
273        memcpy( minColor, colorBlock+i, 3 );
274        memcpy( maxColor, colorBlock+j, 3 );
275      }
276    }
277  }
278  if ( ColorTo565( maxColor ) < ColorTo565( minColor ) ) {
279    SwapColors( minColor, maxColor );
280  }
281}
282
283
284int ColorLuminance( const byte *color )
285{
286  return ( color[0] + color[1] * 2 + color[2] );
287}
288
289
290void GetMinMaxColorsByLuminance( const byte *colorBlock, byte *minColor, byte *maxColor )
291{
292  int maxLuminance = -1, minLuminance = MAX_INT;
293  for (int i = 0; i < 16; i++ ) {
294    int luminance = ColorLuminance( colorBlock+i*4 );
295    if ( luminance > maxLuminance ) {
296      maxLuminance = luminance;
297      memcpy( maxColor, colorBlock+i*4, 3 );
298    }
299    if ( luminance < minLuminance ) {
300      minLuminance = luminance;
301      memcpy( minColor, colorBlock+i*4, 3 );
302    }
303  }
304  if ( ColorTo565( maxColor ) < ColorTo565( minColor ) ) {
305    SwapColors( minColor, maxColor );
306  }
307}
308
309void GetMinMaxColorsByBBox( const byte *colorBlock, byte *minColor, byte *maxColor )
310{
311  int i;
312  byte inset[3];
313  minColor[0] = minColor[1] = minColor[2] = 255;
314  maxColor[0] = maxColor[1] = maxColor[2] = 0;
315  for ( i = 0; i < 16; i++ ) {
316    if ( colorBlock[i*4+0] < minColor[0] ) { minColor[0] = colorBlock[i*4+0]; }
317    if ( colorBlock[i*4+1] < minColor[1] ) { minColor[1] = colorBlock[i*4+1]; }
318    if ( colorBlock[i*4+2] < minColor[2] ) { minColor[2] = colorBlock[i*4+2]; }
319    if ( colorBlock[i*4+0] > maxColor[0] ) { maxColor[0] = colorBlock[i*4+0]; }
320    if ( colorBlock[i*4+1] > maxColor[1] ) { maxColor[1] = colorBlock[i*4+1]; }
321    if ( colorBlock[i*4+2] > maxColor[2] ) { maxColor[2] = colorBlock[i*4+2]; }
322  }
323  inset[0] = ( maxColor[0] - minColor[0] ) >> INSET_SHIFT;
324  inset[1] = ( maxColor[1] - minColor[1] ) >> INSET_SHIFT;
325  inset[2] = ( maxColor[2] - minColor[2] ) >> INSET_SHIFT;
326  minColor[0] = ( minColor[0] + inset[0] <= 255 ) ? minColor[0] + inset[0] : 255;
327  minColor[1] = ( minColor[1] + inset[1] <= 255 ) ? minColor[1] + inset[1] : 255;
328  minColor[2] = ( minColor[2] + inset[2] <= 255 ) ? minColor[2] + inset[2] : 255;
329  maxColor[0] = ( maxColor[0] >= inset[0] ) ? maxColor[0] - inset[0] : 0;
330  maxColor[1] = ( maxColor[1] >= inset[1] ) ? maxColor[1] - inset[1] : 0;
331  maxColor[2] = ( maxColor[2] >= inset[2] ) ? maxColor[2] - inset[2] : 0;
332}
333
334
335//
336// GetMinMaxColorsAlpha for DXT5
337//
338void GetMinMaxColorsAlpha(  byte *colorBlock, byte *minColor, byte *maxColor )
339{
340  int i;
341  byte inset[4];
342  byte y,cg, co, r, g, b;
343
344  minColor[0] = minColor[1] = minColor[2] = minColor[3] = 255;
345  maxColor[0] = maxColor[1] = maxColor[2] = maxColor[3] = 0;
346
347  for ( i = 0; i < 16; i++ ) {
348    r = colorBlock[i*4+0];
349    g = colorBlock[i*4+1];
350    b = colorBlock[i*4+2];
351    y  = (g>>1) + ((r+b)>>2);
352    cg = g - ((r+b)>>1);
353    co = r - b;
354
355    colorBlock[i*4+0] = co;
356    colorBlock[i*4+1] = cg;
357    colorBlock[i*4+2] = 0;
358    colorBlock[i*4+3] = y;
359
360    if ( colorBlock[i*4+0] < minColor[0] ) { minColor[0] = colorBlock[i*4+0]; }
361    if ( colorBlock[i*4+1] < minColor[1] ) { minColor[1] = colorBlock[i*4+1]; }
362    if ( colorBlock[i*4+2] < minColor[2] ) { minColor[2] = colorBlock[i*4+2]; }
363    if ( colorBlock[i*4+3] < minColor[3] ) { minColor[3] = colorBlock[i*4+3]; }
364    if ( colorBlock[i*4+0] > maxColor[0] ) { maxColor[0] = colorBlock[i*4+0]; }
365    if ( colorBlock[i*4+1] > maxColor[1] ) { maxColor[1] = colorBlock[i*4+1]; }
366    if ( colorBlock[i*4+2] > maxColor[2] ) { maxColor[2] = colorBlock[i*4+2]; }
367    if ( colorBlock[i*4+3] > maxColor[3] ) { maxColor[3] = colorBlock[i*4+3]; }
368  }
369
370  inset[0] = ( maxColor[0] - minColor[0] ) >> INSET_SHIFT;
371  inset[1] = ( maxColor[1] - minColor[1] ) >> INSET_SHIFT;
372  inset[2] = ( maxColor[2] - minColor[2] ) >> INSET_SHIFT;
373  inset[3] = ( maxColor[3] - minColor[3] ) >> INSET_SHIFT;
374
375  minColor[0] = ( minColor[0] + inset[0] <= 255 ) ? minColor[0] + inset[0] : 255;
376  minColor[1] = ( minColor[1] + inset[1] <= 255 ) ? minColor[1] + inset[1] : 255;
377  minColor[2] = ( minColor[2] + inset[2] <= 255 ) ? minColor[2] + inset[2] : 255;
378  minColor[3] = ( minColor[3] + inset[3] <= 255 ) ? minColor[3] + inset[3] : 255;
379
380  maxColor[0] = ( maxColor[0] >= inset[0] ) ? maxColor[0] - inset[0] : 0;
381  maxColor[1] = ( maxColor[1] >= inset[1] ) ? maxColor[1] - inset[1] : 0;
382  maxColor[2] = ( maxColor[2] >= inset[2] ) ? maxColor[2] - inset[2] : 0;
383  maxColor[3] = ( maxColor[3] >= inset[3] ) ? maxColor[3] - inset[3] : 0;
384}
385
386
387void EmitColorIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor, byte *&outData )
388{
389  byte colors[4][4];
390  unsigned int indices[16];
391
392  colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
393  colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
394  colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 5 );
395
396  colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
397  colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
398  colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 5 );
399
400  colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
401  colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
402  colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
403
404  colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
405  colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
406  colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
407
408  for ( int i = 0; i < 16; i++ ) {
409    unsigned int minDistance = MAX_INT;
410    for ( int j = 0; j < 4; j++ ) {
411      unsigned int dist = ColorDistance( &colorBlock[i*4], &colors[j][0] );
412      if ( dist < minDistance ) {
413        minDistance = dist;
414        indices[i] = j;
415      }
416    }
417  }
418  dword result = 0;
419  for ( int i = 0; i < 16; i++ ) {
420    result |= ( indices[i] << (unsigned int)( i << 1 ) );
421  }
422  EmitDoubleWord( result, outData );
423}
424
425
426void EmitColorIndicesFast( const byte *colorBlock, const byte *minColor, const byte *maxColor, byte *&outData )
427{
428  word colors[4][4];
429  dword result = 0;
430
431  colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
432  colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
433  colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 5 );
434  colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
435  colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
436  colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 5 );
437  colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
438  colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
439  colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
440  colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
441  colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
442  colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
443
444  for ( int i = 15; i >= 0; i-- ) {
445    int c0 = colorBlock[i*4+0];
446    int c1 = colorBlock[i*4+1];
447    int c2 = colorBlock[i*4+2];
448    int d0 = abs( colors[0][0] - c0 ) + abs( colors[0][1] - c1 ) + abs( colors[0][2] - c2 );
449    int d1 = abs( colors[1][0] - c0 ) + abs( colors[1][1] - c1 ) + abs( colors[1][2] - c2 );
450    int d2 = abs( colors[2][0] - c0 ) + abs( colors[2][1] - c1 ) + abs( colors[2][2] - c2 );
451    int d3 = abs( colors[3][0] - c0 ) + abs( colors[3][1] - c1 ) + abs( colors[3][2] - c2 );
452
453    int b0 = d0 > d3;
454    int b1 = d1 > d2;
455    int b2 = d0 > d2;
456    int b3 = d1 > d3;
457    int b4 = d2 > d3;
458
459    int x0 = b1 & b2;
460    int x1 = b0 & b3;
461    int x2 = b0 & b4;
462    result |= ( x2 | ( ( x0 | x1 ) << 1 ) ) << ( i << 1 );
463  }
464  EmitDoubleWord( result, outData );
465}
466
467
468//
469// Emit indices for DXT5
470//
471void EmitAlphaIndices( const byte *colorBlock, const byte minAlpha, const byte maxAlpha, byte *&outData )
472{
473  byte indices[16];
474  byte alphas[8];
475
476  alphas[0] = maxAlpha;
477  alphas[1] = minAlpha;
478  alphas[2] = ( 6 * maxAlpha + 1 * minAlpha ) / 7;
479  alphas[3] = ( 5 * maxAlpha + 2 * minAlpha ) / 7;
480  alphas[4] = ( 4 * maxAlpha + 3 * minAlpha ) / 7;
481  alphas[5] = ( 3 * maxAlpha + 4 * minAlpha ) / 7;
482  alphas[6] = ( 2 * maxAlpha + 5 * minAlpha ) / 7;
483  alphas[7] = ( 1 * maxAlpha + 6 * minAlpha ) / 7;
484
485  colorBlock += 3;
486
487  for ( int i = 0; i < 16; i++ ) {
488    int minDistance = MAX_INT;
489    byte a = colorBlock[i*4];
490    for ( int j = 0; j < 8; j++ ) {
491      int dist = abs( a - alphas[j] );
492      if ( dist < minDistance ) {
493        minDistance = dist; indices[i] = j;
494      }
495    }
496  }
497
498  EmitByte( (indices[ 0] >> 0) | (indices[ 1] << 3) | (indices[ 2] << 6) , outData);
499  EmitByte( (indices[ 2] >> 2) | (indices[ 3] << 1) | (indices[ 4] << 4) | (indices[ 5] << 7) , outData);
500  EmitByte( (indices[ 5] >> 1) | (indices[ 6] << 2) | (indices[ 7] << 5) , outData);
501  EmitByte( (indices[ 8] >> 0) | (indices[ 9] << 3) | (indices[10] << 6) , outData);
502  EmitByte( (indices[10] >> 2) | (indices[11] << 1) | (indices[12] << 4) | (indices[13] << 7) , outData);
503  EmitByte( (indices[13] >> 1) | (indices[14] << 2) | (indices[15] << 5) , outData);
504}
505
506
507void EmitAlphaIndicesFast( const byte *colorBlock, const byte minAlpha, const byte maxAlpha, byte *&outData )
508{
509  //assert( maxAlpha > minAlpha );
510
511  byte indices[16];
512  byte mid = ( maxAlpha - minAlpha ) / ( 2 * 7 );
513  byte ab1 = minAlpha + mid;
514  byte ab2 = ( 6 * maxAlpha + 1 * minAlpha ) / 7 + mid;
515  byte ab3 = ( 5 * maxAlpha + 2 * minAlpha ) / 7 + mid;
516  byte ab4 = ( 4 * maxAlpha + 3 * minAlpha ) / 7 + mid;
517  byte ab5 = ( 3 * maxAlpha + 4 * minAlpha ) / 7 + mid;
518  byte ab6 = ( 2 * maxAlpha + 5 * minAlpha ) / 7 + mid;
519  byte ab7 = ( 1 * maxAlpha + 6 * minAlpha ) / 7 + mid;
520
521  colorBlock += 3;
522
523  for ( int i = 0; i < 16; i++ ) {
524
525    byte a = colorBlock[i*4];
526
527    int b1 = ( a <= ab1 );
528    int b2 = ( a <= ab2 );
529    int b3 = ( a <= ab3 );
530    int b4 = ( a <= ab4 );
531    int b5 = ( a <= ab5 );
532    int b6 = ( a <= ab6 );
533    int b7 = ( a <= ab7 );
534
535    int index = ( b1 + b2 + b3 + b4 + b5 + b6 + b7 + 1 ) & 7;
536
537    indices[i] = index ^ ( 2 > index );
538  }
539
540  EmitByte( (indices[ 0] >> 0) | (indices[ 1] << 3) | (indices[ 2] << 6) , outData);
541  EmitByte( (indices[ 2] >> 2) | (indices[ 3] << 1) | (indices[ 4] << 4) | (indices[ 5] << 7) , outData);
542  EmitByte( (indices[ 5] >> 1) | (indices[ 6] << 2) | (indices[ 7] << 5) , outData);
543  EmitByte( (indices[ 8] >> 0) | (indices[ 9] << 3) | (indices[10] << 6) , outData);
544  EmitByte( (indices[10] >> 2) | (indices[11] << 1) | (indices[12] << 4) | (indices[13] << 7) , outData);
545  EmitByte( (indices[13] >> 1) | (indices[14] << 2) | (indices[15] << 5) , outData);
546}
547
548
549double ComputeError( const byte *original, const byte *dxt, int width, int height)
550{
551  // Compute RMS error
552  double error;
553  int s, d;
554
555  error = 0.0;
556
557  // dxt: pointer to data read back from the framebuffer. RGB data upside down.
558  for (int i=0; i<height; i++)
559    {
560      for (int j=0; j<width; j++)
561        {
562          s = original[4*(width*i+j)+0];
563          d = dxt[3*(width*(height-i-1)+j)+0];
564          error += (s-d) * (s-d);
565
566          s = original[4*(width*i+j)+1];
567          d = dxt[3*(width*(height-i-1)+j)+1];
568          error += (s-d) * (s-d);
569
570          s = original[4*(width*i+j)+2];
571          d = dxt[3*(width*(height-i-1)+j)+2];
572          error += (s-d) * (s-d);
573        }
574    }
575  error = sqrt( error / (double)( width*height ) );
576
577  return error;
578}
Note: See TracBrowser for help on using the repository browser.