From 264e447e8090e96c705d3d6e89a1497ab5ecb95b Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Thu, 26 Sep 2013 20:17:07 -0400 Subject: [PATCH] Deal with this bug once and for all. If we have an image in block stream order, then explicitly reorder it before doing any work. Then keep it that way. I probably could have fixed this in the amount of time I've wasted on it. -____- --- CLTool/src/clunix.cpp | 4 ++- CLTool/src/clwin32.cpp | 4 ++- Core/include/CompressedImage.h | 2 ++ Core/include/Image.h | 11 ++++++- Core/src/Image.cpp | 57 +++++++++++++++++++++++++++++++++ PVRTCEncoder/src/Compressor.cpp | 10 ++---- 6 files changed, 77 insertions(+), 11 deletions(-) diff --git a/CLTool/src/clunix.cpp b/CLTool/src/clunix.cpp index cccc264..2dd713d 100644 --- a/CLTool/src/clunix.cpp +++ b/CLTool/src/clunix.cpp @@ -206,6 +206,9 @@ int main(int argc, char **argv) { } const Image *img = file.GetImage(); + if(format == eCompressionFormat_PVRTC) { + const_cast(img)->SetBlockStreamOrder(false); + } int numBlocks = (img->GetWidth() * img->GetHeight())/16; BlockStatManager *statManager = NULL; @@ -247,7 +250,6 @@ int main(int argc, char **argv) { if(format == eCompressionFormat_BPTC) { strcat(basename, "-bc7.png"); } else if(format == eCompressionFormat_PVRTC) { - cImg.SetBlockStreamOrder(false); strcat(basename, "-pvrtc.png"); } diff --git a/CLTool/src/clwin32.cpp b/CLTool/src/clwin32.cpp index d05e12a..53057a6 100644 --- a/CLTool/src/clwin32.cpp +++ b/CLTool/src/clwin32.cpp @@ -212,6 +212,9 @@ int _tmain(int argc, _TCHAR* argv[]) } const Image *img = file.GetImage(); + if(format == eCompressionFormat_PVRTC) { + const_cast(img)->SetBlockStreamOrder(false); + } int numBlocks = (img->GetWidth() * img->GetHeight())/16; BlockStatManager *statManager = NULL; @@ -253,7 +256,6 @@ int _tmain(int argc, _TCHAR* argv[]) if(format == eCompressionFormat_BPTC) { strcat_s(basename, "-bc7.png"); } else if(format == eCompressionFormat_PVRTC) { - cImg.SetBlockStreamOrder(false); strcat_s(basename, "-pvrtc.png"); } diff --git a/Core/include/CompressedImage.h b/Core/include/CompressedImage.h index 8799d11..86021a7 100644 --- a/Core/include/CompressedImage.h +++ b/Core/include/CompressedImage.h @@ -97,6 +97,8 @@ class CompressedImage { // !FIXME! We should have a function to explicitly return the in/out buf // size for a given compressed image. bool DecompressImage(uint8 *outBuf, uint32 outBufSz) const; + + ECompressionFormat GetFormat() const { return m_Format; } }; #endif // _COMPRESSED_IMAGE_H_ diff --git a/Core/include/Image.h b/Core/include/Image.h index 7c2a35c..2ac3162 100644 --- a/Core/include/Image.h +++ b/Core/include/Image.h @@ -70,7 +70,13 @@ class Image { uint32 GetWidth() const { return m_Width; } uint32 GetHeight() const { return m_Height; } - void SetBlockStreamOrder(bool flag) { m_bBlockStreamOrder = flag; } + void SetBlockStreamOrder(bool flag) { + if(flag) { + ConvertToBlockStreamOrder(); + } else { + ConvertFromBlockStreamOrder(); + } + } bool GetBlockStreamOrder() const { return m_bBlockStreamOrder; } private: @@ -80,6 +86,9 @@ class Image { bool m_bBlockStreamOrder; uint8 *m_PixelData; + + void ConvertToBlockStreamOrder(); + void ConvertFromBlockStreamOrder(); }; #endif // __TEXCOMP_IMAGE_H__ diff --git a/Core/src/Image.cpp b/Core/src/Image.cpp index a918706..ac57763 100644 --- a/Core/src/Image.cpp +++ b/Core/src/Image.cpp @@ -117,6 +117,11 @@ Image::Image(const CompressedImage &ci) fprintf(stderr, "Error decompressing image!\n"); return; } + + // !HACK! + if(ci.GetFormat() == eCompressionFormat_PVRTC) { + m_bBlockStreamOrder = false; + } } Image::Image(const ImageLoader &loader) @@ -207,3 +212,55 @@ double Image::ComputePSNR(const CompressedImage &ci) const { delete unCompData; return PSNR; } + +void Image::ConvertToBlockStreamOrder() { + if(m_bBlockStreamOrder || !m_PixelData) + return; + + uint32 *newPixelData = new uint32[GetWidth() * GetHeight() * 4]; + for(uint32 j = 0; j < GetHeight(); j+=4) { + for(uint32 i = 0; i < GetWidth(); i+=4) { + uint32 blockX = i / 4; + uint32 blockY = j / 4; + uint32 blockIdx = blockY * (GetWidth() / 4) + blockX; + + uint32 offset = blockIdx * 4 * 4; + for(uint32 t = 0; t < 16; t++) { + uint32 x = i + t % 4; + uint32 y = j + t / 4; + newPixelData[offset + t] = + reinterpret_cast(m_PixelData)[y*GetWidth() + x]; + } + } + } + + delete m_PixelData; + m_PixelData = reinterpret_cast(newPixelData); + m_bBlockStreamOrder = true; +} + +void Image::ConvertFromBlockStreamOrder() { + if(!m_bBlockStreamOrder || !m_PixelData) + return; + + uint32 *newPixelData = new uint32[GetWidth() * GetHeight() * 4]; + for(uint32 j = 0; j < GetHeight(); j+=4) { + for(uint32 i = 0; i < GetWidth(); i+=4) { + uint32 blockX = i / 4; + uint32 blockY = j / 4; + uint32 blockIdx = blockY * (GetWidth() / 4) + blockX; + + uint32 offset = blockIdx * 4 * 4; + for(uint32 t = 0; t < 16; t++) { + uint32 x = i + t % 4; + uint32 y = j + t / 4; + newPixelData[y*GetWidth() + x] = + reinterpret_cast(m_PixelData)[offset + t]; + } + } + } + + delete m_PixelData; + m_PixelData = reinterpret_cast(newPixelData); + m_bBlockStreamOrder = false; +} diff --git a/PVRTCEncoder/src/Compressor.cpp b/PVRTCEncoder/src/Compressor.cpp index 19e1e0f..66768da 100644 --- a/PVRTCEncoder/src/Compressor.cpp +++ b/PVRTCEncoder/src/Compressor.cpp @@ -137,14 +137,8 @@ namespace PVRTCC { Image img(dcj.height, dcj.width); uint32 nPixels = dcj.height * dcj.width; for(uint32 i = 0; i < nPixels; i++) { - // Assume block stream order (whyyyy) - uint32 blockIdx = i / 16; - uint32 blockWidth = dcj.width / 4; - uint32 blockX = blockIdx % blockWidth; - uint32 blockY = blockIdx / blockWidth; - - uint32 x = blockX * 4 + (i % 4); - uint32 y = blockY * 4 + (i % 16) / 4; + uint32 x = i % dcj.width; + uint32 y = i / dcj.width; const uint32 *pixels = reinterpret_cast(dcj.inBuf); img(x, y).UnpackRGBA(pixels[i]);