982 lines
23 KiB
C++
982 lines
23 KiB
C++
|
#include "S3Decompression.h"
|
||
|
typedef UInt32 DWORD;
|
||
|
typedef UInt16 WORD;
|
||
|
typedef UInt8 BYTE;
|
||
|
|
||
|
#if UNITY_OSX
|
||
|
#define BigEndian 1
|
||
|
#else
|
||
|
#define BigEndian 0
|
||
|
#endif
|
||
|
|
||
|
struct DXTColBlock
|
||
|
{
|
||
|
WORD col0;
|
||
|
WORD col1;
|
||
|
|
||
|
// no bit fields - use bytes
|
||
|
BYTE row[4];
|
||
|
};
|
||
|
|
||
|
struct DXTAlphaBlockExplicit
|
||
|
{
|
||
|
WORD row[4];
|
||
|
};
|
||
|
|
||
|
struct DXTAlphaBlock3BitLinear
|
||
|
{
|
||
|
BYTE alpha0;
|
||
|
BYTE alpha1;
|
||
|
|
||
|
BYTE stuff[6];
|
||
|
};
|
||
|
|
||
|
#if BigEndian
|
||
|
|
||
|
// use cast to struct instead of RGBA_MAKE as struct is
|
||
|
// much
|
||
|
struct Color8888
|
||
|
{
|
||
|
BYTE a;
|
||
|
BYTE b; // Last one is MSB, 1st is LSB.
|
||
|
BYTE g; // order of the output ARGB or BGRA, etc...
|
||
|
BYTE r; // change the order of names to change the
|
||
|
};
|
||
|
|
||
|
static inline void ByteSwap(UInt16& i)
|
||
|
{
|
||
|
i = static_cast<UInt16>((i << 8) | (i >> 8));
|
||
|
}
|
||
|
|
||
|
struct Color565
|
||
|
{
|
||
|
unsigned nBlue : 5; // order of names changes
|
||
|
unsigned nGreen : 6; // byte order of output to 32 bit
|
||
|
unsigned nRed : 5;
|
||
|
};
|
||
|
|
||
|
#else
|
||
|
|
||
|
static inline void ByteSwap(UInt16& i) { }
|
||
|
|
||
|
// use cast to struct instead of RGBA_MAKE as struct is
|
||
|
// much
|
||
|
struct Color8888
|
||
|
{
|
||
|
BYTE r; // change the order of names to change the
|
||
|
BYTE g; // order of the output ARGB or BGRA, etc...
|
||
|
BYTE b; // Last one is MSB, 1st is LSB.
|
||
|
BYTE a;
|
||
|
};
|
||
|
|
||
|
struct Color565
|
||
|
{
|
||
|
unsigned nBlue : 5; // order of names changes
|
||
|
unsigned nGreen : 6; // byte order of output to 32 bit
|
||
|
unsigned nRed : 5;
|
||
|
};
|
||
|
|
||
|
|
||
|
#endif
|
||
|
|
||
|
inline void GetColorBlockColors( DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
||
|
Color8888 * col_2, Color8888 * col_3,
|
||
|
WORD & wrd )
|
||
|
{
|
||
|
// There are 4 methods to use - see the Time_ functions.
|
||
|
// 1st = shift = does normal approach per byte for color comps
|
||
|
// 2nd = use freak variable bit field color565 for component extraction
|
||
|
// 3rd = use super-freak DWORD adds BEFORE shifting the color components
|
||
|
// This lets you do only 1 add per color instead of 3 BYTE adds and
|
||
|
// might be faster
|
||
|
// Call RunTimingSession() to run each of them & output result to txt file
|
||
|
|
||
|
|
||
|
// freak variable bit structure method
|
||
|
// normal math
|
||
|
// This method is fastest
|
||
|
WORD col0 = pBlock->col0;
|
||
|
ByteSwap (col0);
|
||
|
WORD col1 = pBlock->col1;
|
||
|
ByteSwap (col1);
|
||
|
|
||
|
Color565 * pCol;
|
||
|
|
||
|
pCol = (Color565*) & (col0 );
|
||
|
|
||
|
col_0->a = 0xff;
|
||
|
col_0->r = pCol->nRed;
|
||
|
col_0->r <<= 3; // shift to full precision
|
||
|
col_0->g = pCol->nGreen;
|
||
|
col_0->g <<= 2;
|
||
|
col_0->b = pCol->nBlue;
|
||
|
col_0->b <<= 3;
|
||
|
|
||
|
pCol = (Color565*) & (col1 );
|
||
|
col_1->a = 0xff;
|
||
|
col_1->r = pCol->nRed;
|
||
|
col_1->r <<= 3; // shift to full precision
|
||
|
col_1->g = pCol->nGreen;
|
||
|
col_1->g <<= 2;
|
||
|
col_1->b = pCol->nBlue;
|
||
|
col_1->b <<= 3;
|
||
|
|
||
|
|
||
|
if( col0 > col1 )
|
||
|
{
|
||
|
// Four-color block: derive the other two colors.
|
||
|
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
|
||
|
// These two bit codes correspond to the 2-bit fields
|
||
|
// stored in the 64-bit block.
|
||
|
|
||
|
wrd = ((WORD)col_0->r * 2 + (WORD)col_1->r )/3;
|
||
|
// no +1 for rounding
|
||
|
// as bits have been shifted to 888
|
||
|
col_2->r = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->g * 2 + (WORD)col_1->g )/3;
|
||
|
col_2->g = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->b * 2 + (WORD)col_1->b )/3;
|
||
|
col_2->b = (BYTE)wrd;
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
wrd = ((WORD)col_0->r + (WORD)col_1->r *2 )/3;
|
||
|
col_3->r = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->g + (WORD)col_1->g *2 )/3;
|
||
|
col_3->g = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->b + (WORD)col_1->b *2 )/3;
|
||
|
col_3->b = (BYTE)wrd;
|
||
|
col_3->a = 0xff;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Three-color block: derive the other color.
|
||
|
// 00 = color_0, 01 = color_1, 10 = color_2,
|
||
|
// 11 = transparent.
|
||
|
// These two bit codes correspond to the 2-bit fields
|
||
|
// stored in the 64-bit block.
|
||
|
|
||
|
// explicit for each component, unlike some refrasts...
|
||
|
|
||
|
// TRACE("block has alpha\n");
|
||
|
|
||
|
wrd = ((WORD)col_0->r + (WORD)col_1->r )/2;
|
||
|
col_2->r = (BYTE)wrd;
|
||
|
wrd = ((WORD)col_0->g + (WORD)col_1->g )/2;
|
||
|
col_2->g = (BYTE)wrd;
|
||
|
wrd = ((WORD)col_0->b + (WORD)col_1->b )/2;
|
||
|
col_2->b = (BYTE)wrd;
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
col_3->r = 0x00; // random color to indicate alpha
|
||
|
col_3->g = 0xff;
|
||
|
col_3->b = 0xff;
|
||
|
col_3->a = 0x00;
|
||
|
|
||
|
}
|
||
|
} // Get color block colors (...)
|
||
|
|
||
|
|
||
|
|
||
|
inline void DecodeColorBlock( DWORD * pImPos, DXTColBlock * pColorBlock, int width,
|
||
|
DWORD * col_0,
|
||
|
DWORD * col_1, DWORD * col_2, DWORD * col_3 )
|
||
|
{
|
||
|
// width is width of image in pixels
|
||
|
|
||
|
|
||
|
DWORD bits;
|
||
|
int r,n;
|
||
|
|
||
|
// bit masks = 00000011, 00001100, 00110000, 11000000
|
||
|
const DWORD masks[] = { 3, 12, 3 << 4, 3 << 6 };
|
||
|
const int shift[] = { 0, 2, 4, 6 };
|
||
|
|
||
|
// r steps through lines in y
|
||
|
for( r=0; r < 4; r++, pImPos += width-4 ) // no width*4 as DWORD ptr inc will *4
|
||
|
{
|
||
|
|
||
|
// width * 4 bytes per pixel per line
|
||
|
// each j dxtc row is 4 lines of pixels
|
||
|
|
||
|
// pImPos = (DWORD*)((DWORD)pBase + i*16 + (r+j*4) * m_nWidth * 4 );
|
||
|
|
||
|
// n steps through pixels
|
||
|
for( n=0; n < 4; n++ )
|
||
|
{
|
||
|
bits = pColorBlock->row[r] & masks[n];
|
||
|
bits >>= shift[n];
|
||
|
// AssertIf (bits < 0 || bits > 3);
|
||
|
switch( bits )
|
||
|
{
|
||
|
case 0 :
|
||
|
*pImPos = *col_0;
|
||
|
pImPos++; // increment to next DWORD
|
||
|
break;
|
||
|
case 1 :
|
||
|
*pImPos = *col_1;
|
||
|
pImPos++;
|
||
|
break;
|
||
|
case 2 :
|
||
|
*pImPos = *col_2;
|
||
|
pImPos++;
|
||
|
break;
|
||
|
case 3 :
|
||
|
*pImPos = *col_3;
|
||
|
pImPos++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
inline void DecodeAlphaExplicit( DWORD * pImPos, DXTAlphaBlockExplicit * pAlphaBlock,
|
||
|
int width, DWORD alphazero )
|
||
|
{
|
||
|
// alphazero is a bit mask that when & with the image color
|
||
|
// will zero the alpha bits, so if the image DWORDs are
|
||
|
// ARGB then alphazero will be 0x00ffffff or if
|
||
|
// RGBA then alphazero will be 0xffffff00
|
||
|
// alphazero constructed automaticaly from field order of Color8888 structure
|
||
|
|
||
|
// decodes to 32 bit format only
|
||
|
|
||
|
int row, pix;
|
||
|
|
||
|
WORD wrd;
|
||
|
|
||
|
Color8888 col;
|
||
|
col.r = col.g = col.b = 0;
|
||
|
|
||
|
|
||
|
//TRACE("\n");
|
||
|
|
||
|
for( row=0; row < 4; row++, pImPos += width-4 )
|
||
|
{
|
||
|
// pImPow += pImPos += width-4 moves to next row down
|
||
|
|
||
|
wrd = pAlphaBlock->row[ row ];
|
||
|
ByteSwap (wrd);
|
||
|
|
||
|
// TRACE("0x%.8x\t\t", wrd);
|
||
|
|
||
|
for( pix = 0; pix < 4; pix++ )
|
||
|
{
|
||
|
// zero the alpha bits of image pixel
|
||
|
*pImPos &= alphazero;
|
||
|
|
||
|
col.a = wrd & 0x000f; // get only low 4 bits
|
||
|
// col.a <<= 4; // shift to full byte precision
|
||
|
// NOTE: with just a << 4 you'll never have alpha
|
||
|
// of 0xff, 0xf0 is max so pure shift doesn't quite
|
||
|
// cover full alpha range.
|
||
|
// It's much cheaper than divide & scale though.
|
||
|
// To correct for this, and get 0xff for max alpha,
|
||
|
// or the low bits back in after left shifting
|
||
|
col.a = col.a | (col.a << 4 ); // This allows max 4 bit alpha to be 0xff alpha
|
||
|
// in final image, and is crude approach to full
|
||
|
// range scale
|
||
|
|
||
|
*pImPos |= *((DWORD*)&col); // or the bits into the prev. nulled alpha
|
||
|
|
||
|
wrd >>= 4; // move next bits to lowest 4
|
||
|
|
||
|
pImPos++; // move to next pixel in the row
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BYTE gBits[4][4];
|
||
|
WORD gAlphas[8];
|
||
|
Color8888 gACol[4][4];
|
||
|
|
||
|
|
||
|
inline void DecodeAlpha3BitLinear( DWORD * pImPos, DXTAlphaBlock3BitLinear * pAlphaBlock,
|
||
|
int width, DWORD alphazero)
|
||
|
{
|
||
|
|
||
|
gAlphas[0] = pAlphaBlock->alpha0;
|
||
|
gAlphas[1] = pAlphaBlock->alpha1;
|
||
|
|
||
|
|
||
|
// 8-alpha or 6-alpha block?
|
||
|
|
||
|
if( gAlphas[0] > gAlphas[1] )
|
||
|
{
|
||
|
// 8-alpha block: derive the other 6 alphas.
|
||
|
// 000 = alpha_0, 001 = alpha_1, others are interpolated
|
||
|
|
||
|
gAlphas[2] = ( 6 * gAlphas[0] + gAlphas[1]) / 7; // bit code 010
|
||
|
gAlphas[3] = ( 5 * gAlphas[0] + 2 * gAlphas[1]) / 7; // Bit code 011
|
||
|
gAlphas[4] = ( 4 * gAlphas[0] + 3 * gAlphas[1]) / 7; // Bit code 100
|
||
|
gAlphas[5] = ( 3 * gAlphas[0] + 4 * gAlphas[1]) / 7; // Bit code 101
|
||
|
gAlphas[6] = ( 2 * gAlphas[0] + 5 * gAlphas[1]) / 7; // Bit code 110
|
||
|
gAlphas[7] = ( gAlphas[0] + 6 * gAlphas[1]) / 7; // Bit code 111
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// 6-alpha block: derive the other alphas.
|
||
|
// 000 = alpha_0, 001 = alpha_1, others are interpolated
|
||
|
|
||
|
gAlphas[2] = (4 * gAlphas[0] + gAlphas[1]) / 5; // Bit code 010
|
||
|
gAlphas[3] = (3 * gAlphas[0] + 2 * gAlphas[1]) / 5; // Bit code 011
|
||
|
gAlphas[4] = (2 * gAlphas[0] + 3 * gAlphas[1]) / 5; // Bit code 100
|
||
|
gAlphas[5] = ( gAlphas[0] + 4 * gAlphas[1]) / 5; // Bit code 101
|
||
|
gAlphas[6] = 0; // Bit code 110
|
||
|
gAlphas[7] = 255; // Bit code 111
|
||
|
}
|
||
|
|
||
|
|
||
|
// Decode 3-bit fields into array of 16 BYTES with same value
|
||
|
|
||
|
// first two rows of 4 pixels each:
|
||
|
// pRows = (Alpha3BitRows*) & ( pAlphaBlock->stuff[0] );
|
||
|
const DWORD mask = 0x00000007; // bits = 00 00 01 11
|
||
|
|
||
|
DWORD bits = *( (DWORD*) & ( pAlphaBlock->stuff[0] ));
|
||
|
|
||
|
gBits[0][0] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[0][1] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[0][2] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[0][3] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[1][0] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[1][1] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[1][2] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[1][3] = (BYTE)( bits & mask );
|
||
|
|
||
|
// now for last two rows:
|
||
|
|
||
|
bits = *( (DWORD*) & ( pAlphaBlock->stuff[3] )); // last 3 bytes
|
||
|
|
||
|
gBits[2][0] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[2][1] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[2][2] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[2][3] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[3][0] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[3][1] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[3][2] = (BYTE)( bits & mask );
|
||
|
bits >>= 3;
|
||
|
gBits[3][3] = (BYTE)( bits & mask );
|
||
|
|
||
|
|
||
|
// decode the codes into alpha values
|
||
|
int row, pix;
|
||
|
|
||
|
|
||
|
for( row = 0; row < 4; row++ )
|
||
|
{
|
||
|
for( pix=0; pix < 4; pix++ )
|
||
|
{
|
||
|
gACol[row][pix].a = (BYTE) gAlphas[ gBits[row][pix] ];
|
||
|
|
||
|
// AssertIf( gACol[row][pix].r != 0 );
|
||
|
// AssertIf( gACol[row][pix].g != 0 );
|
||
|
// AssertIf( gACol[row][pix].b == 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Write out alpha values to the image bits
|
||
|
|
||
|
for( row=0; row < 4; row++, pImPos += width-4 )
|
||
|
{
|
||
|
// pImPow += pImPos += width-4 moves to next row down
|
||
|
|
||
|
for( pix = 0; pix < 4; pix++ )
|
||
|
{
|
||
|
// zero the alpha bits of image pixel
|
||
|
*pImPos &= alphazero;
|
||
|
|
||
|
*pImPos |= *((DWORD*) &(gACol[row][pix])); // or the bits into the prev. nulled alpha
|
||
|
pImPos++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void DecompressDXT1(int width, int height, DWORD* m_pCompBytes, DWORD* m_pDecompBytes)
|
||
|
{
|
||
|
// This was hacked up pretty quick & slopily
|
||
|
// decompresses to 32 bit format 0xARGB
|
||
|
|
||
|
int xblocks, yblocks;
|
||
|
|
||
|
xblocks = width / 4;
|
||
|
yblocks = height / 4;
|
||
|
|
||
|
|
||
|
int i,j;
|
||
|
|
||
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
||
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
||
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
||
|
|
||
|
DXTColBlock * pBlock;
|
||
|
|
||
|
Color8888 col_0, col_1, col_2, col_3;
|
||
|
|
||
|
|
||
|
WORD wrd;
|
||
|
|
||
|
for( j=0; j < yblocks; j++ )
|
||
|
{
|
||
|
// 8 bytes per block
|
||
|
pBlock = (DXTColBlock*) ( (DWORD)m_pCompBytes + j * xblocks * 8 );
|
||
|
|
||
|
|
||
|
for( i=0; i < xblocks; i++, pBlock++ )
|
||
|
{
|
||
|
|
||
|
// inline func:
|
||
|
GetColorBlockColors( pBlock, &col_0, &col_1, &col_2, &col_3, wrd );
|
||
|
|
||
|
|
||
|
// now decode the color block into the bitmap bits
|
||
|
// inline func:
|
||
|
|
||
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * width * 4 );
|
||
|
|
||
|
|
||
|
DecodeColorBlock( pImPos, pBlock, width, (DWORD*)&col_0, (DWORD*)&col_1,
|
||
|
(DWORD*)&col_2, (DWORD*)&col_3 );
|
||
|
|
||
|
|
||
|
// Set to RGB test pattern
|
||
|
// pImPos = (DWORD*)((DWORD)pBase + i*4 + j*m_nWidth*4);
|
||
|
// *pImPos = ((i*4) << 16) | ((j*4) << 8 ) | ( (63-i)*4 );
|
||
|
|
||
|
// checkerboard of only col_0 and col_1 basis colors:
|
||
|
// pImPos = (DWORD*)((DWORD)pBase + i*8 + j*m_nWidth*8);
|
||
|
// *pImPos = *((DWORD*)&col_0);
|
||
|
// pImPos += 1 + m_nWidth;
|
||
|
// *pImPos = *((DWORD*)&col_1);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void DecompressDXT3(int width, int height, DWORD* m_pCompBytes, DWORD* m_pDecompBytes)
|
||
|
{
|
||
|
int xblocks, yblocks;
|
||
|
|
||
|
xblocks = width / 4;
|
||
|
yblocks = height / 4;
|
||
|
|
||
|
|
||
|
int i,j;
|
||
|
|
||
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
||
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
||
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
||
|
|
||
|
DXTColBlock * pBlock;
|
||
|
DXTAlphaBlockExplicit * pAlphaBlock;
|
||
|
|
||
|
Color8888 col_0, col_1, col_2, col_3;
|
||
|
|
||
|
|
||
|
WORD wrd;
|
||
|
|
||
|
// fill alphazero with appropriate value to zero out alpha when
|
||
|
// alphazero is ANDed with the image color 32 bit DWORD:
|
||
|
col_0.a = 0;
|
||
|
col_0.r = col_0.g = col_0.b = 0xff;
|
||
|
DWORD alphazero = *((DWORD*) &col_0);
|
||
|
|
||
|
|
||
|
for( j=0; j < yblocks; j++ )
|
||
|
{
|
||
|
// 8 bytes per block
|
||
|
// 1 block for alpha, 1 block for color
|
||
|
|
||
|
pBlock = (DXTColBlock*) ( (DWORD)m_pCompBytes + j * xblocks * 16 );
|
||
|
|
||
|
for( i=0; i < xblocks; i++, pBlock ++ )
|
||
|
{
|
||
|
|
||
|
// inline
|
||
|
// Get alpha block
|
||
|
|
||
|
pAlphaBlock = (DXTAlphaBlockExplicit*) pBlock;
|
||
|
|
||
|
// inline func:
|
||
|
// Get color block & colors
|
||
|
pBlock++;
|
||
|
GetColorBlockColors( pBlock, &col_0, &col_1, &col_2, &col_3, wrd );
|
||
|
|
||
|
// Decode the color block into the bitmap bits
|
||
|
// inline func:
|
||
|
|
||
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * width * 4 );
|
||
|
|
||
|
|
||
|
DecodeColorBlock( pImPos, pBlock, width, (DWORD*)&col_0, (DWORD*)&col_1,
|
||
|
(DWORD*)&col_2, (DWORD*)&col_3 );
|
||
|
|
||
|
// Overwrite the previous alpha bits with the alpha block
|
||
|
// info
|
||
|
// inline func:
|
||
|
DecodeAlphaExplicit( pImPos, pAlphaBlock, width, alphazero );
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void DecompressDXT5(int width, int height, DWORD* m_pCompBytes, DWORD* m_pDecompBytes)
|
||
|
{
|
||
|
|
||
|
int xblocks, yblocks;
|
||
|
|
||
|
xblocks = width / 4;
|
||
|
yblocks = height / 4;
|
||
|
|
||
|
|
||
|
int i,j;
|
||
|
|
||
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
||
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
||
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
||
|
|
||
|
DXTColBlock * pBlock;
|
||
|
DXTAlphaBlock3BitLinear * pAlphaBlock;
|
||
|
|
||
|
Color8888 col_0, col_1, col_2, col_3;
|
||
|
WORD wrd;
|
||
|
|
||
|
// fill alphazero with appropriate value to zero out alpha when
|
||
|
// alphazero is ANDed with the image color 32 bit DWORD:
|
||
|
col_0.a = 0;
|
||
|
col_0.r = col_0.g = col_0.b = 0xff;
|
||
|
DWORD alphazero = *((DWORD*) &col_0);
|
||
|
|
||
|
////////////////////////////////
|
||
|
// TRACE("blocks: x: %d y: %d\n", xblocks, yblocks );
|
||
|
|
||
|
for( j=0; j < yblocks; j++ )
|
||
|
{
|
||
|
// 8 bytes per block
|
||
|
// 1 block for alpha, 1 block for color
|
||
|
|
||
|
pBlock = (DXTColBlock*) ( (DWORD)m_pCompBytes + j * xblocks * 16 );
|
||
|
|
||
|
for( i=0; i < xblocks; i++, pBlock ++ )
|
||
|
{
|
||
|
|
||
|
// inline
|
||
|
// Get alpha block
|
||
|
|
||
|
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
|
||
|
|
||
|
// inline func:
|
||
|
// Get color block & colors
|
||
|
pBlock++;
|
||
|
|
||
|
GetColorBlockColors( pBlock, &col_0, &col_1, &col_2, &col_3, wrd );
|
||
|
|
||
|
// Decode the color block into the bitmap bits
|
||
|
// inline func:
|
||
|
|
||
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * width * 4 );
|
||
|
|
||
|
|
||
|
DecodeColorBlock( pImPos, pBlock, width, (DWORD*)&col_0, (DWORD*)&col_1,
|
||
|
(DWORD*)&col_2, (DWORD*)&col_3 );
|
||
|
|
||
|
// Overwrite the previous alpha bits with the alpha block
|
||
|
// info
|
||
|
|
||
|
DecodeAlpha3BitLinear( pImPos, pAlphaBlock, width, alphazero );
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
} // dxt5
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
inline void GetColorBlockColors_m2( DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
||
|
Color8888 * col_2, Color8888 * col_3,
|
||
|
WORD & wrd )
|
||
|
{
|
||
|
// method 2
|
||
|
// freak variable bit structure method
|
||
|
// normal math
|
||
|
|
||
|
Color565 * pCol;
|
||
|
|
||
|
pCol = (Color565*) & (pBlock->col0 );
|
||
|
|
||
|
col_0->a = 0xff;
|
||
|
col_0->r = pCol->nRed;
|
||
|
col_0->r <<= 3; // shift to full precision
|
||
|
col_0->g = pCol->nGreen;
|
||
|
col_0->g <<= 2;
|
||
|
col_0->b = pCol->nBlue;
|
||
|
col_0->b <<= 3;
|
||
|
|
||
|
pCol = (Color565*) & (pBlock->col1 );
|
||
|
col_1->a = 0xff;
|
||
|
col_1->r = pCol->nRed;
|
||
|
col_1->r <<= 3; // shift to full precision
|
||
|
col_1->g = pCol->nGreen;
|
||
|
col_1->g <<= 2;
|
||
|
col_1->b = pCol->nBlue;
|
||
|
col_1->b <<= 3;
|
||
|
|
||
|
|
||
|
if( pBlock->col0 > pBlock->col1 )
|
||
|
{
|
||
|
// Four-color block: derive the other two colors.
|
||
|
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
|
||
|
// These two bit codes correspond to the 2-bit fields
|
||
|
// stored in the 64-bit block.
|
||
|
|
||
|
wrd = ((WORD)col_0->r * 2 + (WORD)col_1->r )/3;
|
||
|
// no +1 for rounding
|
||
|
// as bits have been shifted to 888
|
||
|
col_2->r = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->g * 2 + (WORD)col_1->g )/3;
|
||
|
col_2->g = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->b * 2 + (WORD)col_1->b )/3;
|
||
|
col_2->b = (BYTE)wrd;
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
wrd = ((WORD)col_0->r + (WORD)col_1->r *2 )/3;
|
||
|
col_3->r = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->g + (WORD)col_1->g *2 )/3;
|
||
|
col_3->g = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->b + (WORD)col_1->b *2 )/3;
|
||
|
col_3->b = (BYTE)wrd;
|
||
|
col_3->a = 0xff;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Three-color block: derive the other color.
|
||
|
// 00 = color_0, 01 = color_1, 10 = color_2,
|
||
|
// 11 = transparent.
|
||
|
// These two bit codes correspond to the 2-bit fields
|
||
|
// stored in the 64-bit block.
|
||
|
|
||
|
// explicit for each component, unlike some refrasts...
|
||
|
|
||
|
// TRACE("block has alpha\n");
|
||
|
|
||
|
wrd = ((WORD)col_0->r + (WORD)col_1->r )/2;
|
||
|
col_2->r = (BYTE)wrd;
|
||
|
wrd = ((WORD)col_0->g + (WORD)col_1->g )/2;
|
||
|
col_2->g = (BYTE)wrd;
|
||
|
wrd = ((WORD)col_0->b + (WORD)col_1->b )/2;
|
||
|
col_2->b = (BYTE)wrd;
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
col_3->r = 0x00; // random color to indicate alpha
|
||
|
col_3->g = 0xff;
|
||
|
col_3->b = 0xff;
|
||
|
col_3->a = 0x00;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
/*
|
||
|
inline void GetColorBlockColors_m3( DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
||
|
Color8888 * col_2, Color8888 * col_3,
|
||
|
WORD & wrd )
|
||
|
{
|
||
|
// method 3
|
||
|
//////////////////////////////////////////////////////
|
||
|
// super-freak variable bit structure with
|
||
|
// Cool Math Trick (tm)
|
||
|
|
||
|
// Do 2/3 1/3 math BEFORE bit shift on the whole DWORD
|
||
|
// as the fields will NEVER carry into the next
|
||
|
// or overflow!! =)
|
||
|
|
||
|
Color565 * pCol;
|
||
|
|
||
|
pCol = (Color565*) & (pBlock->col0 );
|
||
|
|
||
|
col_0->a = 0x00; // must set to 0 to avoid overflow in DWORD add
|
||
|
col_0->r = pCol->nRed;
|
||
|
col_0->g = pCol->nGreen;
|
||
|
col_0->b = pCol->nBlue;
|
||
|
|
||
|
pCol = (Color565*) & (pBlock->col1 );
|
||
|
col_1->a = 0x00;
|
||
|
col_1->r = pCol->nRed;
|
||
|
col_1->g = pCol->nGreen;
|
||
|
col_1->b = pCol->nBlue;
|
||
|
|
||
|
if( pBlock->col0 > pBlock->col1 )
|
||
|
{
|
||
|
*((DWORD*)col_2) = ( (*((DWORD*)col_0)) * 2 + (*((DWORD*)col_1)) );
|
||
|
|
||
|
*((DWORD*)col_3) = ( (*((DWORD*)col_0)) + (*((DWORD*)col_1)) * 2 );
|
||
|
|
||
|
// now shift to appropriate precision & divide by 3.
|
||
|
col_2->r = ((WORD)col_2->r << 3) / (WORD)3;
|
||
|
col_2->g = ((WORD)col_2->g << 2) / (WORD)3;
|
||
|
col_2->b = ((WORD)col_2->b << 3) / (WORD)3;
|
||
|
|
||
|
col_3->r = ((WORD)col_3->r << 3) / (WORD)3;
|
||
|
col_3->g = ((WORD)col_3->g << 2) / (WORD)3;
|
||
|
col_3->b = ((WORD)col_3->b << 3) / (WORD)3;
|
||
|
|
||
|
|
||
|
col_0->a = 0xff; // now set appropriate alpha
|
||
|
col_1->a = 0xff;
|
||
|
col_2->a = 0xff;
|
||
|
col_3->a = 0xff;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*((DWORD*)col_2) = ( (*((DWORD*)col_0)) + (*((DWORD*)col_1)) );
|
||
|
|
||
|
// now shift to appropriate precision & divide by 2.
|
||
|
// << 3 ) / 2 == << 2
|
||
|
// << 2 ) / 2 == << 1
|
||
|
col_2->r = ((WORD)col_2->r << 2);
|
||
|
col_2->g = ((WORD)col_2->g << 1);
|
||
|
col_2->b = ((WORD)col_2->b << 2);
|
||
|
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
col_3->a = 0x00; //
|
||
|
col_3->r = 0x00; // random color to indicate alpha
|
||
|
col_3->g = 0xff;
|
||
|
col_3->b = 0xff;
|
||
|
}
|
||
|
|
||
|
// now shift orig color components
|
||
|
col_0->r <<= 3;
|
||
|
col_0->g <<= 2;
|
||
|
col_0->b <<= 3;
|
||
|
|
||
|
col_1->r <<= 3;
|
||
|
col_1->g <<= 2;
|
||
|
col_1->b <<= 3;
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
/*
|
||
|
inline void GetColorBlockColors_m4( DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
||
|
Color8888 * col_2, Color8888 * col_3,
|
||
|
WORD & wrd )
|
||
|
{
|
||
|
|
||
|
// m1 color extraction from 5-6-5
|
||
|
// m3 color math on DWORD before bit shift to full precision
|
||
|
|
||
|
|
||
|
wrd = pBlock->col0;
|
||
|
col_0->a = 0x00; // must set to 0 to avoid possible overflow & carry to next field in DWORD add
|
||
|
|
||
|
// extract r,g,b bits
|
||
|
col_0->b = (unsigned char) wrd & 0x1f; // 0x1f = 0001 1111 to mask out upper 3 bits
|
||
|
wrd >>= 5;
|
||
|
col_0->g = (unsigned char) wrd & 0x3f; // 0x3f = 0011 1111 to mask out upper 2 bits
|
||
|
wrd >>= 6;
|
||
|
col_0->r = (unsigned char) wrd & 0x1f;
|
||
|
|
||
|
|
||
|
// same for col # 2:
|
||
|
wrd = pBlock->col1;
|
||
|
col_1->a = 0x00; // must set to 0 to avoid possible overflow in DWORD add
|
||
|
|
||
|
// extract r,g,b bits
|
||
|
col_1->b = (unsigned char) wrd & 0x1f;
|
||
|
wrd >>= 5;
|
||
|
col_1->g = (unsigned char) wrd & 0x3f;
|
||
|
wrd >>= 6;
|
||
|
col_1->r = (unsigned char) wrd & 0x1f;
|
||
|
|
||
|
|
||
|
if( pBlock->col0 > pBlock->col1 )
|
||
|
{
|
||
|
*((DWORD*)col_2) = ( (*((DWORD*)col_0)) * 2 + (*((DWORD*)col_1)) );
|
||
|
|
||
|
*((DWORD*)col_3) = ( (*((DWORD*)col_0)) + (*((DWORD*)col_1)) * 2 );
|
||
|
|
||
|
// shift to appropriate precision & divide by 3.
|
||
|
col_2->r = ((WORD)col_2->r << 3) / (WORD)3;
|
||
|
col_2->g = ((WORD)col_2->g << 2) / (WORD)3;
|
||
|
col_2->b = ((WORD)col_2->b << 3) / (WORD)3;
|
||
|
|
||
|
col_3->r = ((WORD)col_3->r << 3) / (WORD)3;
|
||
|
col_3->g = ((WORD)col_3->g << 2) / (WORD)3;
|
||
|
col_3->b = ((WORD)col_3->b << 3) / (WORD)3;
|
||
|
|
||
|
|
||
|
col_0->a = 0xff; // set appropriate alpha
|
||
|
col_1->a = 0xff;
|
||
|
col_2->a = 0xff;
|
||
|
col_3->a = 0xff;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*((DWORD*)col_2) = ( (*((DWORD*)col_0)) + (*((DWORD*)col_1)) );
|
||
|
|
||
|
// shift to appropriate precision & divide by 2.
|
||
|
// << 3 ) / 2 == << 2
|
||
|
// << 2 ) / 2 == << 1
|
||
|
col_2->r = ((WORD)col_2->r << 2);
|
||
|
col_2->g = ((WORD)col_2->g << 1);
|
||
|
col_2->b = ((WORD)col_2->b << 2);
|
||
|
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
col_3->a = 0x00; //
|
||
|
col_3->r = 0x00; // random color to indicate alpha
|
||
|
col_3->g = 0xff;
|
||
|
col_3->b = 0xff;
|
||
|
}
|
||
|
|
||
|
// shift orig color components to full precision
|
||
|
col_0->r <<= 3;
|
||
|
col_0->g <<= 2;
|
||
|
col_0->b <<= 3;
|
||
|
|
||
|
col_1->r <<= 3;
|
||
|
col_1->g <<= 2;
|
||
|
col_1->b <<= 3;
|
||
|
}
|
||
|
*/
|
||
|
/*
|
||
|
inline void GetColorBlockColors_m1( DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
||
|
Color8888 * col_2, Color8888 * col_3,
|
||
|
WORD & wrd )
|
||
|
{
|
||
|
|
||
|
// Method 1:
|
||
|
// Shifty method
|
||
|
|
||
|
wrd = pBlock->col0;
|
||
|
col_0->a = 0xff;
|
||
|
|
||
|
// extract r,g,b bits
|
||
|
col_0->b = (unsigned char) wrd;
|
||
|
col_0->b <<= 3; // shift to full precision
|
||
|
wrd >>= 5;
|
||
|
col_0->g = (unsigned char) wrd;
|
||
|
col_0->g <<= 2; // shift to full precision
|
||
|
wrd >>= 6;
|
||
|
col_0->r = (unsigned char) wrd;
|
||
|
col_0->r <<= 3; // shift to full precision
|
||
|
|
||
|
|
||
|
// same for col # 2:
|
||
|
wrd = pBlock->col1;
|
||
|
col_1->a = 0xff;
|
||
|
|
||
|
// extract r,g,b bits
|
||
|
col_1->b = (unsigned char) wrd;
|
||
|
col_1->b <<= 3; // shift to full precision
|
||
|
wrd >>= 5;
|
||
|
col_1->g = (unsigned char) wrd;
|
||
|
col_1->g <<= 2; // shift to full precision
|
||
|
wrd >>= 6;
|
||
|
col_1->r = (unsigned char) wrd;
|
||
|
col_1->r <<= 3; // shift to full precision
|
||
|
|
||
|
|
||
|
|
||
|
// use this for all but the super-freak math method
|
||
|
|
||
|
if( pBlock->col0 > pBlock->col1 )
|
||
|
{
|
||
|
// Four-color block: derive the other two colors.
|
||
|
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
|
||
|
// These two bit codes correspond to the 2-bit fields
|
||
|
// stored in the 64-bit block.
|
||
|
|
||
|
wrd = ((WORD)col_0->r * 2 + (WORD)col_1->r )/3;
|
||
|
// no +1 for rounding
|
||
|
// as bits have been shifted to 888
|
||
|
col_2->r = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->g * 2 + (WORD)col_1->g )/3;
|
||
|
col_2->g = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->b * 2 + (WORD)col_1->b )/3;
|
||
|
col_2->b = (BYTE)wrd;
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
wrd = ((WORD)col_0->r + (WORD)col_1->r *2 )/3;
|
||
|
col_3->r = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->g + (WORD)col_1->g *2 )/3;
|
||
|
col_3->g = (BYTE)wrd;
|
||
|
|
||
|
wrd = ((WORD)col_0->b + (WORD)col_1->b *2 )/3;
|
||
|
col_3->b = (BYTE)wrd;
|
||
|
col_3->a = 0xff;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Three-color block: derive the other color.
|
||
|
// 00 = color_0, 01 = color_1, 10 = color_2,
|
||
|
// 11 = transparent.
|
||
|
// These two bit codes correspond to the 2-bit fields
|
||
|
// stored in the 64-bit block.
|
||
|
|
||
|
// explicit for each component, unlike some refrasts...
|
||
|
|
||
|
// TRACE("block has alpha\n");
|
||
|
|
||
|
wrd = ((WORD)col_0->r + (WORD)col_1->r )/2;
|
||
|
col_2->r = (BYTE)wrd;
|
||
|
wrd = ((WORD)col_0->g + (WORD)col_1->g )/2;
|
||
|
col_2->g = (BYTE)wrd;
|
||
|
wrd = ((WORD)col_0->b + (WORD)col_1->b )/2;
|
||
|
col_2->b = (BYTE)wrd;
|
||
|
col_2->a = 0xff;
|
||
|
|
||
|
col_3->r = 0x00; // random color to indicate alpha
|
||
|
col_3->g = 0xff;
|
||
|
col_3->b = 0xff;
|
||
|
col_3->a = 0x00;
|
||
|
|
||
|
}
|
||
|
} // Get color block colors (...)
|
||
|
|
||
|
*/
|