1 /* -----------------------------------------------------------------------------
3 Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 -------------------------------------------------------------------------- */
32 static int FloatToInt( float a
, int limit
)
34 // use ANSI round-to-zero behaviour to get round-to-nearest
35 int i
= int( a
+ 0.5f
);
47 void CompressAlphaDxt3( u8
const* rgba
, int mask
, void* block
)
49 u8
* bytes
= reinterpret_cast< u8
* >( block
);
51 // quantise and pack the alpha values pairwise
52 for( int i
= 0; i
< 8; ++i
)
54 // quantise down to 4 bits
55 float alpha1
= float(rgba
[8*i
+ 3]) * ( 15.0f
/255.0f
);
56 float alpha2
= float(rgba
[8*i
+ 7]) * ( 15.0f
/255.0f
);
57 int quant1
= FloatToInt( alpha1
, 15 );
58 int quant2
= FloatToInt( alpha2
, 15 );
60 // set alpha to zero where masked
61 int bit1
= 1 << ( 2*i
);
62 int bit2
= 1 << ( 2*i
+ 1 );
63 if( ( mask
& bit1
) == 0 )
65 if( ( mask
& bit2
) == 0 )
69 bytes
[i
] = u8( quant1
| ( quant2
<< 4 ) );
73 void DecompressAlphaDxt3( u8
* rgba
, void const* block
)
75 u8
const* bytes
= reinterpret_cast< u8
const* >( block
);
77 // unpack the alpha values pairwise
78 for( int i
= 0; i
< 8; ++i
)
80 // quantise down to 4 bits
87 // convert back up to bytes
88 rgba
[8*i
+ 3] = lo
| ( lo
<< 4 );
89 rgba
[8*i
+ 7] = hi
| ( hi
>> 4 );
93 static void FixRange( int& min
, int& max
, int steps
)
95 if( max
- min
< steps
)
96 max
= std::min( min
+ steps
, 255 );
97 if( max
- min
< steps
)
98 min
= std::max( 0, max
- steps
);
101 static int FitCodes( u8
const* rgba
, int mask
, u8
const* codes
, u8
* indices
)
103 // fit each alpha value to the codebook
105 for( int i
= 0; i
< 16; ++i
)
107 // check this pixel is valid
109 if( ( mask
& bit
) == 0 )
111 // use the first code
116 // find the least error and corresponding index
117 int value
= rgba
[4*i
+ 3];
120 for( int j
= 0; j
< 8; ++j
)
122 // get the squared error from this code
123 int dist
= int(value
) - int(codes
[j
]);
126 // compare with the best so far
134 // save this index and accumulate the error
135 indices
[i
] = u8(index
);
139 // return the total error
143 static void WriteAlphaBlock( int alpha0
, int alpha1
, u8
const* indices
, void* block
)
145 u8
* bytes
= reinterpret_cast< u8
* >( block
);
147 // write the first two bytes
148 bytes
[0] = u8(alpha0
);
149 bytes
[1] = u8(alpha1
);
151 // pack the indices with 3 bits each
152 u8
* dest
= bytes
+ 2;
153 u8
const* src
= indices
;
154 for( int i
= 0; i
< 2; ++i
)
156 // pack 8 3-bit values
158 for( int j
= 0; j
< 8; ++j
)
161 value
|= ( index
<< 3*j
);
165 for( int j
= 0; j
< 3; ++j
)
167 int byte
= ( value
>> 8*j
) & 0xff;
173 static void WriteAlphaBlock5( int alpha0
, int alpha1
, u8
const* indices
, void* block
)
175 // check the relative values of the endpoints
176 if( alpha0
> alpha1
)
180 for( int i
= 0; i
< 16; ++i
)
182 u8 index
= indices
[i
];
185 else if( index
== 1 )
187 else if( index
<= 5 )
188 swapped
[i
] = 7 - index
;
194 WriteAlphaBlock( alpha1
, alpha0
, swapped
, block
);
199 WriteAlphaBlock( alpha0
, alpha1
, indices
, block
);
203 static void WriteAlphaBlock7( int alpha0
, int alpha1
, u8
const* indices
, void* block
)
205 // check the relative values of the endpoints
206 if( alpha0
< alpha1
)
210 for( int i
= 0; i
< 16; ++i
)
212 u8 index
= indices
[i
];
215 else if( index
== 1 )
218 swapped
[i
] = 9 - index
;
222 WriteAlphaBlock( alpha1
, alpha0
, swapped
, block
);
227 WriteAlphaBlock( alpha0
, alpha1
, indices
, block
);
231 void CompressAlphaDxt5( u8
const* rgba
, int mask
, void* block
)
233 // get the range for 5-alpha and 7-alpha interpolation
238 for( int i
= 0; i
< 16; ++i
)
240 // check this pixel is valid
242 if( ( mask
& bit
) == 0 )
245 // incorporate into the min/max
246 int value
= rgba
[4*i
+ 3];
251 if( value
!= 0 && value
< min5
)
253 if( value
!= 255 && value
> max5
)
257 // handle the case that no valid range was found
263 // fix the range to be the minimum in each case
264 FixRange( min5
, max5
, 5 );
265 FixRange( min7
, max7
, 7 );
267 // set up the 5-alpha code book
269 codes5
[0] = u8(min5
);
270 codes5
[1] = u8(max5
);
271 for( int i
= 1; i
< 5; ++i
)
272 codes5
[1 + i
] = u8( ( ( 5 - i
)*min5
+ i
*max5
)/5 );
276 // set up the 7-alpha code book
278 codes7
[0] = u8(min7
);
279 codes7
[1] = u8(max7
);
280 for( int i
= 1; i
< 7; ++i
)
281 codes7
[1 + i
] = u8( ( ( 7 - i
)*min7
+ i
*max7
)/7 );
283 // fit the data to both code books
286 int err5
= FitCodes( rgba
, mask
, codes5
, indices5
);
287 int err7
= FitCodes( rgba
, mask
, codes7
, indices7
);
289 // save the block with least error
291 WriteAlphaBlock5( min5
, max5
, indices5
, block
);
293 WriteAlphaBlock7( min7
, max7
, indices7
, block
);
296 void DecompressAlphaDxt5( u8
* rgba
, void const* block
)
298 // get the two alpha values
299 u8
const* bytes
= reinterpret_cast< u8
const* >( block
);
300 int alpha0
= bytes
[0];
301 int alpha1
= bytes
[1];
303 // compare the values to build the codebook
305 codes
[0] = u8(alpha0
);
306 codes
[1] = u8(alpha1
);
307 if( alpha0
<= alpha1
)
309 // use 5-alpha codebook
310 for( int i
= 1; i
< 5; ++i
)
311 codes
[1 + i
] = u8( ( ( 5 - i
)*alpha0
+ i
*alpha1
)/5 );
317 // use 7-alpha codebook
318 for( int i
= 1; i
< 7; ++i
)
319 codes
[1 + i
] = u8( ( ( 7 - i
)*alpha0
+ i
*alpha1
)/7 );
322 // decode the indices
324 u8
const* src
= bytes
+ 2;
326 for( int i
= 0; i
< 2; ++i
)
330 for( int j
= 0; j
< 3; ++j
)
333 value
|= ( byte
<< 8*j
);
336 // unpack 8 3-bit values from it
337 for( int j
= 0; j
< 8; ++j
)
339 int index
= ( value
>> 3*j
) & 0x7;
344 // write out the indexed codebook values
345 for( int i
= 0; i
< 16; ++i
)
346 rgba
[4*i
+ 3] = codes
[indices
[i
]];
349 } // namespace squish