|
|
参考代码:
#pragma pack(push, 1)
struct CGeColor565
{
WORD blue : 5;
WORD green : 6;
WORD red : 5;
};
struct CGeColor444
{
WORD blue : 4;
WORD green : 4;
WORD red : 4;
WORD alpha : 4;
};
struct CGeDXTColBlock
{
CGeColor565 m_Color565Table[2];
BYTE m_Row[4];
};
struct CGeDXTAlphaBlockExplicit
{
WORD m_Row[4];
};
struct CGeDXTAlphaBlock3BitLinear
{
BYTE m_AlphaValue[2];
BYTE m_Data[6];
};
struct CGeDXT1Block
{
CGeDXTColBlock m_ColorBlock;
};
struct CGeDXT3Block // also used by dxt2
{
CGeDXTAlphaBlockExplicit m_AlphaBlock;
CGeDXTColBlock m_ColorBlock;
};
struct CGeDXT5Block // also used by dxt4
{
CGeDXTAlphaBlock3BitLinear m_AlphaBlock;
CGeDXTColBlock m_ColorBlock;
};
#pragma pack(pop)
BOOL CGePixLayer::Create(CGeTexture* lpImage)
{
UINT pitch;
BYTE* lpSrcData= NULL;
CGeAutoTexturToSurface atts(lpImage);
if ( (lpSrcData=(BYTE*)atts.Lock(pitch)) == NULL )
{
return FALSE;
}
ASSERT( m_PixLayer == NULL);
SAFE_DELETE(m_PixLayer);
m_PixLayer = new CGePix32Layer;
m_PixLayer->Create(lpImage->GetTextureWidth(), lpImage->GetTextureHeight());
switch(lpImage->GetFormat())
{
case D3DFMT_A4R4G4B4:
return __CreateForm4444(lpSrcData, pitch);
case D3DFMT_DXT1:
return __CreateFormDXT1(lpSrcData, pitch);
case D3DFMT_DXT2:
case D3DFMT_DXT3:
return __CreateFormDXT2(lpSrcData, pitch);
case D3DFMT_R5G6B5:
return __CreateForm565(lpSrcData, pitch);
case D3DFMT_DXT4:
case D3DFMT_DXT5:
return __CreateFormDXT4(lpSrcData, pitch);
}
return TRUE;
}
static void GetBlockColors(const CGeDXTColBlock &block, CGePix32 m_ColorTable[4], bool isDXT1)
{
for (int i = 0; i < 2; i++)
{
m_ColorTable.alpha = 0xff;
m_ColorTable.red = block.m_Color565Table.red * 0xff / 0x1f;
m_ColorTable.green = block.m_Color565Table.green* 0xff / 0x3f;
m_ColorTable.blue = block.m_Color565Table.blue * 0xff / 0x1f;
}
WORD *wCol = (WORD *)block.m_Color565Table;
if (wCol[0] > wCol[1] || !isDXT1)
{
// 4 color block
for (int i = 0; i < 2; i++)
{
m_ColorTable[i + 2].alpha = 0xff;
m_ColorTable[i + 2].red = (WORD (m_ColorTable[0].red ) * (2 - i) + WORD (m_ColorTable[1].red ) * (1 + i)) / 3;
m_ColorTable[i + 2].green = (WORD (m_ColorTable[0].green ) * (2 - i) + WORD (m_ColorTable[1].green ) * (1 + i)) / 3;
m_ColorTable[i + 2].blue = (WORD (m_ColorTable[0].blue ) * (2 - i) + WORD (m_ColorTable[1].blue ) * (1 + i)) / 3;
}
}
else
{
// 3 color block, number 4 is transparent
m_ColorTable[2].alpha = 0xff;
m_ColorTable[2].red = (WORD (m_ColorTable[0].red ) + WORD (m_ColorTable[1].red )) / 2;
m_ColorTable[2].green = (WORD (m_ColorTable[0].green ) + WORD (m_ColorTable[1].green )) / 2;
m_ColorTable[2].blue = (WORD (m_ColorTable[0].blue ) + WORD (m_ColorTable[1].blue )) / 2;
m_ColorTable[3].alpha = 0x00;
m_ColorTable[3].red = 0x00;
m_ColorTable[3].green = 0x00;
m_ColorTable[3].blue = 0x00;
}
}
BOOL CGePixLayer::__CreateFormDXT1(BYTE* lpData, UINT pitch)
{
CGePix32 Color32Table[4];
CGePix32* lpDestData= (CGePix32*)m_PixLayer->GetData();
int nDestHeight= m_PixLayer->GetHeight();
int nDestWidth = m_PixLayer->GetWidth();
for(int block_y=0; block_y< nDestHeight; block_y+= 4)
{
for(int block_x=0; block_x< nDestWidth; block_x+= 4)
{
BYTE* lpCurrSrcData = lpData+ (pitch* block_y >> 2) + ( block_x << 1 );
CGeDXT1Block* lpBlock= (CGeDXT1Block*)(lpCurrSrcData);
GetBlockColors(lpBlock->m_ColorBlock, Color32Table, TRUE);
for(int row=0; row<4; ++row) // line
{
/// column
CGePix32* lpDestDataW= &lpDestData[ (block_y+ row)* nDestWidth + block_x];
int Data = lpBlock->m_ColorBlock.m_Row[row];
int nMask= 0;
int Mask = 0x03;
for(int j=0; j<4; ++j)
{
int bit= (Data & Mask) >> nMask;
Mask <<= 2;
nMask+=2;
*lpDestDataW++ = Color32Table[bit];
}
}
}
}
return TRUE;
}
BOOL CGePixLayer::__CreateFormDXT2(BYTE* lpData, UINT pitch)
{
CGePix32 Color32Table[4];
CGePix32* lpDestData= (CGePix32*)m_PixLayer->GetData();
int nDestHeight= m_PixLayer->GetHeight();
int nDestWidth = m_PixLayer->GetWidth();
for(int block_y=0; block_y< nDestHeight; block_y+= 4)
{
for(int block_x=0; block_x< nDestWidth; block_x+= 4)
{
/// each block
BYTE* lpCurrSrcData = lpData+ (pitch* block_y >> 2) + ( block_x << 2 );
CGeDXT3Block* lpBlock= (CGeDXT3Block*)(lpCurrSrcData);
GetBlockColors(lpBlock->m_ColorBlock, Color32Table, TRUE);
for(int row=0; row<4; ++row) //row
{
/// column
CGePix32* lpDestDataW= &lpDestData[ (block_y+ row)* nDestWidth + block_x];
BYTE Data = lpBlock->m_ColorBlock.m_Row[row];
WORD Alpha= lpBlock->m_AlphaBlock.m_Row[row];
int nMask= 0;
int Mask = 0x03;
int Mask2= 0x0F;
int nMask2=0;
for(int j=0; j<4; ++j)
{
int bit= (Data & Mask) >> nMask;
int alp= (Alpha& Mask2) >> nMask2;
Mask <<= 2;
Mask2 <<= 4;
nMask+=2;
nMask2+=4;
*lpDestDataW = Color32Table[bit];
lpDestDataW->alpha = alp * 0x11;
lpDestDataW++;
}
}
}
}
return TRUE;
}
BOOL CGePixLayer::__CreateFormDXT4(BYTE* lpData, UINT pitch)
{
CGePix32 Color32Table[4];
CGePix32* lpDestData= (CGePix32*)m_PixLayer->GetData();
int nDestHeight= m_PixLayer->GetHeight();
int nDestWidth = m_PixLayer->GetWidth();
for(int block_y=0; block_y< nDestHeight; block_y+= 4)
{
for(int block_x=0; block_x< nDestWidth; block_x+= 4)
{
unsigned m_alphas[8];
unsigned m_alphaBits;
int m_offset;
/// each block
BYTE* lpCurrSrcData = lpData+ (pitch* block_y >> 2) + ( block_x << 2 );
CGeDXT5Block* lpBlock= (CGeDXT5Block*)(lpCurrSrcData);
GetBlockColors(lpBlock->m_ColorBlock, Color32Table, TRUE);
const CGeDXTAlphaBlock3BitLinear& ABlineBlock= lpBlock->m_AlphaBlock;
m_alphas[0] = ABlineBlock.m_AlphaValue[0];
m_alphas[1] = ABlineBlock.m_AlphaValue[1];
if(m_alphas[0]> m_alphas[1])
{
// 8 alpha block
for(int i=0; i<6; ++i)
m_alphas[i+2] = ((6-i)* m_alphas[0] + (1+i) * m_alphas[1]+ 3) / 7;
}
else
{
// 6 alpha block
for (int i = 0; i < 4; i++)
m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5;
m_alphas[6] = 0;
m_alphas[7] = 0xFF;
}
for(int row=0; row<4; ++row) // line
{
int i = row >> 1;
m_alphaBits = unsigned( ABlineBlock.m_Data[0+i*3]) | (unsigned( ABlineBlock.m_Data[1+i*3]) << 8) | ( unsigned)((ABlineBlock.m_Data[2+i*3]) << 16 );
m_offset = (row & 1) * 12;
/// column
CGePix32* lpDestDataW= &lpDestData[ (block_y+ row)* nDestWidth + block_x];
BYTE Data = lpBlock->m_ColorBlock.m_Row[row];
int nMask= 0;
int Mask = 0x03;
for(int j=0; j<4; ++j)
{
int bit= (Data & Mask) >> nMask;
Mask <<= 2;
nMask+=2;
*lpDestDataW = Color32Table[bit];
unsigned bits = (m_alphaBits >> (j * 3 + m_offset)) & 7;
lpDestDataW->alpha = m_alphas[bits];
lpDestDataW++;
}
}
}
}
return TRUE;
}
以上代码,如果有错误,希望指正。
MSN: liushaojing2004@hotmail.com |
|