2008-02-14 05:08:26 +00:00
|
|
|
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person
|
|
|
|
// obtaining a copy of this software and associated documentation
|
|
|
|
// files (the "Software"), to deal in the Software without
|
|
|
|
// restriction, including without limitation the rights to use,
|
|
|
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following
|
|
|
|
// conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be
|
|
|
|
// included in all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
|
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
|
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
#include <nvtt/nvtt.h>
|
2008-11-21 07:38:12 +00:00
|
|
|
#include <nvimage/Image.h>
|
2008-11-21 07:58:49 +00:00
|
|
|
#include <nvimage/ImageIO.h>
|
2008-11-21 07:38:12 +00:00
|
|
|
#include <nvimage/BlockDXT.h>
|
|
|
|
#include <nvimage/ColorBlock.h>
|
|
|
|
#include <nvcore/Ptr.h>
|
|
|
|
#include <nvcore/Debug.h>
|
2008-11-21 07:58:49 +00:00
|
|
|
#include <nvcore/StrLib.h>
|
2008-11-22 11:33:31 +00:00
|
|
|
#include <nvcore/StdStream.h>
|
|
|
|
#include <nvcore/TextWriter.h>
|
2008-11-22 22:08:31 +00:00
|
|
|
#include <nvcore/FileSystem.h>
|
2008-11-21 07:38:12 +00:00
|
|
|
|
|
|
|
#include <stdlib.h> // free
|
|
|
|
#include <string.h> // memcpy
|
2008-02-14 05:08:26 +00:00
|
|
|
#include <time.h> // clock
|
|
|
|
|
2008-02-14 09:21:57 +00:00
|
|
|
|
2008-11-21 07:38:12 +00:00
|
|
|
using namespace nv;
|
|
|
|
|
|
|
|
static const char * s_fileNames[] = {
|
2008-11-22 11:33:31 +00:00
|
|
|
// Kodak image set
|
2008-11-22 00:14:05 +00:00
|
|
|
"kodim01.png",
|
|
|
|
"kodim02.png",
|
|
|
|
"kodim03.png",
|
|
|
|
"kodim04.png",
|
|
|
|
"kodim05.png",
|
|
|
|
"kodim06.png",
|
|
|
|
"kodim07.png",
|
|
|
|
"kodim08.png",
|
|
|
|
"kodim09.png",
|
|
|
|
"kodim10.png",
|
|
|
|
"kodim11.png",
|
|
|
|
"kodim12.png",
|
|
|
|
"kodim13.png",
|
|
|
|
"kodim14.png",
|
|
|
|
"kodim15.png",
|
|
|
|
"kodim16.png",
|
|
|
|
"kodim17.png",
|
|
|
|
"kodim18.png",
|
|
|
|
"kodim19.png",
|
|
|
|
"kodim20.png",
|
|
|
|
"kodim21.png",
|
|
|
|
"kodim22.png",
|
|
|
|
"kodim23.png",
|
|
|
|
"kodim24.png",
|
2008-11-22 11:33:31 +00:00
|
|
|
// Waterloo image set
|
2008-11-22 00:14:05 +00:00
|
|
|
"clegg.png",
|
|
|
|
"frymire.png",
|
|
|
|
"lena.png",
|
|
|
|
"monarch.png",
|
|
|
|
"peppers.png",
|
|
|
|
"sail.png",
|
|
|
|
"serrano.png",
|
|
|
|
"tulips.png",
|
2008-11-22 11:33:31 +00:00
|
|
|
// Epic image set
|
|
|
|
"Bradley1.png",
|
|
|
|
"Gradient.png",
|
|
|
|
"MoreRocks.png",
|
|
|
|
"Wall.png",
|
|
|
|
"Rainbow.png",
|
|
|
|
"Text.png",
|
2008-11-21 07:38:12 +00:00
|
|
|
};
|
|
|
|
const int s_fileCount = sizeof(s_fileNames)/sizeof(s_fileNames[0]);
|
2008-02-14 09:21:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
struct MyOutputHandler : public nvtt::OutputHandler
|
|
|
|
{
|
2008-11-21 07:38:12 +00:00
|
|
|
MyOutputHandler() : m_data(NULL), m_ptr(NULL) {}
|
2008-11-22 00:14:05 +00:00
|
|
|
~MyOutputHandler()
|
|
|
|
{
|
|
|
|
free(m_data);
|
|
|
|
}
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-02-14 09:21:57 +00:00
|
|
|
virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
|
|
|
|
{
|
2008-11-22 00:14:05 +00:00
|
|
|
m_size = size;
|
|
|
|
m_width = width;
|
|
|
|
m_height = height;
|
|
|
|
free(m_data);
|
|
|
|
m_data = (unsigned char *)malloc(size);
|
2008-11-21 07:38:12 +00:00
|
|
|
m_ptr = m_data;
|
2008-02-14 09:21:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool writeData(const void * data, int size)
|
|
|
|
{
|
|
|
|
memcpy(m_ptr, data, size);
|
|
|
|
m_ptr += size;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
Image * decompress(nvtt::Format format)
|
|
|
|
{
|
|
|
|
int bw = (m_width + 3) / 4;
|
|
|
|
int bh = (m_height + 3) / 4;
|
|
|
|
|
|
|
|
AutoPtr<Image> img( new Image() );
|
|
|
|
img->allocate(m_width, m_height);
|
|
|
|
|
|
|
|
if (format == nvtt::Format_BC1)
|
|
|
|
{
|
|
|
|
BlockDXT1 * block = (BlockDXT1 *)m_data;
|
|
|
|
|
|
|
|
for (int y = 0; y < bh; y++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < bw; x++)
|
|
|
|
{
|
|
|
|
ColorBlock colors;
|
|
|
|
block->decodeBlock(&colors);
|
|
|
|
|
|
|
|
for (int yy = 0; yy < 4; yy++)
|
|
|
|
{
|
|
|
|
for (int xx = 0; xx < 4; xx++)
|
|
|
|
{
|
|
|
|
Color32 c = colors.color(xx, yy);
|
|
|
|
|
|
|
|
if (x * 4 + xx < m_width && y * 4 + yy < m_height)
|
|
|
|
{
|
|
|
|
img->pixel(x * 4 + xx, y * 4 + yy) = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
block++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return img.release();
|
|
|
|
}
|
|
|
|
|
|
|
|
int m_size;
|
|
|
|
int m_width;
|
|
|
|
int m_height;
|
|
|
|
unsigned char * m_data;
|
2008-02-14 09:21:57 +00:00
|
|
|
unsigned char * m_ptr;
|
|
|
|
};
|
2008-02-14 05:08:26 +00:00
|
|
|
|
2008-11-21 07:38:12 +00:00
|
|
|
|
|
|
|
float rmsError(const Image * a, const Image * b)
|
2008-02-15 08:58:02 +00:00
|
|
|
{
|
2008-11-22 00:14:05 +00:00
|
|
|
nvCheck(a != NULL);
|
|
|
|
nvCheck(b != NULL);
|
|
|
|
nvCheck(a->width() == b->width());
|
|
|
|
nvCheck(a->height() == b->height());
|
2008-02-15 08:58:02 +00:00
|
|
|
|
2008-12-09 11:25:46 +00:00
|
|
|
int mse = 0;
|
2008-02-15 08:58:02 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
const uint count = a->width() * a->height();
|
2008-02-15 08:58:02 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
for (uint i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
Color32 c0 = a->pixel(i);
|
|
|
|
Color32 c1 = b->pixel(i);
|
2008-02-15 08:58:02 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
int r = c0.r - c1.r;
|
|
|
|
int g = c0.g - c1.g;
|
|
|
|
int b = c0.b - c1.b;
|
|
|
|
//int a = c0.a - c1.a;
|
2008-05-06 19:52:27 +00:00
|
|
|
|
2008-12-09 11:25:46 +00:00
|
|
|
mse += r * r;
|
|
|
|
mse += g * g;
|
|
|
|
mse += b * b;
|
2008-11-22 00:14:05 +00:00
|
|
|
}
|
2008-02-15 08:58:02 +00:00
|
|
|
|
2008-12-09 11:25:46 +00:00
|
|
|
return sqrtf(float(mse) / count);
|
2008-02-15 08:58:02 +00:00
|
|
|
}
|
2008-02-14 05:08:26 +00:00
|
|
|
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-02-14 05:08:26 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2008-11-21 09:09:57 +00:00
|
|
|
const uint version = nvtt::version();
|
|
|
|
const uint major = version / 100;
|
|
|
|
const uint minor = version % 100;
|
|
|
|
|
|
|
|
printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007 - 2008\n\n", major, minor);
|
|
|
|
|
|
|
|
bool fast = false;
|
|
|
|
bool nocuda = false;
|
|
|
|
bool showHelp = false;
|
|
|
|
const char * outPath = "output";
|
2008-11-22 11:33:31 +00:00
|
|
|
const char * regressPath = NULL;
|
2008-11-21 09:09:57 +00:00
|
|
|
|
|
|
|
// Parse arguments.
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
if (strcmp("-fast", argv[i]) == 0)
|
|
|
|
{
|
|
|
|
fast = true;
|
|
|
|
}
|
|
|
|
else if (strcmp("-nocuda", argv[i]) == 0)
|
|
|
|
{
|
|
|
|
nocuda = true;
|
|
|
|
}
|
|
|
|
else if (strcmp("-help", argv[i]) == 0)
|
|
|
|
{
|
|
|
|
showHelp = true;
|
|
|
|
}
|
|
|
|
else if (strcmp("-out", argv[i]) == 0)
|
|
|
|
{
|
|
|
|
if (i+1 < argc && argv[i+1][0] != '-') outPath = argv[i+1];
|
|
|
|
}
|
2008-11-22 11:33:31 +00:00
|
|
|
else if (strcmp("-regress", argv[i]) == 0)
|
|
|
|
{
|
|
|
|
if (i+1 < argc && argv[i+1][0] != '-') regressPath = argv[i+1];
|
|
|
|
}
|
2008-11-21 09:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (showHelp)
|
|
|
|
{
|
|
|
|
printf("usage: nvtestsuite [options]\n\n");
|
|
|
|
|
2008-11-22 11:33:31 +00:00
|
|
|
printf("Input options:\n");
|
|
|
|
printf(" -regress <path>\tRegression directory.\n");
|
|
|
|
|
2008-11-21 09:09:57 +00:00
|
|
|
printf("Compression options:\n");
|
2008-11-22 11:33:31 +00:00
|
|
|
printf(" -fast \tFast compression.\n");
|
|
|
|
printf(" -nocuda \tDo not use cuda compressor.\n");
|
2008-11-21 09:09:57 +00:00
|
|
|
|
|
|
|
printf("Output options:\n");
|
2008-11-22 11:33:31 +00:00
|
|
|
printf(" -out <path> \tOutput directory.\n");
|
2008-11-21 09:09:57 +00:00
|
|
|
|
|
|
|
return 1;
|
2008-12-09 11:25:46 +00:00
|
|
|
}
|
2008-11-21 09:09:57 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
nvtt::InputOptions inputOptions;
|
|
|
|
inputOptions.setMipmapGeneration(false);
|
2008-02-14 05:08:26 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
nvtt::CompressionOptions compressionOptions;
|
|
|
|
compressionOptions.setFormat(nvtt::Format_BC1);
|
2008-11-21 09:09:57 +00:00
|
|
|
if (fast)
|
|
|
|
{
|
|
|
|
compressionOptions.setQuality(nvtt::Quality_Fastest);
|
2008-11-22 00:14:05 +00:00
|
|
|
}
|
2008-11-21 09:09:57 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
compressionOptions.setQuality(nvtt::Quality_Production);
|
|
|
|
}
|
2008-02-14 05:08:26 +00:00
|
|
|
|
|
|
|
nvtt::OutputOptions outputOptions;
|
2008-11-22 00:14:05 +00:00
|
|
|
outputOptions.setOutputHeader(false);
|
2008-02-14 09:21:57 +00:00
|
|
|
|
|
|
|
MyOutputHandler outputHandler;
|
|
|
|
outputOptions.setOutputHandler(&outputHandler);
|
|
|
|
|
2009-03-02 07:32:00 +00:00
|
|
|
nvtt::Context context;
|
|
|
|
context.enableCudaAcceleration(!nocuda);
|
2008-02-14 09:21:57 +00:00
|
|
|
|
2008-11-22 22:08:31 +00:00
|
|
|
FileSystem::createDirectory(outPath);
|
2008-11-22 11:33:31 +00:00
|
|
|
|
2008-12-29 11:29:45 +00:00
|
|
|
Path csvFileName;
|
|
|
|
csvFileName.format("%s/result.csv", outPath);
|
2008-11-22 11:33:31 +00:00
|
|
|
StdOutputStream csvStream(csvFileName);
|
|
|
|
TextWriter csvWriter(&csvStream);
|
|
|
|
|
2008-11-21 09:09:57 +00:00
|
|
|
float totalTime = 0;
|
2008-12-07 23:15:06 +00:00
|
|
|
float totalRMSE = 0;
|
2008-11-22 11:33:31 +00:00
|
|
|
int failedTests = 0;
|
|
|
|
float totalDiff = 0;
|
2008-02-14 05:08:26 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
for (int i = 0; i < s_fileCount; i++)
|
|
|
|
{
|
|
|
|
AutoPtr<Image> img( new Image() );
|
|
|
|
|
|
|
|
if (!img->load(s_fileNames[i]))
|
|
|
|
{
|
|
|
|
printf("Input image '%s' not found.\n", s_fileNames[i]);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
inputOptions.setTextureLayout(nvtt::TextureType_2D, img->width(), img->height());
|
|
|
|
inputOptions.setMipmapData(img->pixels(), img->width(), img->height());
|
2008-02-14 05:08:26 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
printf("Compressing: \t'%s'\n", s_fileNames[i]);
|
2008-11-21 07:38:12 +00:00
|
|
|
|
|
|
|
clock_t start = clock();
|
2008-02-14 09:21:57 +00:00
|
|
|
|
2009-03-02 07:32:00 +00:00
|
|
|
context.process(inputOptions, compressionOptions, outputOptions);
|
2008-02-14 05:08:26 +00:00
|
|
|
|
|
|
|
clock_t end = clock();
|
2008-11-21 09:09:57 +00:00
|
|
|
printf(" Time: \t%.3f sec\n", float(end-start) / CLOCKS_PER_SEC);
|
|
|
|
totalTime += float(end-start);
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-11-22 00:14:05 +00:00
|
|
|
AutoPtr<Image> img_out( outputHandler.decompress(nvtt::Format_BC1) );
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-12-29 11:29:45 +00:00
|
|
|
Path outputFileName;
|
|
|
|
outputFileName.format("%s/%s", outPath, s_fileNames[i]);
|
2008-11-21 08:06:25 +00:00
|
|
|
outputFileName.stripExtension();
|
|
|
|
outputFileName.append(".tga");
|
2008-11-22 00:14:05 +00:00
|
|
|
if (!ImageIO::save(outputFileName, img_out.ptr()))
|
2008-11-21 08:06:25 +00:00
|
|
|
{
|
|
|
|
printf("Error saving file '%s'.\n", outputFileName.str());
|
|
|
|
}
|
2008-11-21 07:58:49 +00:00
|
|
|
|
2008-12-07 23:15:06 +00:00
|
|
|
float rmse = rmsError(img.ptr(), img_out.ptr());
|
|
|
|
totalRMSE += rmse;
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-12-07 23:15:06 +00:00
|
|
|
printf(" RMSE: \t%.4f\n", rmse);
|
2008-11-22 11:33:31 +00:00
|
|
|
|
|
|
|
// Output csv file
|
2008-12-07 23:15:06 +00:00
|
|
|
csvWriter << "\"" << s_fileNames[i] << "\"," << rmse << "\n";
|
2008-11-22 11:33:31 +00:00
|
|
|
|
|
|
|
if (regressPath != NULL)
|
|
|
|
{
|
2008-12-29 11:29:45 +00:00
|
|
|
Path regressFileName;
|
|
|
|
regressFileName.format("%s/%s", regressPath, s_fileNames[i]);
|
2008-11-22 11:33:31 +00:00
|
|
|
regressFileName.stripExtension();
|
|
|
|
regressFileName.append(".tga");
|
|
|
|
|
|
|
|
AutoPtr<Image> img_reg( new Image() );
|
|
|
|
if (!img_reg->load(regressFileName.str()))
|
|
|
|
{
|
|
|
|
printf("Regression image '%s' not found.\n", regressFileName.str());
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2008-12-07 23:15:06 +00:00
|
|
|
float rmse_reg = rmsError(img.ptr(), img_reg.ptr());
|
2008-11-22 11:33:31 +00:00
|
|
|
|
2008-12-07 23:15:06 +00:00
|
|
|
float diff = rmse_reg - rmse;
|
2008-11-22 11:33:31 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-11-22 22:08:31 +00:00
|
|
|
fflush(stdout);
|
2008-11-22 00:14:05 +00:00
|
|
|
}
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-12-07 23:15:06 +00:00
|
|
|
totalRMSE /= s_fileCount;
|
2008-11-22 11:33:31 +00:00
|
|
|
totalDiff /= s_fileCount;
|
|
|
|
|
|
|
|
printf("Total Results:\n");
|
|
|
|
printf(" Total Time: \t%.3f sec\n", totalTime / CLOCKS_PER_SEC);
|
2008-12-07 23:15:06 +00:00
|
|
|
printf(" Average RMSE:\t%.4f\n", totalRMSE);
|
2008-11-21 07:38:12 +00:00
|
|
|
|
2008-11-22 11:33:31 +00:00
|
|
|
if (regressPath != NULL)
|
|
|
|
{
|
|
|
|
printf("Regression Results:\n");
|
|
|
|
printf(" Diff: %.4f\n", totalDiff);
|
|
|
|
printf(" %d/%d tests failed.\n", failedTests, s_fileCount);
|
|
|
|
}
|
2008-02-14 05:08:26 +00:00
|
|
|
|
2008-02-14 09:21:57 +00:00
|
|
|
return EXIT_SUCCESS;
|
2008-02-14 05:08:26 +00:00
|
|
|
}
|
|
|
|
|