diff --git a/BPTCEncoder/CMakeLists.txt b/BPTCEncoder/CMakeLists.txt index 0bbac8e..03cda9b 100644 --- a/BPTCEncoder/CMakeLists.txt +++ b/BPTCEncoder/CMakeLists.txt @@ -40,106 +40,13 @@ # # -INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Core/include) +INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/BPTCEncoder/include) INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/BPTCEncoder/include) INCLUDE(CheckCXXSourceRuns) -#SET(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) -#IF(CMAKE_COMPILER_IS_GNUCC) -# -# # Test whether or not the compiler allows inline -# # assmbly... -# CHECK_CXX_SOURCE_RUNS(" -# \#ifdef _MSC_VER -# int main() { -# int x = 1, y = 0; -# __asm { -# mov eax, x -# mov y, eax -# } -# return !y; -# } -# \#else -# int main() { -# int x = 1, y = 0; -# __asm__ (\"movl %1, %%eax;\" -# \"movl %%eax, %0;\" -# :\"=r\"(y) /* output */ -# :\"r\"(x) /* input */ -# :\"%eax\" /* clobbered register */ -# ); -# -# return !y; -# } -# \#endif" -# HAS_INLINE_ASSEMBLY -# ) -# -# # If the compiler doesn't allow it, then try with a -# # compiler flag... -# IF( NOT HAS_INLINE_ASSEMBLY ) -# SET(CMAKE_REQUIRED_FLAGS -fasm-blocks) -# CHECK_CXX_SOURCE_RUNS(" -# \#ifdef _MSC_VER -# int main() { -# int x = 1, y = 0; -# __asm { -# mov eax, x -# mov y, eax -# } -# return !y; -# } -# \#else -# int main() { -# int x = 1, y = 0; -# __asm__ (\"movl %1, %%eax;\" -# \"movl %%eax, %0;\" -# :\"=r\"(y) /* output */ -# :\"r\"(x) /* input */ -# :\"%eax\" /* clobbered register */ -# ); -# -# return !y; -# } -# \#endif" -# HAS_INLINE_ASSEMBLY_WITH_FLAGS -# ) -# ENDIF() -# -# SET(CMAKE_REQUIRED_FLAGS -msse4.1) -# CHECK_CXX_SOURCE_RUNS(" -# #include -# int main() { -# const __m128 fv = _mm_set1_ps(1.0f); -# const __m128 fv2 = _mm_set1_ps(2.0f); -# -# const __m128 ans = _mm_blend_ps(fv, fv2, 2); -# -# return ((int *)(&ans))[0]; -# }" -# HAS_SSE_41 -# ) -# -# IF(HAS_SSE_41) -# SET(CMAKE_REQUIRED_FLAGS -msse4.2) -# CHECK_CXX_SOURCE_RUNS(" -# #include -# int main() { -# const unsigned int testMe = 5; -# return !(2 == _mm_popcnt_u32(testMe)); -# }" -# HAS_SSE_POPCNT -# ) -# ENDIF(HAS_SSE_41) -# -#ELSEIF(MSVC) -##!FIXME! -#ENDIF() -#SET(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) - IF( NOT HAS_INLINE_ASSEMBLY AND NOT HAS_INLINE_ASSEMBLY_WITH_FLAGS ) SET( NO_INLINE_ASSEMBLY true ) ENDIF() @@ -178,55 +85,56 @@ ELSEIF( MSVC ) ) ENDIF() + IF( HAS_MSVC_ATOMICS OR HAS_GCC_ATOMICS ) SET(HAS_ATOMICS true) ENDIF() CONFIGURE_FILE( - "config/BC7Config.h.in" - "include/BC7Config.h" + "config/BC7Config.h.in" + "include/BC7Config.h" ) SET( HEADERS - src/BC7CompressionMode.h - src/BitStream.h - src/RGBAEndpoints.h + src/BC7CompressionMode.h + src/BitStream.h + src/RGBAEndpoints.h src/ParallelStage.h ) SET( SOURCES - src/BC7Compressor.cpp - src/RGBAEndpoints.cpp + src/BC7Compressor.cpp + src/RGBAEndpoints.cpp src/ParallelStage.cpp ) IF( HAS_SSE_41 ) - IF ( HAS_SSE_POPCNT ) - IF( MSVC ) - ADD_DEFINITIONS( /arch:SSE4.2 ) - ELSE() #Assume GCC - ADD_DEFINITIONS( -msse4.2 ) - ENDIF() - ELSE() - IF( MSVC ) - ADD_DEFINITIONS( /arch:SSE4.1 ) - ELSE() #Assume GCC - ADD_DEFINITIONS( -msse4.1 ) - ENDIF() + IF ( HAS_SSE_POPCNT ) + IF( MSVC ) + ADD_DEFINITIONS( /arch:SSE4.2 ) + ELSE() #Assume GCC + ADD_DEFINITIONS( -msse4.2 ) ENDIF() + ELSE() + IF( MSVC ) + ADD_DEFINITIONS( /arch:SSE4.1 ) + ELSE() #Assume GCC + ADD_DEFINITIONS( -msse4.1 ) + ENDIF() + ENDIF() - SET( HEADERS - ${HEADERS} - src/RGBAEndpointsSIMD.h - src/BC7CompressionModeSIMD.h - ) + SET( HEADERS + ${HEADERS} + src/RGBAEndpointsSIMD.h + src/BC7CompressionModeSIMD.h + ) - SET( SOURCES - ${SOURCES} - src/BC7CompressorSIMD.cpp - src/RGBAEndpointsSIMD.cpp - ) + SET( SOURCES + ${SOURCES} + src/BC7CompressorSIMD.cpp + src/RGBAEndpointsSIMD.cpp + ) ENDIF( HAS_SSE_41 ) IF( HAS_INLINE_ASSEMBLY_WITH_FLAGS ) @@ -238,6 +146,8 @@ IF( HAS_INLINE_ASSEMBLY_WITH_FLAGS ) ENDIF() ADD_LIBRARY( BPTCEncoder - ${HEADERS} - ${SOURCES} + ${HEADERS} + ${SOURCES} ) + +TARGET_LINK_LIBRARIES( BPTCEncoder FasTCBase ) \ No newline at end of file diff --git a/BPTCEncoder/include/BC7Compressor.h b/BPTCEncoder/include/BC7Compressor.h index e216f07..b77aba0 100755 --- a/BPTCEncoder/include/BC7Compressor.h +++ b/BPTCEncoder/include/BC7Compressor.h @@ -79,7 +79,7 @@ #include "BC7Config.h" #include "CompressionJob.h" -class BlockStatManager; +#include namespace BC7C { // This is the error metric that is applied to our error measurement algorithm @@ -120,7 +120,7 @@ namespace BC7C { // made into a list of statistics. We can use this to see whether or not // certain heuristics are working, such as whether or not certain modes are // being chosen more often than others, etc. - void CompressWithStats(const CompressionJob &, BlockStatManager &statManager); + void CompressWithStats(const CompressionJob &, std::ostream *logStream); #ifdef HAS_SSE_41 // Compress the image given as RGBA data to BC7 format using an algorithm diff --git a/BPTCEncoder/src/BC7Compressor.cpp b/BPTCEncoder/src/BC7Compressor.cpp index 1a490ab..5013cee 100755 --- a/BPTCEncoder/src/BC7Compressor.cpp +++ b/BPTCEncoder/src/BC7Compressor.cpp @@ -76,14 +76,11 @@ #include "BC7Compressor.h" #include "BC7CompressionMode.h" -#include "TexComp.h" #include "TexCompTypes.h" #include "BCLookupTables.h" #include "RGBAEndpoints.h" #include "BitStream.h" -#include "BlockStats.h" - #ifdef HAS_MSVC_ATOMICS # include "Windows.h" #endif @@ -100,6 +97,7 @@ #include #include #include +#include // #define USE_PCA_FOR_SHAPE_ESTIMATION @@ -1543,10 +1541,27 @@ namespace BC7C { const float *GetErrorMetric() { return kErrorMetrics[GetErrorMetricEnum()]; } ErrorMetric GetErrorMetricEnum() { return gErrorMetric; } + class BlockLogger { + public: + BlockLogger(uint32 blockIdx, std::ostream &os) + : m_BlockIdx(blockIdx), m_Stream(os) { } + + template + friend std::ostream &operator<<(const BlockLogger &bl, const T &v); + + uint32 m_BlockIdx; + std::ostream &m_Stream; + }; + + template + std::ostream &operator<<(const BlockLogger &bl, const T &v) { + return bl.m_Stream << bl.m_BlockIdx << ": " << v; + } + // Function prototypes static void CompressBC7Block(const uint32 *block, uint8 *outBuf); static void CompressBC7Block( - const uint32 *block, uint8 *outBuf, BlockStatManager &statManager + const uint32 *block, uint8 *outBuf, const BlockLogger &logStream ); static int gQualityLevel = 50; @@ -1710,17 +1725,20 @@ namespace BC7C { } #endif // HAS_ATOMICS - void CompressWithStats( - const CompressionJob &cj, - BlockStatManager &statManager - ) { + void CompressWithStats(const CompressionJob &cj, std::ostream *logStream) { const unsigned char *inBuf = cj.inBuf; unsigned char *outBuf = cj.outBuf; for(uint32 j = 0; j < cj.height; j += 4) { for(uint32 i = 0; i < cj.width; i += 4) { - CompressBC7Block((const uint32 *)inBuf, outBuf, statManager); + const uint32 *pixelBuf = reinterpret_cast(inBuf); + if(logStream) { + uint32 blockIdx = (j/4) * (cj.width/4) + (i/4); + CompressBC7Block(pixelBuf, outBuf, BlockLogger(blockIdx, *logStream)); + } else { + CompressBC7Block(pixelBuf, outBuf); + } #ifndef NDEBUG uint8 *block = outBuf; @@ -2203,23 +2221,27 @@ namespace BC7C { } } + template + static void PrintStat(const BlockLogger &lgr, const char *stat, const T &v) { + lgr << stat << " -- " << v << std::endl; + } + // Compress a single block but collect statistics as well... static void CompressBC7Block( - const uint32 *block, uint8 *outBuf, BlockStatManager &statManager + const uint32 *block, uint8 *outBuf, const BlockLogger &logStream ) { class RAIIStatSaver { private: - uint32 m_BlockIdx; - BlockStatManager &m_BSM; + const BlockLogger &m_Logger; int *m_ModePtr; double *m_Estimates; double *m_Errors; public: - RAIIStatSaver(uint32 blockIdx, BlockStatManager &m) - : m_BlockIdx(blockIdx), m_BSM(m) + RAIIStatSaver(const BlockLogger &logger) + : m_Logger(logger) , m_ModePtr(NULL), m_Estimates(NULL), m_Errors(NULL) { } void SetMode(int *modePtr) { m_ModePtr = modePtr; } void SetEstimates(double *estimates) { m_Estimates = estimates; } @@ -2231,20 +2253,16 @@ namespace BC7C { assert(m_Estimates); assert(m_Errors); - BlockStat s (kBlockStatString[eBlockStat_Mode], *m_ModePtr); - m_BSM.AddStat(m_BlockIdx, s); + PrintStat(m_Logger, kBlockStatString[eBlockStat_Mode], *m_ModePtr); for(uint32 i = 0; i < BC7CompressionMode::kNumModes; i++) { - s = BlockStat( - kBlockStatString[eBlockStat_ModeZeroEstimate + i], m_Estimates[i] - ); - m_BSM.AddStat(m_BlockIdx, s); - - s = BlockStat( - kBlockStatString[eBlockStat_ModeZeroError + i], m_Errors[i] - ); - m_BSM.AddStat(m_BlockIdx, s); + PrintStat(m_Logger, + kBlockStatString[eBlockStat_ModeZeroEstimate + i], + m_Estimates[i]); + PrintStat(m_Logger, + kBlockStatString[eBlockStat_ModeZeroError + i], + m_Errors[i]); } } }; @@ -2259,12 +2277,7 @@ namespace BC7C { modeError[i] = modeEstimate[i] = -1.0; } - uint32 blockIdx = statManager.BeginBlock(); - for(int i = 0; i < kNumBlockStats; i++) { - statManager.AddStat(blockIdx, BlockStat(kBlockStatString[i], 0)); - } - - RAIIStatSaver __statsaver__(blockIdx, statManager); + RAIIStatSaver __statsaver__(logStream); __statsaver__.SetMode(&bestMode); __statsaver__.SetEstimates(modeEstimate); __statsaver__.SetErrors(modeError); @@ -2275,9 +2288,7 @@ namespace BC7C { CompressOptimalColorBC7(*block, bStrm); bestMode = 5; - BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 0); - statManager.AddStat(blockIdx, s); - + PrintStat(logStream, kBlockStatString[eBlockStat_Path], 0); return; } @@ -2303,9 +2314,7 @@ namespace BC7C { WriteTransparentBlock(bStrm); bestMode = 6; - BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 1); - statManager.AddStat(blockIdx, s); - + PrintStat(logStream, kBlockStatString[eBlockStat_Path], 1); return; } @@ -2334,8 +2343,7 @@ namespace BC7C { error = 1.0; } - BlockStat s (kBlockStatString[eBlockStat_SingleShapeEstimate], error); - statManager.AddStat(blockIdx, s); + PrintStream(logStream, kBlockStatString[eBlockStat_SingleShapeEstimate], error); #endif } } @@ -2380,10 +2388,9 @@ namespace BC7C { } if(err < bestError[0]) { - BlockStat s = BlockStat( + PrintStat(logStream, kBlockStatString[eBlockStat_TwoShapeEstimate], err ); - statManager.AddStat(blockIdx, s); } // If it's small, we'll take it! @@ -2394,8 +2401,7 @@ namespace BC7C { ); bestMode = modeChosen; - BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 2); - statManager.AddStat(blockIdx, s); + PrintStat(logStream, kBlockStatString[eBlockStat_Path], 2); return; } @@ -2445,10 +2451,9 @@ namespace BC7C { } if(err < bestError[1]) { - BlockStat s = BlockStat( + PrintStat(logStream, kBlockStatString[eBlockStat_ThreeShapeEstimate], err ); - statManager.AddStat(blockIdx, s); } // If it's small, we'll take it! @@ -2459,9 +2464,7 @@ namespace BC7C { ); bestMode = modeChosen; - BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 2); - statManager.AddStat(blockIdx, s); - + PrintStat(logStream, kBlockStatString[eBlockStat_Path], 2); return; } @@ -2475,8 +2478,7 @@ namespace BC7C { } } - BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 3); - statManager.AddStat(blockIdx, s); + PrintStat(logStream, kBlockStatString[eBlockStat_Path], 3); uint8 tempBuf1[16], tempBuf2[16]; diff --git a/Base/CMakeLists.txt b/Base/CMakeLists.txt new file mode 100644 index 0000000..53fb033 --- /dev/null +++ b/Base/CMakeLists.txt @@ -0,0 +1,72 @@ +# FasTC +# Copyright (c) 2013 University of North Carolina at Chapel Hill. +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for educational, research, and non-profit purposes, without +# fee, and without a written agreement is hereby granted, provided that the +# above copyright notice, this paragraph, and the following four paragraphs +# appear in all copies. +# +# Permission to incorporate this software into commercial products may be +# obtained by contacting the authors or the Office of Technology Development +# at the University of North Carolina at Chapel Hill . +# +# This software program and documentation are copyrighted by the University of +# North Carolina at Chapel Hill. The software program and documentation are +# supplied "as is," without any accompanying services from the University of +# North Carolina at Chapel Hill or the authors. The University of North +# Carolina at Chapel Hill and the authors do not warrant that the operation of +# the program will be uninterrupted or error-free. The end-user understands +# that the program was developed for research purposes and is advised not to +# rely exclusively on the program for any reason. +# +# IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE +# AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, +# OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF +# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA +# AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY +# DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY +# STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON +# AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND +# THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +# ENHANCEMENTS, OR MODIFICATIONS. +# +# Please send all BUG REPORTS to . +# +# The authors may be contacted via: +# +# Pavel Krajcevski +# Dept of Computer Science +# 201 S Columbia St +# Frederick P. Brooks, Jr. Computer Science Bldg +# Chapel Hill, NC 27599-3175 +# USA +# +# + +SET( SOURCES + "src/Image.cpp" + "src/CompressionJob.cpp" +) + +SET( HEADERS + "include/TexCompTypes.h" + "include/Image.h" + "include/CompressionJob.h" +) + +INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) + +ADD_LIBRARY( FasTCBase + ${HEADERS} + ${SOURCES} +) + +IF( NOT WIN32 AND NOT APPLE ) + TARGET_LINK_LIBRARIES( FasTCBase rt ) +ENDIF() diff --git a/Core/include/CompressionJob.h b/Base/include/CompressionJob.h similarity index 100% rename from Core/include/CompressionJob.h rename to Base/include/CompressionJob.h diff --git a/Core/include/Image.h b/Base/include/Image.h similarity index 89% rename from Core/include/Image.h rename to Base/include/Image.h index 7c2a35c..c8a5d25 100644 --- a/Core/include/Image.h +++ b/Base/include/Image.h @@ -45,27 +45,17 @@ #define __TEXCOMP_IMAGE_H__ #include "TexCompTypes.h" -#include "TexComp.h" - -// Forward declarations -class ImageLoader; // Class definition class Image { public: - Image(const CompressedImage &); - Image(const ImageLoader &); Image(uint32 width, uint32 height, const uint32 *pixels); - ~Image(); - Image(const Image &); Image &operator=(const Image &); + virtual ~Image(); - const uint8 *RawData() const { return m_PixelData; } - - CompressedImage *Compress(const SCompressionSettings &settings) const; - double ComputePSNR(const CompressedImage &ci) const; + const uint8 *RawData() const { return m_Data; } uint32 GetWidth() const { return m_Width; } uint32 GetHeight() const { return m_Height; } @@ -73,13 +63,21 @@ class Image { void SetBlockStreamOrder(bool flag) { m_bBlockStreamOrder = flag; } bool GetBlockStreamOrder() const { return m_bBlockStreamOrder; } + double ComputePSNR(Image *other); + + virtual void ComputeRGBA() { } + virtual const uint32 *GetRGBA() const { + return reinterpret_cast(RawData()); + } + private: uint32 m_Width; uint32 m_Height; bool m_bBlockStreamOrder; - uint8 *m_PixelData; + protected: + uint8 *m_Data; }; #endif // __TEXCOMP_IMAGE_H__ diff --git a/Core/include/TexCompTypes.h b/Base/include/TexCompTypes.h similarity index 100% rename from Core/include/TexCompTypes.h rename to Base/include/TexCompTypes.h diff --git a/Core/src/CompressionJob.cpp b/Base/src/CompressionJob.cpp similarity index 100% rename from Core/src/CompressionJob.cpp rename to Base/src/CompressionJob.cpp diff --git a/Core/src/Image.cpp b/Base/src/Image.cpp similarity index 52% rename from Core/src/Image.cpp rename to Base/src/Image.cpp index c1284cf..c082c77 100644 --- a/Core/src/Image.cpp +++ b/Base/src/Image.cpp @@ -42,13 +42,12 @@ */ #include "Image.h" -#include "ImageLoader.h" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include template static inline T sad( const T &a, const T &b ) { @@ -59,12 +58,11 @@ Image::Image(const Image &other) : m_Width(other.m_Width) , m_Height(other.m_Height) , m_bBlockStreamOrder(other.GetBlockStreamOrder()) - , m_PixelData(new uint8[m_Width * m_Height * 4]) + , m_Data(new uint8[m_Width * m_Height * 4]) { - if(m_PixelData) { - memcpy(m_PixelData, other.m_PixelData, m_Width * m_Height * 4); - } - else { + if(m_Data) { + memcpy(m_Data, other.m_Data, m_Width * m_Height * 4); + } else { fprintf(stderr, "Out of memory!\n"); } } @@ -73,10 +71,13 @@ Image::Image(uint32 width, uint32 height, const uint32 *pixels) : m_Width(width) , m_Height(height) , m_bBlockStreamOrder(false) - , m_PixelData(new uint8[4 * m_Width * m_Height]) { - if(m_PixelData && pixels) - memcpy(m_PixelData, pixels, m_Width * m_Height * sizeof(uint32)); + if(pixels) { + m_Data = new uint8[4 * m_Width * m_Height]; + memcpy(m_Data, pixels, m_Width * m_Height * sizeof(uint32)); + } else { + m_Data = NULL; + } } @@ -86,110 +87,68 @@ Image &Image::operator=(const Image &other) { m_Height = other.m_Height; m_bBlockStreamOrder = other.GetBlockStreamOrder(); - if(m_PixelData) { - delete [] m_PixelData; + if(m_Data) { + delete [] m_Data; } - if(other.m_PixelData) { - m_PixelData = new uint8[m_Width * m_Height * 4]; - if(m_PixelData) - memcpy(m_PixelData, other.m_PixelData, m_Width * m_Height * 4); + if(other.m_Data) { + m_Data = new uint8[m_Width * m_Height * 4]; + if(m_Data) + memcpy(m_Data, other.m_Data, m_Width * m_Height * 4); else fprintf(stderr, "Out of memory!\n"); } else { - m_PixelData = other.m_PixelData; + m_Data = other.m_Data; } return *this; } -Image::Image(const CompressedImage &ci) - : m_Width(ci.GetWidth()) - , m_Height(ci.GetHeight()) - , m_bBlockStreamOrder(true) -{ - unsigned int bufSz = ci.GetWidth() * ci.GetHeight() * 4; - m_PixelData = new uint8[ bufSz ]; - if(!m_PixelData) { fprintf(stderr, "%s\n", "Out of memory!"); return; } - - if(!ci.DecompressImage(m_PixelData, bufSz)) { - fprintf(stderr, "Error decompressing image!\n"); - return; - } -} - -Image::Image(const ImageLoader &loader) - : m_Width(loader.GetWidth()) - , m_Height(loader.GetHeight()) - , m_bBlockStreamOrder(true) - , m_PixelData(0) -{ - if(loader.GetImageData()) { - m_PixelData = new uint8[ loader.GetImageDataSz() ]; - if(!m_PixelData) { fprintf(stderr, "%s\n", "Out of memory!"); return; } - memcpy(m_PixelData, loader.GetImageData(), loader.GetImageDataSz()); - } - else { - fprintf(stderr, "%s\n", "Failed to get data from image loader!"); - } -} - Image::~Image() { - if(m_PixelData) { - delete [] m_PixelData; - m_PixelData = 0; + if(m_Data) { + delete [] m_Data; + m_Data = 0; } } -CompressedImage *Image::Compress(const SCompressionSettings &settings) const { - CompressedImage *outImg = NULL; - const unsigned int dataSz = GetWidth() * GetHeight() * 4; +double Image::ComputePSNR(Image *other) { + if(!other) + return -1.0; - assert(dataSz > 0); - - // Allocate data based on the compression method - int cmpDataSz = 0; - switch(settings.format) { - default: assert(!"Not implemented!"); // Fall Through V - case eCompressionFormat_DXT1: cmpDataSz = dataSz / 8; break; - case eCompressionFormat_DXT5: cmpDataSz = dataSz / 4; break; - case eCompressionFormat_BPTC: cmpDataSz = dataSz / 4; break; + if(other->GetWidth() != GetWidth() || + other->GetHeight() != GetHeight()) { + return -1.0; } - unsigned char *cmpData = new unsigned char[cmpDataSz]; - CompressImageData(m_PixelData, dataSz, cmpData, cmpDataSz, settings); + // Compute raw 8-bit RGBA data... + other->ComputeRGBA(); + ComputeRGBA(); - outImg = new CompressedImage(GetWidth(), GetHeight(), settings.format, cmpData); - - delete [] cmpData; - return outImg; -} - -double Image::ComputePSNR(const CompressedImage &ci) const { - unsigned int imageSz = 4 * GetWidth() * GetHeight(); - unsigned char *unCompData = new unsigned char[imageSz]; - if(!(ci.DecompressImage(unCompData, imageSz))) { - fprintf(stderr, "%s\n", "Failed to decompress image."); - delete [] unCompData; - return -1.0f; - } + const uint8 *ourData = + reinterpret_cast(GetRGBA()); + const uint8 *otherData = + reinterpret_cast(other->GetRGBA()); const double wr = 1.0; const double wg = 1.0; const double wb = 1.0; double MSE = 0.0; + const uint32 imageSz = GetWidth() * GetHeight() * 4; for(uint32 i = 0; i < imageSz; i+=4) { - const unsigned char *pixelDataRaw = m_PixelData + i; - const unsigned char *pixelDataUncomp = unCompData + i; + const unsigned char *ourPixel = ourData + i; + const unsigned char *otherPixel = otherData + i; - double rawAlphaScale = double(pixelDataRaw[3]) / 255.0; - double uncompAlphaScale = double(pixelDataUncomp[3]) / 255.0; - double dr = double(sad(rawAlphaScale * pixelDataRaw[0], uncompAlphaScale * pixelDataUncomp[0])) * wr; - double dg = double(sad(rawAlphaScale * pixelDataRaw[1], uncompAlphaScale * pixelDataUncomp[1])) * wg; - double db = double(sad(rawAlphaScale * pixelDataRaw[2], uncompAlphaScale * pixelDataUncomp[2])) * wb; + double ourAlphaScale = double(ourPixel[3]) / 255.0; + double otherAlphaScale = double(otherPixel[3]) / 255.0; + double dr = double(sad(ourAlphaScale * ourPixel[0], + otherAlphaScale * otherPixel[0])) * wr; + double dg = double(sad(ourAlphaScale * ourPixel[1], + otherAlphaScale * otherPixel[1])) * wg; + double db = double(sad(ourAlphaScale * ourPixel[2], + otherAlphaScale * otherPixel[2])) * wb; const double pixelMSE = (double(dr) * double(dr)) + @@ -208,8 +167,5 @@ double Image::ComputePSNR(const CompressedImage &ci) const { (255.0 * wb) * (255.0 * wb); double PSNR = 10 * log10(MAXI/MSE); - - // Cleanup - delete unCompData; return PSNR; } diff --git a/CLTool/CMakeLists.txt b/CLTool/CMakeLists.txt index 4980eb7..e325c4f 100644 --- a/CLTool/CMakeLists.txt +++ b/CLTool/CMakeLists.txt @@ -46,6 +46,7 @@ ELSE() SET( SOURCES "src/clunix.cpp" ) ENDIF() +INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Base/include ) INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Core/include ) INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/IO/include ) @@ -61,5 +62,6 @@ IF( MSVC ) ENDIF() TARGET_LINK_LIBRARIES( tc BPTCEncoder ) +TARGET_LINK_LIBRARIES( tc FasTCBase ) TARGET_LINK_LIBRARIES( tc FasTCIO ) TARGET_LINK_LIBRARIES( tc FasTCCore ) diff --git a/CLTool/src/clunix.cpp b/CLTool/src/clunix.cpp index aa39d52..2ed560f 100644 --- a/CLTool/src/clunix.cpp +++ b/CLTool/src/clunix.cpp @@ -186,9 +186,9 @@ int main(int argc, char **argv) { return 1; } - const Image *img = file.GetImage(); + Image img = Image(*file.GetImage()); - int numBlocks = (img->GetWidth() * img->GetHeight())/16; + int numBlocks = (img.GetWidth() * img.GetHeight())/16; BlockStatManager *statManager = NULL; if(bSaveLog) { statManager = new BlockStatManager(numBlocks); @@ -203,13 +203,13 @@ int main(int argc, char **argv) { settings.iJobSize = numJobs; settings.pStatManager = statManager; - CompressedImage *ci = img->Compress(settings); + CompressedImage *ci = CompressImage(&img, settings); if(NULL == ci) { fprintf(stderr, "Error compressing image!\n"); return 1; } - double PSNR = img->ComputePSNR(*ci); + double PSNR = img.ComputePSNR(ci); if(PSNR > 0.0) { fprintf(stdout, "PSNR: %.3f\n", PSNR); } @@ -223,7 +223,7 @@ int main(int argc, char **argv) { statManager->ToFile(logname); } - Image cImg (*ci); + Image cImg(*ci); ImageFile cImgFile (strcat(basename, "-bc7.png"), eFileFormat_PNG, cImg); cImgFile.Write(); diff --git a/CMakeLists.txt b/CMakeLists.txt index 10278be..63f5b30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,7 @@ SET(CMAKE_MODULE_PATH "${FasTC_SOURCE_DIR}/CMakeModules" ${CMAKE_MODULE_PATH}) FIND_PACKAGE(PVRTexLib) SET(FASTC_DIRECTORIES - BPTCEncoder PVRTCEncoder IO Core + BPTCEncoder PVRTCEncoder IO Core Base ) FOREACH(DIR ${FASTC_DIRECTORIES}) diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 0e33516..a532b4c 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -1,30 +1,39 @@ # FasTC -# Copyright (c) 2012 University of North Carolina at Chapel Hill. All rights reserved. +# Copyright (c) 2013 University of North Carolina at Chapel Hill. +# All rights reserved. # -# Permission to use, copy, modify, and distribute this software and its documentation for educational, -# research, and non-profit purposes, without fee, and without a written agreement is hereby granted, -# provided that the above copyright notice, this paragraph, and the following four paragraphs appear -# in all copies. +# Permission to use, copy, modify, and distribute this software and its +# documentation for educational, research, and non-profit purposes, without +# fee, and without a written agreement is hereby granted, provided that the +# above copyright notice, this paragraph, and the following four paragraphs +# appear in all copies. # -# Permission to incorporate this software into commercial products may be obtained by contacting the -# authors or the Office of Technology Development at the University of North Carolina at Chapel Hill . +# Permission to incorporate this software into commercial products may be +# obtained by contacting the authors or the Office of Technology Development +# at the University of North Carolina at Chapel Hill . # -# This software program and documentation are copyrighted by the University of North Carolina at Chapel Hill. -# The software program and documentation are supplied "as is," without any accompanying services from the -# University of North Carolina at Chapel Hill or the authors. The University of North Carolina at Chapel Hill -# and the authors do not warrant that the operation of the program will be uninterrupted or error-free. The -# end-user understands that the program was developed for research purposes and is advised not to rely -# exclusively on the program for any reason. +# This software program and documentation are copyrighted by the University of +# North Carolina at Chapel Hill. The software program and documentation are +# supplied "as is," without any accompanying services from the University of +# North Carolina at Chapel Hill or the authors. The University of North +# Carolina at Chapel Hill and the authors do not warrant that the operation of +# the program will be uninterrupted or error-free. The end-user understands +# that the program was developed for research purposes and is advised not to +# rely exclusively on the program for any reason. # -# IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE AUTHORS BE LIABLE TO ANY PARTY FOR -# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE -# USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE -# AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE +# AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, +# OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF +# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA +# AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. # -# THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, -# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY -# STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY -# OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +# THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY +# DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY +# STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON +# AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND +# THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, # ENHANCEMENTS, OR MODIFICATIONS. # # Please send all BUG REPORTS to . @@ -43,18 +52,14 @@ SET( SOURCES "src/TexComp.cpp" "src/CompressedImage.cpp" - "src/Image.cpp" "src/BlockStats.cpp" - "src/CompressionJob.cpp" ) SET( HEADERS "include/TexComp.h" "include/CompressedImage.h" - "include/TexCompTypes.h" - "include/Image.h" "include/BlockStats.h" - "include/CompressionJob.h" + "src/CompressionFuncs.h" ) # Make sure to add the appropriate stopwatch files... @@ -71,6 +76,8 @@ ELSE() SET( LINK_FLAGS -lrt ${LINK_FLAGS} ) ENDIF() +INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Base/include ) + INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/BPTCEncoder/include ) INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/BPTCEncoder/include ) @@ -85,8 +92,8 @@ SET( THREAD_APIS_AVAILABLE "None" ) ###### Find Boost... IF( MSVC ) - SET(ENV{BOOSTLIBDIR} "${MSVC_LIB_DIR}") - SET(ENV{BOOSTINCLUDEDIR} "${MSVC_INSTALL_PATH}/include") + SET(ENV{BOOSTLIBDIR} "${MSVC_LIB_DIR}") + SET(ENV{BOOSTINCLUDEDIR} "${MSVC_INSTALL_PATH}/include") ENDIF( MSVC ) SET( Boost_USE_STATIC_LIBS ON ) @@ -147,6 +154,7 @@ ADD_LIBRARY( FasTCCore ${SOURCES} ) +TARGET_LINK_LIBRARIES( FasTCCore FasTCBase ) TARGET_LINK_LIBRARIES( FasTCCore FasTCIO ) TARGET_LINK_LIBRARIES( FasTCCore BPTCEncoder ) diff --git a/Core/include/BlockStats.h b/Core/include/BlockStats.h index ebb997c..b7f68dd 100644 --- a/Core/include/BlockStats.h +++ b/Core/include/BlockStats.h @@ -1,30 +1,39 @@ /* FasTC - * Copyright (c) 2012 University of North Carolina at Chapel Hill. All rights reserved. + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. * - * Permission to use, copy, modify, and distribute this software and its documentation for educational, - * research, and non-profit purposes, without fee, and without a written agreement is hereby granted, - * provided that the above copyright notice, this paragraph, and the following four paragraphs appear - * in all copies. + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. * - * Permission to incorporate this software into commercial products may be obtained by contacting the - * authors or the Office of Technology Development at the University of North Carolina at Chapel Hill . + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . * - * This software program and documentation are copyrighted by the University of North Carolina at Chapel Hill. - * The software program and documentation are supplied "as is," without any accompanying services from the - * University of North Carolina at Chapel Hill or the authors. The University of North Carolina at Chapel Hill - * and the authors do not warrant that the operation of the program will be uninterrupted or error-free. The - * end-user understands that the program was developed for research purposes and is advised not to rely - * exclusively on the program for any reason. + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. * - * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE AUTHORS BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE - * USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE - * AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. * - * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY - * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY - * OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. * * Please send all BUG REPORTS to . diff --git a/Core/include/CompressedImage.h b/Core/include/CompressedImage.h index 831a50c..016df4d 100644 --- a/Core/include/CompressedImage.h +++ b/Core/include/CompressedImage.h @@ -52,16 +52,14 @@ enum ECompressionFormat { kNumCompressionFormats }; -class CompressedImage { +#include "Image.h" + +class CompressedImage : public Image { private: - unsigned int m_Width; - unsigned int m_Height; - ECompressionFormat m_Format; - - unsigned char *m_Data; - unsigned int m_DataSz; + uint32 m_DataSz; + uint32 *m_RGBAData; void InitData(const unsigned char *withData); public: @@ -77,11 +75,11 @@ class CompressedImage { const unsigned char *data ); - unsigned int GetHeight() const { return m_Height; } - unsigned int GetWidth() const { return m_Width; } - CompressedImage( const CompressedImage &other ); - ~CompressedImage(); + virtual ~CompressedImage(); + + virtual void ComputeRGBA(); + virtual const uint32 *GetRGBA() const { return m_RGBAData; } // Decompress the compressed image data into outBuf. outBufSz is expected // to be the proper size determined by the width, height, and format. diff --git a/Core/include/TexComp.h b/Core/include/TexComp.h index 1ad8c84..b2c7a87 100644 --- a/Core/include/TexComp.h +++ b/Core/include/TexComp.h @@ -48,6 +48,7 @@ #include "CompressionJob.h" // Forward declarations +class Image; class ImageFile; class BlockStatManager; @@ -91,6 +92,8 @@ struct SCompressionSettings { BlockStatManager *pStatManager; }; +extern CompressedImage *CompressImage(Image *img, const SCompressionSettings &settings); + extern bool CompressImageData( const unsigned char *data, const unsigned int dataSz, @@ -99,18 +102,6 @@ extern bool CompressImageData( const SCompressionSettings &settings ); -// A compression function format. It takes the raw data and image dimensions and -// returns the compressed image data into outData. It is assumed that there is -// enough space allocated for outData to store the compressed data. Allocation -// is dependent on the compression format. -typedef void (* CompressionFunc)(const CompressionJob &); - -// A compression function format. It takes the raw data and image dimensions and -// returns the compressed image data into outData. It is assumed that there is -// enough space allocated for outData to store the compressed data. Allocation -// is dependent on the compression format. -typedef void (* CompressionFuncWithStats)(const CompressionJob &, BlockStatManager &statManager); - // This function computes the Peak Signal to Noise Ratio between a // compressed image and a raw image. extern double ComputePSNR(const CompressedImage &ci, const ImageFile &file); diff --git a/Core/src/CompressedImage.cpp b/Core/src/CompressedImage.cpp index 0f4f393..a0f250d 100644 --- a/Core/src/CompressedImage.cpp +++ b/Core/src/CompressedImage.cpp @@ -51,19 +51,10 @@ #include "TexCompTypes.h" #include "BC7Compressor.h" -CompressedImage::CompressedImage() - : m_Width(0) - , m_Height(0) - , m_Format(ECompressionFormat(-1)) - , m_Data(0) - , m_DataSz(0) -{ } - CompressedImage::CompressedImage( const CompressedImage &other ) - : m_Width(other.m_Width) - , m_Height(other.m_Height) + : Image(other) , m_Format(other.m_Format) - , m_Data(0) + , m_RGBAData(0) , m_DataSz(0) { InitData(other.m_Data); @@ -74,11 +65,10 @@ CompressedImage::CompressedImage( const unsigned int height, const ECompressionFormat format, const unsigned char *data -) - : m_Width(width) - , m_Height(height) +) + : Image(width, height, NULL) , m_Format(format) - , m_Data(0) + , m_RGBAData(0) , m_DataSz(0) { InitData(data); @@ -86,7 +76,7 @@ CompressedImage::CompressedImage( void CompressedImage::InitData(const unsigned char *withData) { m_DataSz = 0; - int uncompDataSz = m_Width * m_Height * 4; + int uncompDataSz = GetWidth() * GetHeight() * 4; switch(m_Format) { default: assert(!"Not implemented!"); // Fall through V @@ -122,23 +112,37 @@ bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBuf if(dataSz > outBufSz) { fprintf(stderr, "Not enough space to store entire decompressed image! " "Got %d bytes, but need %d!\n", outBufSz, dataSz); + assert(false); return false; } + DecompressionJob dj (m_Data, outBuf, GetWidth(), GetHeight()); switch(m_Format) { - case eCompressionFormat_BPTC: + case eCompressionFormat_BPTC: { - DecompressionJob dj (m_Data, outBuf, m_Width, m_Height); BC7C::Decompress(dj); } break; - default: - const char *errStr = "Have not implemented decompression method."; - fprintf(stderr, "%s\n", errStr); - assert(!errStr); + default: + { + const char *errStr = "Have not implemented decompression method."; + fprintf(stderr, "%s\n", errStr); + assert(!errStr); + } return false; } return true; } + +void CompressedImage::ComputeRGBA() { + + if(m_RGBAData) { + delete m_RGBAData; + } + m_RGBAData = new uint32[GetWidth() * GetHeight()]; + + uint8 *pixelData = reinterpret_cast(m_RGBAData); + DecompressImage(pixelData, GetWidth() * GetHeight() * 4); +} diff --git a/Core/src/CompressionFuncs.h b/Core/src/CompressionFuncs.h new file mode 100644 index 0000000..6480d4c --- /dev/null +++ b/Core/src/CompressionFuncs.h @@ -0,0 +1,71 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#ifndef CORE_SRC_COMPRESSIONFUNCS_H_ +#define CORE_SRC_COMPRESSIONFUNCS_H_ + +#include "CompressionJob.h" +#include + +// A compression function format. It takes the raw data and image dimensions and +// returns the compressed image data into outData. It is assumed that there is +// enough space allocated for outData to store the compressed data. Allocation +// is dependent on the compression format. +typedef void (* CompressionFunc)(const CompressionJob &); + +// A compression function format. It takes the raw data and image dimensions and +// returns the compressed image data into outData. It is assumed that there is +// enough space allocated for outData to store the compressed data. Allocation +// is dependent on the compression format. +typedef void (* CompressionFuncWithStats)(const CompressionJob &, std::ostream *logStream); + +#endif // CORE_SRC_COMPRESSIONFUNCS_H_ diff --git a/Core/src/TexComp.cpp b/Core/src/TexComp.cpp index 3cf0bf5..c91afe0 100644 --- a/Core/src/TexComp.cpp +++ b/Core/src/TexComp.cpp @@ -48,7 +48,9 @@ #include #include #include +#include +#include "CompressionFuncs.h" #include "BC7Compressor.h" #include "Thread.h" #include "WorkerQueue.h" @@ -57,7 +59,6 @@ #include "ImageFile.h" #include "Image.h" - template static void clamp(T &x, const T &minX, const T &maxX) { x = std::max(std::min(maxX, x), minX); @@ -142,7 +143,9 @@ static double CompressImageInSerial( // !FIXME! We're assuming that we have 4x4 blocks here... CompressionJob cj (imgData, outBuf, imgDataSz / 16, 4); if(fStats && settings.pStatManager) { - (*fStats)(cj, *(settings.pStatManager)); + // !FIXME! Actually use the stat manager... + //(*fStats)(cj, *(settings.pStatManager)); + (*fStats)(cj, &std::cout); } else { (*f)(cj); @@ -330,6 +333,41 @@ static double CompressImageWithWorkerQueue( return cmpTimeTotal / double(settings.iNumCompressions); } +CompressedImage *CompressImage( + Image *img, const SCompressionSettings &settings +) { + if(!img) return NULL; + + const uint32 w = img->GetWidth(); + const uint32 h = img->GetHeight(); + + CompressedImage *outImg = NULL; + const unsigned int dataSz = w * h * 4; + + assert(dataSz > 0); + + // Allocate data based on the compression method + int cmpDataSz = 0; + switch(settings.format) { + default: assert(!"Not implemented!"); // Fall Through V + case eCompressionFormat_DXT1: cmpDataSz = dataSz / 8; break; + case eCompressionFormat_DXT5: cmpDataSz = dataSz / 4; break; + case eCompressionFormat_BPTC: cmpDataSz = dataSz / 4; break; + } + + // Make sure that we have RGBA data... + img->ComputeRGBA(); + + unsigned char *cmpData = new unsigned char[cmpDataSz]; + const uint8 *pixelData = reinterpret_cast(img->GetRGBA()); + CompressImageData(pixelData, dataSz, cmpData, cmpDataSz, settings); + + outImg = new CompressedImage(w, h, settings.format, cmpData); + + delete [] cmpData; + return outImg; +} + bool CompressImageData( const unsigned char *data, const unsigned int dataSz, diff --git a/Core/src/ThreadGroup.cpp b/Core/src/ThreadGroup.cpp index 49be9f5..7aefc57 100644 --- a/Core/src/ThreadGroup.cpp +++ b/Core/src/ThreadGroup.cpp @@ -44,9 +44,10 @@ #include "ThreadGroup.h" #include "BC7Compressor.h" -#include -#include -#include +#include +#include +#include +#include CmpThread::CmpThread() : m_StartBarrier(NULL) @@ -90,7 +91,9 @@ void CmpThread::operator()() { if(m_CmpFunc) (*m_CmpFunc)(cj); else - (*m_CmpFuncWithStats)(cj, *m_StatManager); + // !FIXME! Actually use the block stat manager... + // (*m_CmpFuncWithStats)(cj, *m_StatManager); + (*m_CmpFuncWithStats)(cj, &std::cout); { TCLock lock(*m_ParentCounterLock); diff --git a/Core/src/ThreadGroup.h b/Core/src/ThreadGroup.h index 9c098f5..1bda661 100644 --- a/Core/src/ThreadGroup.h +++ b/Core/src/ThreadGroup.h @@ -44,9 +44,10 @@ #ifndef _THREAD_GROUP_H_ #define _THREAD_GROUP_H_ -#include "TexComp.h" +#include "CompressionFuncs.h" #include "Thread.h" #include "StopWatch.h" +#include "BlockStats.h" struct CmpThread : public TCCallable { friend class ThreadGroup; diff --git a/Core/src/WorkerQueue.cpp b/Core/src/WorkerQueue.cpp index f99499f..c3a6d65 100644 --- a/Core/src/WorkerQueue.cpp +++ b/Core/src/WorkerQueue.cpp @@ -43,10 +43,11 @@ #include "WorkerQueue.h" -#include -#include -#include #include +#include +#include +#include +#include #include "BC7Compressor.h" @@ -104,7 +105,9 @@ void WorkerThread::operator()() { if(f) (*f)(cj); else - (*fStat)(cj, *statManager); + // !FIXME! Actually use stat manager... + // (*fStat)(cj, *statManager); + (*fStat)(cj, &std::cout); break; } diff --git a/Core/src/WorkerQueue.h b/Core/src/WorkerQueue.h index 5f42fc8..d99f96e 100644 --- a/Core/src/WorkerQueue.h +++ b/Core/src/WorkerQueue.h @@ -46,12 +46,13 @@ // Forward declare... class WorkerQueue; +class BlockStatManager; // Necessary includes... #include "TexCompTypes.h" -#include "TexComp.h" #include "Thread.h" #include "StopWatch.h" +#include "CompressionFuncs.h" class WorkerThread : public TCCallable { friend class WorkerQueue; diff --git a/IO/CMakeLists.txt b/IO/CMakeLists.txt index 4e92bd4..28754bc 100644 --- a/IO/CMakeLists.txt +++ b/IO/CMakeLists.txt @@ -90,6 +90,7 @@ CONFIGURE_FILE( INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/IO/include ) INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/IO/include ) +INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Base/include ) INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Core/include ) ADD_LIBRARY(FasTCIO @@ -97,6 +98,8 @@ ADD_LIBRARY(FasTCIO ${HEADERS} ) +TARGET_LINK_LIBRARIES( FasTCIO FasTCBase ) + IF( PNG_FOUND ) TARGET_LINK_LIBRARIES( FasTCIO ${PNG_LIBRARY} ) TARGET_LINK_LIBRARIES( FasTCIO ${ZLIB_LIBRARY} ) diff --git a/IO/src/ImageFile.cpp b/IO/src/ImageFile.cpp index cd1596e..e6f8d84 100644 --- a/IO/src/ImageFile.cpp +++ b/IO/src/ImageFile.cpp @@ -43,11 +43,11 @@ #include "ImageFile.h" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include "ImageWriter.h" @@ -196,8 +196,22 @@ Image *ImageFile::LoadImage(const unsigned char *rawImageData) const { return NULL; } - Image *i = new Image(*loader); + uint8 *pixelData = NULL; + if(loader->GetImageData()) { + pixelData = new uint8[ loader->GetImageDataSz() ]; + if(!pixelData) { fprintf(stderr, "%s\n", "Out of memory!"); exit(1); } + memcpy(pixelData, loader->GetImageData(), loader->GetImageDataSz()); + } + else { + fprintf(stderr, "%s\n", "Failed to get data from image loader!"); + } + + uint32 *pixels = reinterpret_cast(pixelData); + Image *i = new Image(loader->GetWidth(), loader->GetHeight(), pixels); + + // Cleanup delete loader; + delete pixelData; return i; } diff --git a/PVRTCEncoder/CMakeLists.txt b/PVRTCEncoder/CMakeLists.txt index a36c3c9..b288744 100644 --- a/PVRTCEncoder/CMakeLists.txt +++ b/PVRTCEncoder/CMakeLists.txt @@ -54,7 +54,7 @@ INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}) INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/PVRTCEncoder/include) INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/PVRTCEncoder/include) -INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Core/include) +INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) SET( HEADERS include/PVRTCCompressor.h diff --git a/PVRTCEncoder/include/PVRTCCompressor.h b/PVRTCEncoder/include/PVRTCCompressor.h index 5e485fb..b66f1b5 100644 --- a/PVRTCEncoder/include/PVRTCCompressor.h +++ b/PVRTCEncoder/include/PVRTCCompressor.h @@ -53,7 +53,7 @@ #ifndef PVRTCENCODER_INCLUDE_PVRTCCOMPRESSOR_H_ #define PVRTCENCODER_INCLUDE_PVRTCCOMPRESSOR_H_ -#include "Core/include/CompressionJob.h" +#include "Base/include/CompressionJob.h" namespace PVRTCC { diff --git a/PVRTCEncoder/src/Block.h b/PVRTCEncoder/src/Block.h index a948d8a..9baa114 100644 --- a/PVRTCEncoder/src/Block.h +++ b/PVRTCEncoder/src/Block.h @@ -53,7 +53,7 @@ #ifndef PVRTCENCODER_SRC_BLOCK_H_ #define PVRTCENCODER_SRC_BLOCK_H_ -#include "Core/include/TexCompTypes.h" +#include "Base/include/TexCompTypes.h" #include "Pixel.h" diff --git a/PVRTCEncoder/src/Image.cpp b/PVRTCEncoder/src/Image.cpp index c90a57c..75399e3 100644 --- a/PVRTCEncoder/src/Image.cpp +++ b/PVRTCEncoder/src/Image.cpp @@ -58,7 +58,7 @@ #include "Pixel.h" -#include "Core/include/Image.h" +#include "Base/include/Image.h" #include "IO/include/ImageFile.h" namespace PVRTCC { diff --git a/PVRTCEncoder/src/Image.h b/PVRTCEncoder/src/Image.h index eabc045..e264f7c 100644 --- a/PVRTCEncoder/src/Image.h +++ b/PVRTCEncoder/src/Image.h @@ -53,7 +53,7 @@ #ifndef PVRTCENCODER_SRC_IMAGE_H_ #define PVRTCENCODER_SRC_IMAGE_H_ -#include "Core/include/TexCompTypes.h" +#include "Base/include/TexCompTypes.h" #include "PVRTCCompressor.h" namespace PVRTCC { diff --git a/PVRTCEncoder/src/Pixel.h b/PVRTCEncoder/src/Pixel.h index 1953e09..05d037a 100644 --- a/PVRTCEncoder/src/Pixel.h +++ b/PVRTCEncoder/src/Pixel.h @@ -53,7 +53,7 @@ #ifndef PVRTCENCODER_SRC_PIXEL_H_ #define PVRTCENCODER_SRC_PIXEL_H_ -#include "Core/include/TexCompTypes.h" +#include "Base/include/TexCompTypes.h" namespace PVRTCC { diff --git a/PVRTCEncoder/test/TestUtils.h b/PVRTCEncoder/test/TestUtils.h index e1239ae..c25bb5e 100644 --- a/PVRTCEncoder/test/TestUtils.h +++ b/PVRTCEncoder/test/TestUtils.h @@ -53,7 +53,7 @@ #ifndef PVRTCENCODER_TEST_TESTUTILS_H_ #define PVRTCENCODER_TEST_TESTUTILS_H_ -#include "Core/include/TexCompTypes.h" +#include "Base/include/TexCompTypes.h" class PixelPrinter { private: