1*2f083884Ss.makeev_local /* -----------------------------------------------------------------------------
2*2f083884Ss.makeev_local 
3*2f083884Ss.makeev_local 	Copyright (c) 2006 Simon Brown                          [email protected]
4*2f083884Ss.makeev_local 
5*2f083884Ss.makeev_local 	Permission is hereby granted, free of charge, to any person obtaining
6*2f083884Ss.makeev_local 	a copy of this software and associated documentation files (the
7*2f083884Ss.makeev_local 	"Software"), to	deal in the Software without restriction, including
8*2f083884Ss.makeev_local 	without limitation the rights to use, copy, modify, merge, publish,
9*2f083884Ss.makeev_local 	distribute, sublicense, and/or sell copies of the Software, and to
10*2f083884Ss.makeev_local 	permit persons to whom the Software is furnished to do so, subject to
11*2f083884Ss.makeev_local 	the following conditions:
12*2f083884Ss.makeev_local 
13*2f083884Ss.makeev_local 	The above copyright notice and this permission notice shall be included
14*2f083884Ss.makeev_local 	in all copies or substantial portions of the Software.
15*2f083884Ss.makeev_local 
16*2f083884Ss.makeev_local 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*2f083884Ss.makeev_local 	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*2f083884Ss.makeev_local 	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19*2f083884Ss.makeev_local 	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20*2f083884Ss.makeev_local 	CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21*2f083884Ss.makeev_local 	TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22*2f083884Ss.makeev_local 	SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*2f083884Ss.makeev_local 
24*2f083884Ss.makeev_local    -------------------------------------------------------------------------- */
25*2f083884Ss.makeev_local 
26*2f083884Ss.makeev_local #include "colourset.h"
27*2f083884Ss.makeev_local 
28*2f083884Ss.makeev_local namespace squish {
29*2f083884Ss.makeev_local 
ColourSet(u8 const * rgba,int mask,int flags)30*2f083884Ss.makeev_local ColourSet::ColourSet( u8 const* rgba, int mask, int flags )
31*2f083884Ss.makeev_local   : m_count( 0 ),
32*2f083884Ss.makeev_local 	m_transparent( false )
33*2f083884Ss.makeev_local {
34*2f083884Ss.makeev_local 	// check the compression mode for dxt1
35*2f083884Ss.makeev_local 	bool isDxt1 = ( ( flags & kDxt1 ) != 0 );
36*2f083884Ss.makeev_local 	bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 );
37*2f083884Ss.makeev_local 
38*2f083884Ss.makeev_local 	// create the minimal set
39*2f083884Ss.makeev_local 	for( int i = 0; i < 16; ++i )
40*2f083884Ss.makeev_local 	{
41*2f083884Ss.makeev_local 		// check this pixel is enabled
42*2f083884Ss.makeev_local 		int bit = 1 << i;
43*2f083884Ss.makeev_local 		if( ( mask & bit ) == 0 )
44*2f083884Ss.makeev_local 		{
45*2f083884Ss.makeev_local 			m_remap[i] = -1;
46*2f083884Ss.makeev_local 			continue;
47*2f083884Ss.makeev_local 		}
48*2f083884Ss.makeev_local 
49*2f083884Ss.makeev_local 		// check for transparent pixels when using dxt1
50*2f083884Ss.makeev_local 		if( isDxt1 && rgba[4*i + 3] < 128 )
51*2f083884Ss.makeev_local 		{
52*2f083884Ss.makeev_local 			m_remap[i] = -1;
53*2f083884Ss.makeev_local 			m_transparent = true;
54*2f083884Ss.makeev_local 			continue;
55*2f083884Ss.makeev_local 		}
56*2f083884Ss.makeev_local 
57*2f083884Ss.makeev_local 		// loop over previous points for a match
58*2f083884Ss.makeev_local 		for( int j = 0;; ++j )
59*2f083884Ss.makeev_local 		{
60*2f083884Ss.makeev_local 			// allocate a new point
61*2f083884Ss.makeev_local 			if( j == i )
62*2f083884Ss.makeev_local 			{
63*2f083884Ss.makeev_local 				// normalise coordinates to [0,1]
64*2f083884Ss.makeev_local 				float x = ( float )rgba[4*i] / 255.0f;
65*2f083884Ss.makeev_local 				float y = ( float )rgba[4*i + 1] / 255.0f;
66*2f083884Ss.makeev_local 				float z = ( float )rgba[4*i + 2] / 255.0f;
67*2f083884Ss.makeev_local 
68*2f083884Ss.makeev_local 				// ensure there is always non-zero weight even for zero alpha
69*2f083884Ss.makeev_local 				float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
70*2f083884Ss.makeev_local 
71*2f083884Ss.makeev_local 				// add the point
72*2f083884Ss.makeev_local 				m_points[m_count] = Vec3( x, y, z );
73*2f083884Ss.makeev_local 				m_weights[m_count] = ( weightByAlpha ? w : 1.0f );
74*2f083884Ss.makeev_local 				m_remap[i] = m_count;
75*2f083884Ss.makeev_local 
76*2f083884Ss.makeev_local 				// advance
77*2f083884Ss.makeev_local 				++m_count;
78*2f083884Ss.makeev_local 				break;
79*2f083884Ss.makeev_local 			}
80*2f083884Ss.makeev_local 
81*2f083884Ss.makeev_local 			// check for a match
82*2f083884Ss.makeev_local 			int oldbit = 1 << j;
83*2f083884Ss.makeev_local 			bool match = ( ( mask & oldbit ) != 0 )
84*2f083884Ss.makeev_local 				&& ( rgba[4*i] == rgba[4*j] )
85*2f083884Ss.makeev_local 				&& ( rgba[4*i + 1] == rgba[4*j + 1] )
86*2f083884Ss.makeev_local 				&& ( rgba[4*i + 2] == rgba[4*j + 2] )
87*2f083884Ss.makeev_local 				&& ( rgba[4*j + 3] >= 128 || !isDxt1 );
88*2f083884Ss.makeev_local 			if( match )
89*2f083884Ss.makeev_local 			{
90*2f083884Ss.makeev_local 				// get the index of the match
91*2f083884Ss.makeev_local 				int index = m_remap[j];
92*2f083884Ss.makeev_local 
93*2f083884Ss.makeev_local 				// ensure there is always non-zero weight even for zero alpha
94*2f083884Ss.makeev_local 				float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
95*2f083884Ss.makeev_local 
96*2f083884Ss.makeev_local 				// map to this point and increase the weight
97*2f083884Ss.makeev_local 				m_weights[index] += ( weightByAlpha ? w : 1.0f );
98*2f083884Ss.makeev_local 				m_remap[i] = index;
99*2f083884Ss.makeev_local 				break;
100*2f083884Ss.makeev_local 			}
101*2f083884Ss.makeev_local 		}
102*2f083884Ss.makeev_local 	}
103*2f083884Ss.makeev_local 
104*2f083884Ss.makeev_local 	// square root the weights
105*2f083884Ss.makeev_local 	for( int i = 0; i < m_count; ++i )
106*2f083884Ss.makeev_local 		m_weights[i] = std::sqrt( m_weights[i] );
107*2f083884Ss.makeev_local }
108*2f083884Ss.makeev_local 
RemapIndices(u8 const * source,u8 * target) const109*2f083884Ss.makeev_local void ColourSet::RemapIndices( u8 const* source, u8* target ) const
110*2f083884Ss.makeev_local {
111*2f083884Ss.makeev_local 	for( int i = 0; i < 16; ++i )
112*2f083884Ss.makeev_local 	{
113*2f083884Ss.makeev_local 		int j = m_remap[i];
114*2f083884Ss.makeev_local 		if( j == -1 )
115*2f083884Ss.makeev_local 			target[i] = 3;
116*2f083884Ss.makeev_local 		else
117*2f083884Ss.makeev_local 			target[i] = source[j];
118*2f083884Ss.makeev_local 	}
119*2f083884Ss.makeev_local }
120*2f083884Ss.makeev_local 
121*2f083884Ss.makeev_local } // namespace squish
122