From 2f8ea3dc079872cab3f25cd2a54ac71869018b6c Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Thu, 29 Sep 2016 23:48:38 -0700 Subject: [PATCH] Add DXT5 decompression, as mentioned in #21 --- CLTool/src/tc.cpp | 2 + Core/src/CompressedImage.cpp | 4 +- DXTEncoder/include/FasTC/DXTCompressor.h | 1 + DXTEncoder/src/Decompressor.cpp | 63 +++++++++++++++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/CLTool/src/tc.cpp b/CLTool/src/tc.cpp index 5bb7c75..24b8261 100644 --- a/CLTool/src/tc.cpp +++ b/CLTool/src/tc.cpp @@ -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"); } diff --git a/Core/src/CompressedImage.cpp b/Core/src/CompressedImage.cpp index c74b5de..dd5830d 100644 --- a/Core/src/CompressedImage.cpp +++ b/Core/src/CompressedImage.cpp @@ -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) { diff --git a/DXTEncoder/include/FasTC/DXTCompressor.h b/DXTEncoder/include/FasTC/DXTCompressor.h index e736a0d..52cc64f 100755 --- a/DXTEncoder/include/FasTC/DXTCompressor.h +++ b/DXTEncoder/include/FasTC/DXTCompressor.h @@ -25,4 +25,5 @@ namespace DXTC void CompressImageDXT5(const FasTC::CompressionJob &); void DecompressDXT1(const FasTC::DecompressionJob &); + void DecompressDXT5(const FasTC::DecompressionJob &); } diff --git a/DXTEncoder/src/Decompressor.cpp b/DXTEncoder/src/Decompressor.cpp index 0d58d86..1d5be4a 100644 --- a/DXTEncoder/src/Decompressor.cpp +++ b/DXTEncoder/src/Decompressor.cpp @@ -57,11 +57,39 @@ namespace { FasTC::Pixel *colors[4] = { &a, &b, &c, &d }; uint32 *outPixels = reinterpret_cast(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(block) >> 16; + uint32 *outPixels = reinterpret_cast(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(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]; + } + } + } + } }