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

Revision 4, 10.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
44byte *globalOutData;
45
46void ExtractBlock( const byte *inPtr, int width, byte *colorBlock );
47
48void GetMinMaxColors( const byte *colorBlock, byte *minColor, byte *maxColor );
49void GetMinMaxColorsByLuminance( const byte *colorBlock, byte *minColor, byte *maxColor );
50void GetMinMaxColorsByBBox( const byte *colorBlock, byte *minColor, byte *maxColor );
51
52word ColorTo565( const byte *color );
53void EmitByte( byte b );
54void EmitWord( word s );
55void EmitDoubleWord( dword i );
56
57void EmitColorIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor );
58void EmitColorIndicesFast( const byte *colorBlock, const byte *minColor, const byte *maxColor );
59
60
61void CompressImageDXT1( const byte *inBuf, byte *outBuf,
62                        int width, int height, int &outputBytes )
63{
64#if 0
65  ALIGN16( byte block[64] );
66  ALIGN16( byte minColor[4] );
67  ALIGN16( byte maxColor[4] );
68#else
69  byte block[64];
70  byte minColor[4];
71  byte maxColor[4];
72#endif
73
74  globalOutData = outBuf;
75  for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
76    for ( int i = 0; i < width; i += 4 ) {
77      ExtractBlock( inBuf + i * 4, width, block );
78      GetMinMaxColorsByBBox( block, minColor, maxColor );
79      EmitWord( ColorTo565( maxColor ) );
80      EmitWord( ColorTo565( minColor ) );
81      EmitColorIndicesFast( block, minColor, maxColor );
82    }
83  }
84  outputBytes = globalOutData - outBuf;
85}
86
87
88void ExtractBlock( const byte *inPtr, int width, byte *colorBlock )
89{
90  for ( int j = 0; j < 4; j++ ) {
91    memcpy( &colorBlock[j*4*4], inPtr, 4*4 );
92    inPtr += width * 4;
93  }
94}
95
96word ColorTo565( const byte *color )
97{
98  return ( ( color[ 0 ] >> 3 ) << 11 ) |
99         ( ( color[ 1 ] >> 2 ) <<  5 ) |
100         (   color[ 2 ] >> 3 );
101}
102
103void EmitByte( byte b )
104{
105  globalOutData[0] = b;
106  globalOutData += 1;
107}
108
109void EmitWord( word s )
110{
111  globalOutData[0] = ( s >> 0 ) & 255;
112  globalOutData[1] = ( s >> 8 ) & 255;
113  globalOutData += 2;
114}
115
116void EmitDoubleWord( dword i )
117{
118  globalOutData[0] = ( i >> 0 ) & 255;
119  globalOutData[1] = ( i >> 8 ) & 255;
120  globalOutData[2] = ( i >> 16 ) & 255;
121  globalOutData[3] = ( i >> 24 ) & 255;
122  globalOutData += 4;
123}
124
125
126int ColorDistance( const byte *c1, const byte *c2 )
127{
128  return ( ( c1[0] - c2[0] ) * ( c1[0] - c2[0] ) ) +
129    ( ( c1[1] - c2[1] ) * ( c1[1] - c2[1] ) ) +
130    ( ( c1[2] - c2[2] ) * ( c1[2] - c2[2] ) );
131}
132
133void SwapColors( byte *c1, byte *c2 )
134{
135  byte tm[3];
136  memcpy( tm, c1, 3 );
137  memcpy( c1, c2, 3 );
138  memcpy( c2, tm, 3 );
139}
140
141void GetMinMaxColors( const byte *colorBlock, byte *minColor, byte *maxColor )
142{
143  int maxDistance = -1;
144  for ( int i = 0; i < 64 - 4; i += 4 ) {
145    for ( int j = i + 4; j < 64; j += 4 ) {
146      int distance = ColorDistance( &colorBlock[i], &colorBlock[j] );
147      if ( distance > maxDistance ) {
148        maxDistance = distance;
149        memcpy( minColor, colorBlock+i, 3 );
150        memcpy( maxColor, colorBlock+j, 3 );
151      }
152    }
153  }
154  if ( ColorTo565( maxColor ) < ColorTo565( minColor ) ) {
155    SwapColors( minColor, maxColor );
156  }
157}
158
159
160int ColorLuminance( const byte *color )
161{
162  return ( color[0] + color[1] * 2 + color[2] );
163}
164
165
166void GetMinMaxColorsByLuminance( const byte *colorBlock, byte *minColor, byte *maxColor )
167{
168  int maxLuminance = -1, minLuminance = MAX_INT;
169  for (int i = 0; i < 16; i++ ) {
170    int luminance = ColorLuminance( colorBlock+i*4 );
171    if ( luminance > maxLuminance ) {
172      maxLuminance = luminance;
173      memcpy( maxColor, colorBlock+i*4, 3 );
174    }
175    if ( luminance < minLuminance ) {
176      minLuminance = luminance;
177      memcpy( minColor, colorBlock+i*4, 3 );
178    }
179  }
180  if ( ColorTo565( maxColor ) < ColorTo565( minColor ) ) {
181    SwapColors( minColor, maxColor );
182  }
183}
184
185void GetMinMaxColorsByBBox( const byte *colorBlock, byte *minColor, byte *maxColor )
186{
187  int i;
188  byte inset[3];
189  minColor[0] = minColor[1] = minColor[2] = 255;
190  maxColor[0] = maxColor[1] = maxColor[2] = 0;
191  for ( i = 0; i < 16; i++ ) {
192    if ( colorBlock[i*4+0] < minColor[0] ) { minColor[0] = colorBlock[i*4+0]; }
193    if ( colorBlock[i*4+1] < minColor[1] ) { minColor[1] = colorBlock[i*4+1]; }
194    if ( colorBlock[i*4+2] < minColor[2] ) { minColor[2] = colorBlock[i*4+2]; }
195    if ( colorBlock[i*4+0] > maxColor[0] ) { maxColor[0] = colorBlock[i*4+0]; }
196    if ( colorBlock[i*4+1] > maxColor[1] ) { maxColor[1] = colorBlock[i*4+1]; }
197    if ( colorBlock[i*4+2] > maxColor[2] ) { maxColor[2] = colorBlock[i*4+2]; }
198  }
199  inset[0] = ( maxColor[0] - minColor[0] ) >> INSET_SHIFT;
200  inset[1] = ( maxColor[1] - minColor[1] ) >> INSET_SHIFT;
201  inset[2] = ( maxColor[2] - minColor[2] ) >> INSET_SHIFT;
202  minColor[0] = ( minColor[0] + inset[0] <= 255 ) ? minColor[0] + inset[0] : 255;
203  minColor[1] = ( minColor[1] + inset[1] <= 255 ) ? minColor[1] + inset[1] : 255;
204  minColor[2] = ( minColor[2] + inset[2] <= 255 ) ? minColor[2] + inset[2] : 255;
205  maxColor[0] = ( maxColor[0] >= inset[0] ) ? maxColor[0] - inset[0] : 0;
206  maxColor[1] = ( maxColor[1] >= inset[1] ) ? maxColor[1] - inset[1] : 0;
207  maxColor[2] = ( maxColor[2] >= inset[2] ) ? maxColor[2] - inset[2] : 0;
208}
209
210
211void EmitColorIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor )
212{
213  byte colors[4][4];
214  unsigned int indices[16];
215
216  colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
217  colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
218  colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 5 );
219  colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
220  colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
221  colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 5 );
222  colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
223  colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
224  colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
225  colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
226  colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
227  colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
228
229  for ( int i = 0; i < 16; i++ ) {
230    unsigned int minDistance = MAX_INT;
231    for ( int j = 0; j < 4; j++ ) {
232      unsigned int dist = ColorDistance( &colorBlock[i*4], &colors[j][0] );
233      if ( dist < minDistance ) {
234        minDistance = dist;
235        indices[i] = j;
236      }
237    }
238  }
239  dword result = 0;
240  for ( int i = 0; i < 16; i++ ) {
241    result |= ( indices[i] << (unsigned int)( i << 1 ) );
242  }
243  EmitDoubleWord( result );
244}
245
246
247void EmitColorIndicesFast( const byte *colorBlock, const byte *minColor, const byte *maxColor )
248{
249  word colors[4][4];
250  dword result = 0;
251
252  colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
253  colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
254  colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 5 );
255  colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
256  colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
257  colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 5 );
258  colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
259  colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
260  colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
261  colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
262  colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
263  colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
264
265  for ( int i = 15; i >= 0; i-- ) {
266    int c0 = colorBlock[i*4+0];
267    int c1 = colorBlock[i*4+1];
268    int c2 = colorBlock[i*4+2];
269    int d0 = abs( colors[0][0] - c0 ) + abs( colors[0][1] - c1 ) + abs( colors[0][2] - c2 );
270    int d1 = abs( colors[1][0] - c0 ) + abs( colors[1][1] - c1 ) + abs( colors[1][2] - c2 );
271    int d2 = abs( colors[2][0] - c0 ) + abs( colors[2][1] - c1 ) + abs( colors[2][2] - c2 );
272    int d3 = abs( colors[3][0] - c0 ) + abs( colors[3][1] - c1 ) + abs( colors[3][2] - c2 );
273    int b0 = d0 > d3;
274    int b1 = d1 > d2;
275    int b2 = d0 > d2;
276    int b3 = d1 > d3;
277    int b4 = d2 > d3;
278    int x0 = b1 & b2;
279    int x1 = b0 & b3;
280    int x2 = b0 & b4;
281    result |= ( x2 | ( ( x0 | x1 ) << 1 ) ) << ( i << 1 );
282  }
283  EmitDoubleWord( result );
284}
Note: See TracBrowser for help on using the repository browser.