Add DXT5 decompression, as mentioned in #21

This commit is contained in:
Pavel Krajcevski 2016-09-29 23:48:38 -07:00
parent 5dd85e5896
commit 2f8ea3dc07
4 changed files with 67 additions and 3 deletions

View file

@ -326,6 +326,8 @@ int main(int argc, char **argv) {
strcat(basename, "-pvrtc-4bpp.png");
} else if(format == FasTC::eCompressionFormat_DXT1) {
strcat(basename, "-dxt1.png");
} else if(format == FasTC::eCompressionFormat_DXT5) {
strcat(basename, "-dxt5.png");
} else if(format == FasTC::eCompressionFormat_ETC1) {
strcat(basename, "-etc1.png");
}

View file

@ -91,7 +91,9 @@ bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBuf
DecompressionJob dj (m_Format, byteData, outBuf, GetWidth(), GetHeight());
if(m_Format == FasTC::eCompressionFormat_DXT1) {
DXTC::DecompressDXT1(dj);
} else if(m_Format == FasTC::eCompressionFormat_ETC1) {
} else if(m_Format == FasTC::eCompressionFormat_DXT5) {
DXTC::DecompressDXT5(dj);
} else if (m_Format == FasTC::eCompressionFormat_ETC1) {
ETCC::Decompress(dj);
} else if(FasTC::COMPRESSION_FORMAT_PVRTC_BEGIN <= m_Format &&
FasTC::COMPRESSION_FORMAT_PVRTC_END >= m_Format) {

View file

@ -25,4 +25,5 @@ namespace DXTC
void CompressImageDXT5(const FasTC::CompressionJob &);
void DecompressDXT1(const FasTC::DecompressionJob &);
void DecompressDXT5(const FasTC::DecompressionJob &);
}

View file

@ -57,11 +57,39 @@ namespace {
FasTC::Pixel *colors[4] = { &a, &b, &c, &d };
uint32 *outPixels = reinterpret_cast<uint32 *>(outBuf);
for(uint32 i = 0; i < 16; i++) {
outPixels[i] = colors[(mod >> (i*2)) & 3]->Pack();
for (uint32 i = 0; i < 16; i++) {
outPixels[i] &= 0xFF000000;
outPixels[i] |= colors[(mod >> (i * 2)) & 3]->Pack() & 0x00FFFFFF;
}
}
void DecompressDXT5Block(const uint8 *block, uint32 *outBuf) {
int alpha0 = block[0];
int alpha1 = block[1];
int palette[8];
palette[0] = alpha0;
palette[1] = alpha1;
if (alpha0 > alpha1) {
for (int i = 2; i < 8; ++i) {
palette[i] = ((8 - i) * alpha0 + (i - 1) * alpha1) / 7;
}
} else {
for (int i = 2; i < 6; ++i) {
palette[i] = ((6 - i) * alpha0 + (i - 1) * alpha1) / 5;
}
palette[6] = 0;
palette[7] = 255;
}
uint64 mod = *reinterpret_cast<const uint64 *>(block) >> 16;
uint32 *outPixels = reinterpret_cast<uint32 *>(outBuf);
for (uint32 i = 0; i < 16; i++) {
outPixels[i] &= 0x00FFFFFF;
outPixels[i] |= palette[(mod >> (i * 3)) & 7] << 24;
}
}
} // namespace
namespace DXTC
@ -95,4 +123,35 @@ namespace DXTC
}
}
}
void DecompressDXT5(const FasTC::DecompressionJob &dcj)
{
assert(!(dcj.Height() & 3));
assert(!(dcj.Width() & 3));
uint32 blockW = dcj.Width() >> 2;
uint32 blockH = dcj.Height() >> 2;
const uint32 blockSz = GetBlockSize(FasTC::eCompressionFormat_DXT5);
uint32 *outPixels = reinterpret_cast<uint32 *>(dcj.OutBuf());
uint32 outBlock[16];
memset(outBlock, 0xFF, sizeof(outBlock));
for (uint32 j = 0; j < blockH; j++) {
for (uint32 i = 0; i < blockW; i++) {
uint32 offset = (j * blockW + i) * blockSz;
DecompressDXT5Block(dcj.InBuf() + offset, outBlock);
DecompressDXT1Block(dcj.InBuf() + offset + blockSz / 2, outBlock, false);
for (uint32 y = 0; y < 4; y++)
for (uint32 x = 0; x < 4; x++) {
offset = (j * 4 + y)*dcj.Width() + ((i * 4) + x);
outPixels[offset] = outBlock[y * 4 + x];
}
}
}
}
}