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