diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aafc8ed..d354b3c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,7 +72,7 @@ ELSE(MAYA_FOUND) ENDIF(MAYA_FOUND) # FreeImage -INCLUDE(${NV_CMAKE_DIR}/FindFreeImage.cmake) +#INCLUDE(${NV_CMAKE_DIR}/FindFreeImage.cmake) IF(FREEIMAGE_FOUND) SET(HAVE_FREEIMAGE ${FREEIMAGE_FOUND} CACHE BOOL "Set to TRUE if FreeImage is found, FALSE otherwise") MESSAGE(STATUS "Looking for FreeImage - found") diff --git a/src/nvimage/CMakeLists.txt b/src/nvimage/CMakeLists.txt index 8584ede..2c7eb61 100644 --- a/src/nvimage/CMakeLists.txt +++ b/src/nvimage/CMakeLists.txt @@ -22,6 +22,7 @@ SET(IMAGE_SRCS NormalMap.cpp PsdFile.h TgaFile.h + PixelFormat.h ColorSpace.h ColorSpace.cpp) diff --git a/src/nvimage/PixelFormat.h b/src/nvimage/PixelFormat.h index 3ff5406..9a702e7 100644 --- a/src/nvimage/PixelFormat.h +++ b/src/nvimage/PixelFormat.h @@ -30,52 +30,87 @@ namespace nv { - namespace PixelFormat + namespace PixelFormat + { + + // Convert component @a c having @a inbits to the returned value having @a outbits. + inline uint convert(uint c, uint inbits, uint outbits) + { + if (inbits == 0) + { + return 0; + } + else if (inbits >= outbits) + { + // truncate + return c >> (inbits - outbits); + } + else + { + // bitexpand + return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); + } + } + + // Get pixel component shift and size given its mask. + inline void maskShiftAndSize(uint mask, uint * shift, uint * size) { + if (!mask) + { + *shift = 0; + *size = 0; + return; + } + + *shift = 0; + while((mask & 1) == 0) { + ++(*shift); + mask >>= 1; + } + + *size = 0; + while((mask & 1) == 1) { + ++(*size); + mask >>= 1; + } + } + + inline float quantizeCeil(float f, int inbits, int outbits) + { + nvDebugCheck(f >= 0.0f && f <= 1.0f); + //uint i = f * (float(1 << inbits) - 1); + //i = convert(i, inbits, outbits); + //float result = float(i) / (float(1 << outbits) - 1); + //nvCheck(result >= f); + float result; + int offset = 0; + do { + uint i = offset + f * (float(1 << inbits) - 1); + i = convert(i, inbits, outbits); + result = float(i) / (float(1 << outbits) - 1); + offset++; + } while (result < f); + + return result; + } + + /* + inline float quantizeRound(float f, int bits) + { + nvDebugCheck(f >= 0.0f && f <= 1.0f); + float scale = float(1 << bits); + return fround(f * scale) / scale; + } + + inline float quantizeFloor(float f, int bits) + { + nvDebugCheck(f >= 0.0f && f <= 1.0f); + float scale = float(1 << bits); + return floor(f * scale) / scale; + } + */ - // Convert component @a c having @a inbits to the returned value having @a outbits. - inline uint convert(uint c, uint inbits, uint outbits) - { - if (inbits == 0) - { - return 0; - } - else if (inbits >= outbits) - { - // truncate - return c >> (inbits - outbits); - } - else - { - // bitexpand - return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); - } - } - - // Get pixel component shift and size given its mask. - inline void maskShiftAndSize(uint mask, uint * shift, uint * size) - { - if (!mask) - { - *shift = 0; - *size = 0; - return; - } - - *shift = 0; - while((mask & 1) == 0) { - ++(*shift); - mask >>= 1; - } - - *size = 0; - while((mask & 1) == 1) { - ++(*size); - mask >>= 1; - } - } - - } // PixelFormat namespace + } // PixelFormat namespace } // nv namespace diff --git a/src/nvmath/nvmath.h b/src/nvmath/nvmath.h index 2fb504b..c2b2b23 100644 --- a/src/nvmath/nvmath.h +++ b/src/nvmath/nvmath.h @@ -200,27 +200,6 @@ namespace nv return float(iround(f)); } - inline float quantizeCeil(float f, int bits) - { - nvDebugCheck(f >= 0.0f && f <= 1.0f); - float scale = float(1 << bits); - return ceilf(f * scale) / scale; - } - - inline float quantizeRound(float f, int bits) - { - nvDebugCheck(f >= 0.0f && f <= 1.0f); - float scale = float(1 << bits); - return fround(f * scale) / scale; - } - - inline float quantizeFloor(float f, int bits) - { - nvDebugCheck(f >= 0.0f && f <= 1.0f); - float scale = float(1 << bits); - return floor(f * scale) / scale; - } - } // nv #endif // NV_MATH_H diff --git a/src/nvtt/TexImage.cpp b/src/nvtt/TexImage.cpp index e162b66..ea719f3 100644 --- a/src/nvtt/TexImage.cpp +++ b/src/nvtt/TexImage.cpp @@ -34,6 +34,7 @@ #include "nvimage/NormalMap.h" #include "nvimage/BlockDXT.h" #include "nvimage/ColorBlock.h" +#include "nvimage/PixelFormat.h" #include @@ -1154,7 +1155,7 @@ void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/) } } - float scale = quantizeCeil(m, bits); + float scale = PixelFormat::quantizeCeil(m, bits, 8); nvDebugCheck(scale >= m); // Store block scale in blue channel and scale CoCg. @@ -1212,6 +1213,41 @@ void TexImage::fromYCoCg() } } +void TexImage::toLUVW(float range/*= 1.0f*/) +{ + if (m->image == NULL) return; + + detach(); + + float irange = 1.0f / range; + + FloatImage * img = m->image; + float * r = img->channel(0); + float * g = img->channel(1); + float * b = img->channel(2); + float * a = img->channel(3); + + const uint count = img->width() * img->height(); + for (uint i = 0; i < count; i++) { + float R = nv::clamp(r[i] * irange, 0.0f, 1.0f); + float G = nv::clamp(g[i] * irange, 0.0f, 1.0f); + float B = nv::clamp(b[i] * irange, 0.0f, 1.0f); + + float L = max(sqrtf(R*R + G*G + B*B), 1e-6f)); // Avoid division by zero. + //m = quantizeCeil(m, 8); + + r[i] = R / L; + g[i] = G / L; + b[i] = B / L; + a[i] = L; + } +} + +void TexImage::fromLUVW(float range/*= 1.0f*/) +{ + // Decompression is the same as in RGBM. + fromRGBM(range); +} void TexImage::binarize(int channel, float threshold, bool dither) diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 5f8cf99..43e9a98 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -432,6 +432,8 @@ namespace nvtt NVTT_API void toYCoCg(); NVTT_API void blockScaleCoCg(int bits = 5, float threshold = 0.0f); NVTT_API void fromYCoCg(); + NVTT_API void toLUVW(float range = 1.0f); + NVTT_API void fromLUVW(float range = 1.0f); // Color quantization. NVTT_API void binarize(int channel, float threshold, bool dither); @@ -449,9 +451,9 @@ namespace nvtt NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel); // Error compare. - friend NVTT_API float rmsError(const TexImage & reference, const TexImage & img); - friend NVTT_API float rmsAlphaError(const TexImage & reference, const TexImage & img); - friend NVTT_API TexImage diff(const TexImage & reference, const TexImage & img); + friend float rmsError(const TexImage & reference, const TexImage & img); + friend float rmsAlphaError(const TexImage & reference, const TexImage & img); + friend TexImage diff(const TexImage & reference, const TexImage & img); private: void detach(); @@ -467,6 +469,10 @@ namespace nvtt // Return NVTT version. NVTT_API unsigned int version(); + NVTT_API float rmsError(const TexImage & reference, const TexImage & img); + NVTT_API float rmsAlphaError(const TexImage & reference, const TexImage & img); + NVTT_API TexImage diff(const TexImage & reference, const TexImage & img); + } // nvtt namespace #endif // NVTT_H diff --git a/src/nvtt/tests/process_alpha_map.cpp b/src/nvtt/tests/process_alpha_map.cpp index 92d62ff..58a9557 100644 --- a/src/nvtt/tests/process_alpha_map.cpp +++ b/src/nvtt/tests/process_alpha_map.cpp @@ -98,7 +98,7 @@ int main(int argc, char *argv[]) colorMap.flipVertically(); colorMap.setAlphaMode(nvtt::AlphaMode_Transparency); - context.compress(colorMap, colorCompressionOptions, colorOutputOptions); + context.compress(colorMap, 0, 0, colorCompressionOptions, colorOutputOptions); if (inputFileNameNormal != NULL) { context.outputHeader(normalMap, normalMap.countMipmaps(), normalCompressionOptions, normalOutputOptions); @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) normalMap.normalizeNormalMap(); normalMap.copyChannel(colorMap, 3); // Copy alpha channel from color to normal map. - context.compress(normalMap, normalCompressionOptions, normalOutputOptions); + context.compress(normalMap, 0, 0, normalCompressionOptions, normalOutputOptions); } const float gamma = 2.2f; @@ -118,6 +118,7 @@ int main(int argc, char *argv[]) const float coverage = colorMap.alphaTestCoverage(alphaRef); // Build and output mipmaps. + int m = 1; while (colorMap.buildNextMipmap(nvtt::MipmapFilter_Kaiser)) { colorMap.scaleAlphaToCoverage(coverage, alphaRef); @@ -125,15 +126,17 @@ int main(int argc, char *argv[]) nvtt::TexImage tmpColorMap = colorMap; tmpColorMap.toGamma(gamma); - context.compress(tmpColorMap, colorCompressionOptions, colorOutputOptions); + context.compress(tmpColorMap, 0, m, colorCompressionOptions, colorOutputOptions); if (inputFileNameNormal != NULL) { normalMap.buildNextMipmap(nvtt::MipmapFilter_Kaiser); normalMap.normalizeNormalMap(); normalMap.copyChannel(tmpColorMap, 3); - context.compress(normalMap, normalCompressionOptions, normalOutputOptions); + context.compress(normalMap, 0, m, normalCompressionOptions, normalOutputOptions); } + + m++; } return EXIT_SUCCESS; diff --git a/src/nvtt/tests/testsuite.cpp b/src/nvtt/tests/testsuite.cpp index 63a5dc3..48ec61a 100644 --- a/src/nvtt/tests/testsuite.cpp +++ b/src/nvtt/tests/testsuite.cpp @@ -42,6 +42,8 @@ using namespace nv; +#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) + // Kodak image set static const char * s_kodakImageSet[] = { "kodim01.png", @@ -94,17 +96,17 @@ static const char * s_epicImageSet[] = { // Farbrausch static const char * s_farbrauschImageSet[] = { - "t.2d.pn02.bmp", - "t.aircondition.01.bmp", - "t.bricks.02.bmp", - "t.bricks.05.bmp", - "t.concrete.cracked.01.bmp", - "t.envi.colored02.bmp", - "t.envi.colored03.bmp", - "t.font.01.bmp", - "t.sewers.01.bmp", - "t.train.03.bmp", - "t.yello.01.bmp", + "t.2d.pn02.png", + "t.aircondition.01.png", + "t.bricks.02.png", + "t.bricks.05.png", + "t.concrete.cracked.01.png", + "t.envi.colored02.png", + "t.envi.colored03.png", + "t.font.01.png", + "t.sewers.01.png", + "t.train.03.png", + "t.yello.01.png", }; // Lugaru @@ -128,39 +130,75 @@ static const char * s_quake3ImageSet[] = { "q3-wires02.tga", }; +static const char * s_witnessImageSet[] = { + "applebark.tga", + "grass-01.tga", + "brownRock.tga", + "rock-01.tga", + "rock-02.tga", + "Lao-picture.tga", + "laser-base.tga", + "skydome.tga", + "speaker.tga", + "specRuin-base.tga", + "vault.tga", + "specRuin-puzzle.tga" +}; + enum Mode { Mode_BC1, + Mode_BC1_Alpha, + Mode_BC2_Alpha, Mode_BC3_Alpha, Mode_BC3_YCoCg, Mode_BC3_RGBM, + Mode_BC1_Normal, Mode_BC3_Normal, Mode_BC5_Normal, }; +static const char * s_modeNames[] = { + "BC1", + "BC1-Alpha", + "BC2-Alpha", + "BC3-Alpha", + "BC3-YCoCg", + "BC3-RGBM", + "BC3-LUVW", + "BC1-Normal", + "BC3-Normal", + "BC5-Normal", +}; + +struct Test { + const char * name; + int count; + Mode modes[4]; +}; +static Test s_imageTests[] = { + {"DXT Color", 3, {Mode_BC1, Mode_BC3_YCoCg, Mode_BC3_RGBM}}, + {"DXT Alpha", 3, {Mode_BC1_Alpha, Mode_BC2_Alpha, Mode_BC3_Alpha}}, + {"DXT Normal", 3, {Mode_BC1_Normal, Mode_BC3_Normal, Mode_BC5_Normal}}, +}; +const int s_testCount = ARRAY_SIZE(s_imageTests); + struct ImageSet { const char * name; const char ** fileNames; int fileCount; - Mode mode; }; - -#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) - static ImageSet s_imageSets[] = { - {"Kodak - BC1", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), Mode_BC1}, - {"Kodak - BC3-YCoCg", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), Mode_BC3_YCoCg}, - {"Kodak - BC3-RGBM", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), Mode_BC3_RGBM}, - {"Waterloo - BC1", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet), Mode_BC1}, - {"Waterloo - BC3-YCoCg", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet), Mode_BC3_YCoCg}, - {"Epic - BC1", s_epicImageSet, ARRAY_SIZE(s_epicImageSet), Mode_BC1}, - {"Epic - BC1-YCoCg", s_epicImageSet, ARRAY_SIZE(s_epicImageSet), Mode_BC3_YCoCg}, - {"Farbraush - BC1", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet), Mode_BC1}, - {"Farbraush - BC1-YCoCg", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet), Mode_BC3_YCoCg}, - {"Lugaru - BC3", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet), Mode_BC3_Alpha}, - {"Quake3 - BC3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet), Mode_BC3_Alpha}, + {"Kodak", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet)}, // 0 + {"Waterloo", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet)}, // 1 + {"Epic", s_epicImageSet, ARRAY_SIZE(s_epicImageSet)}, // 2 + {"Farbraush", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet)}, // 3 + {"Lugaru", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet)}, // 4 + {"Quake3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet)}, // 5 + {"Witness", s_witnessImageSet, ARRAY_SIZE(s_witnessImageSet)} // 6 }; const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]); + struct MyOutputHandler : public nvtt::OutputHandler { MyOutputHandler() : m_data(NULL), m_ptr(NULL) {} @@ -220,6 +258,7 @@ int main(int argc, char *argv[]) printf("NVIDIA Texture Tools %u.%u.%u - Copyright NVIDIA Corporation 2007\n\n", major, minor, rev); int setIndex = 0; + int testIndex = 0; bool fast = false; bool nocuda = false; bool showHelp = false; @@ -238,6 +277,13 @@ int main(int argc, char *argv[]) i++; } } + else if (strcmp("-test", argv[i]) == 0) + { + if (i+1 < argc && argv[i+1][0] != '-') { + testIndex = atoi(argv[i+1]); + i++; + } + } else if (strcmp("-dec", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { @@ -280,6 +326,16 @@ int main(int argc, char *argv[]) } } + // Validate inputs. + if (testIndex >= s_testCount) { + printf("Invalid test %d\n", testIndex); + return 0; + } + if (setIndex >= s_imageSetCount) { + printf("Invalid image set %d\n", setIndex); + return 0; + } + if (showHelp) { printf("usage: nvtestsuite [options]\n\n"); @@ -287,13 +343,17 @@ int main(int argc, char *argv[]) printf("Input options:\n"); printf(" -path \tInput image path.\n"); printf(" -regress \tRegression directory.\n"); - printf(" -set [0:2] \tImage set.\n"); + printf(" -set [0:5] \tImage set.\n"); printf(" 0: \tKodak.\n"); printf(" 1: \tWaterloo.\n"); printf(" 2: \tEpic.\n"); printf(" 3: \tFarbrausch.\n"); printf(" 4: \tLugaru.\n"); printf(" 5: \tQuake 3.\n"); + printf(" -test [0:2] \tCompression tests to run."); + printf(" 0: \tDXT Color.\n"); + printf(" 1: \tDXT Alpha.\n"); + printf(" 2: \tDXT Normal.\n"); printf(" -dec x \tDecompressor.\n"); printf(" 0: \tReference.\n"); printf(" 1: \tNVIDIA.\n"); @@ -325,20 +385,7 @@ int main(int argc, char *argv[]) const ImageSet & set = s_imageSets[setIndex]; - - if (set.mode == Mode_BC1) { - compressionOptions.setFormat(nvtt::Format_BC1); - } - else if (set.mode == Mode_BC3_Alpha || set.mode == Mode_BC3_YCoCg || set.mode == Mode_BC3_RGBM) { - compressionOptions.setFormat(nvtt::Format_BC3); - } - else if (set.mode == Mode_BC3_Normal) { - compressionOptions.setFormat(nvtt::Format_BC3n); - } - else if (set.mode == Mode_BC5_Normal) { - compressionOptions.setFormat(nvtt::Format_BC5); - } - + const Test & test = s_imageTests[testIndex]; nvtt::OutputOptions outputOptions; @@ -353,147 +400,230 @@ int main(int argc, char *argv[]) FileSystem::changeDirectory(basePath); FileSystem::createDirectory(outPath); - Path csvFileName; - csvFileName.format("%s/result-%d.csv", outPath, setIndex); - StdOutputStream csvStream(csvFileName.str()); - TextWriter csvWriter(&csvStream); + //Path csvFileName; + //csvFileName.format("%s/result-%d.csv", outPath, setIndex); + //StdOutputStream csvStream(csvFileName.str()); + //TextWriter csvWriter(&csvStream); - float totalTime = 0; - float totalRMSE = 0; - int failedTests = 0; - float totalDiff = 0; + Path graphFileName; + graphFileName.format("%s/result-%d.txt", outPath, setIndex); + StdOutputStream graphStream(graphFileName.str()); + TextWriter graphWriter(&graphStream); - const char ** fileNames = set.fileNames; - int fileCount = set.fileCount; + graphWriter << "http://chart.apis.google.com/chart?"; - Timer timer; + // Graph size. + graphWriter << "chs=480x240"; - nvtt::TexImage img; - if (set.mode == Mode_BC3_Alpha) { - img.setAlphaMode(nvtt::AlphaMode_Transparency); + // Graph type: line + graphWriter << "&cht=lc"; + + // Margins. + graphWriter << "&chma=30,10,10|0,40"; + + // Grid lines. + graphWriter << "&chxt=x,y&chxtc=0,-1000|1,-1000"; + + // Labels. + graphWriter << "&chxr=0,1," << set.fileCount << ",1|1,0,0.05,0.01"; + graphWriter << "&chdlp=b"; // Labels at the bottom. + + // Line colors. + graphWriter << "&chco="; + for (int t = 0; t < test.count; t++) + { + const char * colors[] = { + "3D7930", "952826", "3D1FC1", + "3D7930", "952826", "3D1FC1", // pick other colors... + }; + graphWriter << colors[t]; + if (t != test.count-1) graphWriter << ","; } - if (set.mode == Mode_BC3_Normal || set.mode == Mode_BC5_Normal) { - img.setNormalMap(true); + + // Line width. + graphWriter << "&chls="; + for (int t = 0; t < test.count; t++) + { + graphWriter << "2"; + if (t != test.count-1) graphWriter << "|"; } - printf("Processing Set: %s\n", set.name); + // Data ranges. + graphWriter << "&chds="; + for (int t = 0; t < test.count; t++) + { + graphWriter << "0,0.05"; + if (t != test.count-1) graphWriter << ","; + } - for (int i = 0; i < fileCount; i++) + // Leyends. + graphWriter << "&chdl="; + for (int t = 0; t < test.count; t++) { - if (!img.load(fileNames[i])) - { - printf("Input image '%s' not found.\n", fileNames[i]); - return EXIT_FAILURE; - } + graphWriter << s_modeNames[test.modes[t]]; + if (t != test.count-1) graphWriter << "|"; + } - if (img.isNormalMap()) { - img.normalizeNormalMap(); - } + // Title + graphWriter << "&chtt=" << set.name << " - " << test.name; + + float totalTime = 0; + float totalRMSE = 0; + //int failedTests = 0; + float totalDiff = 0; - if (set.mode == Mode_BC3_YCoCg) { - img.toYCoCg(); - img.blockScaleCoCg(); - img.scaleBias(0, 0.5, 0.5); - img.scaleBias(1, 0.5, 0.5); - } - else if (set.mode == Mode_BC3_RGBM) { - img.toRGBM(); - } - printf("Compressing: \t'%s'\n", fileNames[i]); + Timer timer; - timer.start(); + nvtt::TexImage img; - context.compress(img, 0, 0, compressionOptions, outputOptions); + printf("Running Test: %s\n", set.name); - timer.stop(); - printf(" Time: \t%.3f sec\n", timer.elapsed()); - totalTime += timer.elapsed(); + graphWriter << "&chd=t:"; - nvtt::TexImage img_out = outputHandler.decompress(set.mode, decoder); - if (set.mode == Mode_BC3_Alpha) { - img_out.setAlphaMode(nvtt::AlphaMode_Transparency); + for (int t = 0; t < test.count; t++) + { + Mode mode = test.modes[t]; + if (mode == Mode_BC1) { + compressionOptions.setFormat(nvtt::Format_BC1); } - if (set.mode == Mode_BC3_Normal || set.mode == Mode_BC5_Normal) { - img_out.setNormalMap(true); + else if (mode == Mode_BC3_Alpha || mode == Mode_BC3_YCoCg || mode == Mode_BC3_RGBM) { + compressionOptions.setFormat(nvtt::Format_BC3); + } + else if (mode == Mode_BC3_Normal) { + compressionOptions.setFormat(nvtt::Format_BC3n); + } + else if (mode == Mode_BC5_Normal) { + compressionOptions.setFormat(nvtt::Format_BC5); } - if (set.mode == Mode_BC3_YCoCg) { - img_out.scaleBias(0, 1.0, -0.5); - img_out.scaleBias(1, 1.0, -0.5); - img_out.fromYCoCg(); - - img.scaleBias(0, 1.0, -0.5); - img.scaleBias(1, 1.0, -0.5); - img.fromYCoCg(); + if (mode == Mode_BC3_Alpha) { + img.setAlphaMode(nvtt::AlphaMode_Transparency); } - else if (set.mode == Mode_BC3_RGBM) { - img_out.fromRGBM(); - img.fromRGBM(); + if (mode == Mode_BC3_Normal || mode == Mode_BC5_Normal) { + img.setNormalMap(true); } - Path outputFileName; - outputFileName.format("%s/%s", outPath, fileNames[i]); - outputFileName.stripExtension(); - outputFileName.append(".png"); - if (!img_out.save(outputFileName.str())) + + printf("Processing Set: %s\n", set.name); + for (int i = 0; i < set.fileCount; i++) { - printf("Error saving file '%s'.\n", outputFileName.str()); - } + if (!img.load(set.fileNames[i])) + { + printf("Input image '%s' not found.\n", set.fileNames[i]); + return EXIT_FAILURE; + } - float rmse = nvtt::rmsError(img, img_out); - totalRMSE += rmse; + if (img.isNormalMap()) { + img.normalizeNormalMap(); + } - printf(" RMSE: \t%.4f\n", rmse); + nvtt::TexImage tmp = img; + if (mode == Mode_BC3_YCoCg) { + tmp.toYCoCg(); + tmp.blockScaleCoCg(); + tmp.scaleBias(0, 0.5, 0.5); + tmp.scaleBias(1, 0.5, 0.5); + } + else if (mode == Mode_BC3_RGBM) { + tmp.toRGBM(); + } - // Output csv file - csvWriter << "\"" << fileNames[i] << "\"," << rmse << "\n"; + printf("Compressing: \t'%s'\n", set.fileNames[i]); - if (regressPath != NULL) - { - Path regressFileName; - regressFileName.format("%s/%s", regressPath, fileNames[i]); - regressFileName.stripExtension(); - regressFileName.append(".png"); + timer.start(); + + context.compress(tmp, 0, 0, compressionOptions, outputOptions); + + timer.stop(); + printf(" Time: \t%.3f sec\n", timer.elapsed()); + totalTime += timer.elapsed(); + + nvtt::TexImage img_out = outputHandler.decompress(mode, decoder); + if (mode == Mode_BC3_Alpha) { + img_out.setAlphaMode(nvtt::AlphaMode_Transparency); + } + if (mode == Mode_BC3_Normal || mode == Mode_BC5_Normal) { + img_out.setNormalMap(true); + } - nvtt::TexImage img_reg; - if (!img_reg.load(regressFileName.str())) + if (mode == Mode_BC3_YCoCg) { + img_out.scaleBias(0, 1.0, -0.5); + img_out.scaleBias(1, 1.0, -0.5); + img_out.fromYCoCg(); + } + else if (mode == Mode_BC3_RGBM) { + img_out.fromRGBM(); + } + + Path outputFileName; + outputFileName.format("%s/%s", outPath, set.fileNames[i]); + outputFileName.stripExtension(); + outputFileName.append(".png"); + if (!img_out.save(outputFileName.str())) { - printf("Regression image '%s' not found.\n", regressFileName.str()); - return EXIT_FAILURE; + printf("Error saving file '%s'.\n", outputFileName.str()); } - float rmse_reg = rmsError(img, img_reg); + float rmse = nvtt::rmsError(img, img_out); + totalRMSE += rmse; - float diff = rmse_reg - rmse; - totalDiff += diff; + printf(" RMSE: \t%.4f\n", rmse); - const char * text = "PASSED"; - if (equal(diff, 0)) text = "PASSED"; - else if (diff < 0) { - text = "FAILED"; - failedTests++; - } + graphWriter << rmse; + if (i != set.fileCount-1) graphWriter << ","; - printf(" Diff: \t%.4f (%s)\n", diff, text); + // Output csv file + //csvWriter << "\"" << fileNames[i] << "\"," << rmse << "\n"; + + /*if (regressPath != NULL) + { + Path regressFileName; + regressFileName.format("%s/%s", regressPath, fileNames[i]); + regressFileName.stripExtension(); + regressFileName.append(".png"); + + nvtt::TexImage img_reg; + if (!img_reg.load(regressFileName.str())) + { + printf("Regression image '%s' not found.\n", regressFileName.str()); + return EXIT_FAILURE; + } + + float rmse_reg = rmsError(img, img_reg); + + float diff = rmse_reg - rmse; + totalDiff += diff; + + const char * text = "PASSED"; + if (equal(diff, 0)) text = "PASSED"; + else if (diff < 0) { + text = "FAILED"; + failedTests++; + } + + printf(" Diff: \t%.4f (%s)\n", diff, text); + }*/ + + fflush(stdout); } - fflush(stdout); - } + totalRMSE /= set.fileCount; + totalDiff /= set.fileCount; - totalRMSE /= fileCount; - totalDiff /= fileCount; + printf("Total Results:\n"); + printf(" Total Time: \t%.3f sec\n", totalTime); + printf(" Average RMSE:\t%.4f\n", totalRMSE); - printf("Total Results:\n"); - printf(" Total Time: \t%.3f sec\n", totalTime); - printf(" Average RMSE:\t%.4f\n", totalRMSE); + if (t != s_testCount-1) graphWriter << "|"; + } - if (regressPath != NULL) + /*if (regressPath != NULL) { printf("Regression Results:\n"); printf(" Diff: %.4f\n", totalDiff); printf(" %d/%d tests failed.\n", failedTests, fileCount); - } + }*/ return EXIT_SUCCESS; }