Merge changes from The Witness.

This commit is contained in:
Ignacio
2015-03-24 12:14:49 -07:00
parent 7e2a9d1adb
commit a083337473
57 changed files with 2061 additions and 916 deletions

View File

@ -152,6 +152,8 @@ int main(int argc, char *argv[])
bool premultiplyAlpha = false;
nvtt::MipmapFilter mipmapFilter = nvtt::MipmapFilter_Box;
bool loadAsFloat = false;
bool rgbm = false;
bool rangescale = false;
const char * externalCompressor = NULL;
@ -209,6 +211,15 @@ int main(int argc, char *argv[])
{
loadAsFloat = true;
}
else if (strcmp("-rgbm", argv[i]) == 0)
{
rgbm = true;
}
else if (strcmp("-rangescale", argv[i]) == 0)
{
rangescale = true;
}
// Compression options.
else if (strcmp("-fast", argv[i]) == 0)
@ -269,6 +280,11 @@ int main(int argc, char *argv[])
{
format = nvtt::Format_BC7;
}
else if (strcmp("-bc3_rgbm", argv[i]) == 0)
{
format = nvtt::Format_BC3_RGBM;
rgbm = true;
}
// Undocumented option. Mainly used for testing.
else if (strcmp("-ext", argv[i]) == 0)
@ -332,32 +348,35 @@ int main(int argc, char *argv[])
printf("usage: nvcompress [options] infile [outfile.dds]\n\n");
printf("Input options:\n");
printf(" -color \tThe input image is a color map (default).\n");
printf(" -alpha \tThe input image has an alpha channel used for transparency.\n");
printf(" -normal \tThe input image is a normal map.\n");
printf(" -tonormal \tConvert input to normal map.\n");
printf(" -clamp \tClamp wrapping mode (default).\n");
printf(" -repeat \tRepeat wrapping mode.\n");
printf(" -nomips \tDisable mipmap generation.\n");
printf(" -premula \tPremultiply alpha into color channel.\n");
printf(" -mipfilter \tMipmap filter. One of the following: box, triangle, kaiser.\n");
printf(" -float \tLoad as floating point image.\n\n");
printf(" -color The input image is a color map (default).\n");
printf(" -alpha The input image has an alpha channel used for transparency.\n");
printf(" -normal The input image is a normal map.\n");
printf(" -tonormal Convert input to normal map.\n");
printf(" -clamp Clamp wrapping mode (default).\n");
printf(" -repeat Repeat wrapping mode.\n");
printf(" -nomips Disable mipmap generation.\n");
printf(" -premula Premultiply alpha into color channel.\n");
printf(" -mipfilter Mipmap filter. One of the following: box, triangle, kaiser.\n");
printf(" -float Load as floating point image.\n\n");
printf(" -rgbm Transform input to RGBM.\n\n");
printf(" -rangescale Scale image to use entire color range.\n\n");
printf("Compression options:\n");
printf(" -fast \tFast compression.\n");
printf(" -nocuda \tDo not use cuda compressor.\n");
printf(" -rgb \tRGBA format\n");
printf(" -lumi \tLUMINANCE format\n");
printf(" -bc1 \tBC1 format (DXT1)\n");
printf(" -bc1n \tBC1 normal map format (DXT1nm)\n");
printf(" -bc1a \tBC1 format with binary alpha (DXT1a)\n");
printf(" -bc2 \tBC2 format (DXT3)\n");
printf(" -bc3 \tBC3 format (DXT5)\n");
printf(" -bc3n \tBC3 normal map format (DXT5nm)\n");
printf(" -bc4 \tBC4 format (ATI1)\n");
printf(" -bc5 \tBC5 format (3Dc/ATI2)\n");
printf(" -bc6 \tBC6 format\n");
printf(" -bc7 \tBC7 format\n\n");
printf(" -fast Fast compression.\n");
printf(" -nocuda Do not use cuda compressor.\n");
printf(" -rgb RGBA format\n");
printf(" -lumi LUMINANCE format\n");
printf(" -bc1 BC1 format (DXT1)\n");
printf(" -bc1n BC1 normal map format (DXT1nm)\n");
printf(" -bc1a BC1 format with binary alpha (DXT1a)\n");
printf(" -bc2 BC2 format (DXT3)\n");
printf(" -bc3 BC3 format (DXT5)\n");
printf(" -bc3n BC3 normal map format (DXT5nm)\n");
printf(" -bc4 BC4 format (ATI1)\n");
printf(" -bc5 BC5 format (3Dc/ATI2)\n");
printf(" -bc6 BC6 format\n");
printf(" -bc7 BC7 format\n\n");
printf(" -bc3_rgbm BC3-rgbm format\n\n");
printf("Output options:\n");
printf(" -silent \tDo not output progress messages\n");
@ -376,145 +395,211 @@ int main(int argc, char *argv[])
// Set input options.
nvtt::InputOptions inputOptions;
if (nv::strCaseDiff(input.extension(), ".dds") == 0)
{
// Load surface.
nv::DirectDrawSurface dds(input.str());
if (!dds.isValid())
{
fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str());
bool useSurface = false; // @@ use Surface API in all cases!
nvtt::Surface image;
if (true || format == nvtt::Format_BC3_RGBM || rgbm) {
useSurface = true;
if (!image.load(input.str())) {
fprintf(stderr, "Error opening input file '%s'.\n", input.str());
return EXIT_FAILURE;
}
if (!dds.isSupported())
{
fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str());
return EXIT_FAILURE;
}
if (rangescale) {
// get color range
float min_color[3], max_color[3];
image.range(0, &min_color[0], &max_color[0]);
image.range(1, &min_color[1], &max_color[1]);
image.range(2, &min_color[2], &max_color[2]);
uint faceCount;
if (dds.isTexture2D())
{
inputOptions.setTextureLayout(nvtt::TextureType_2D, dds.width(), dds.height());
faceCount = 1;
}
else if (dds.isTexture3D())
{
inputOptions.setTextureLayout(nvtt::TextureType_3D, dds.width(), dds.height(), dds.depth());
faceCount = 1;
//printf("Color range = %.2f %.2f %.2f\n", max_color[0], max_color[1], max_color[2]);
nvDebugBreak();
}
else
{
nvDebugCheck(dds.isTextureCube());
inputOptions.setTextureLayout(nvtt::TextureType_Cube, dds.width(), dds.height());
faceCount = 6;
}
float color_range = nv::max3(max_color[0], max_color[1], max_color[2]);
const float max_color_range = 16.0f;
uint mipmapCount = dds.mipmapCount();
nv::Image mipmap;
for (uint f = 0; f < faceCount; f++)
{
for (uint m = 0; m < mipmapCount; m++)
{
dds.mipmap(&mipmap, f, m); // @@ Load as float.
inputOptions.setMipmapData(mipmap.pixels(), mipmap.width(), mipmap.height(), mipmap.depth(), f, m);
if (color_range > max_color_range) {
//Log::print("Clamping color range %f to %f\n", color_range, max_color_range);
color_range = max_color_range;
}
//color_range = max_color_range; // Use a fixed color range for now.
for (int i = 0; i < 3; i++) {
image.scaleBias(i, 1.0f / color_range, 0.0f);
}
image.toneMap(nvtt::ToneMapper_Linear, /*parameters=*/NULL); // Clamp without changing the hue.
// Clamp alpha.
image.clamp(3);
}
if (alpha) {
image.setAlphaMode(nvtt::AlphaMode_Transparency);
}
// To gamma.
image.toGamma(2);
if (format != nvtt::Format_BC3_RGBM) {
image.setAlphaMode(nvtt::AlphaMode_None);
image.toRGBM(1, 0.15f);
}
}
else
{
if (nv::strCaseDiff(input.extension(), ".exr") == 0 || nv::strCaseDiff(input.extension(), ".hdr") == 0)
{
loadAsFloat = true;
else if (format == nvtt::Format_BC6) {
//format = nvtt::Format_BC1;
//fprintf(stderr, "BLABLABLA.\n");
useSurface = true;
if (!image.load(input.str())) {
fprintf(stderr, "Error opening input file '%s'.\n", input.str());
return EXIT_FAILURE;
}
if (loadAsFloat)
image.setAlphaMode(nvtt::AlphaMode_Transparency);
}
else {
if (nv::strCaseDiff(input.extension(), ".dds") == 0)
{
nv::AutoPtr<nv::FloatImage> image(nv::ImageIO::loadFloat(input.str()));
if (image == NULL)
// Load surface.
nv::DirectDrawSurface dds(input.str());
if (!dds.isValid())
{
fprintf(stderr, "The file '%s' is not a supported image type.\n", input.str());
fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str());
return EXIT_FAILURE;
}
inputOptions.setFormat(nvtt::InputFormat_RGBA_32F);
inputOptions.setTextureLayout(nvtt::TextureType_2D, image->width(), image->height());
/*for (uint i = 0; i < image->componentNum(); i++)
if (!dds.isSupported())
{
inputOptions.setMipmapChannelData(image->channel(i), i, image->width(), image->height());
}*/
fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str());
return EXIT_FAILURE;
}
uint faceCount;
if (dds.isTexture2D())
{
inputOptions.setTextureLayout(nvtt::TextureType_2D, dds.width(), dds.height());
faceCount = 1;
}
else if (dds.isTexture3D())
{
inputOptions.setTextureLayout(nvtt::TextureType_3D, dds.width(), dds.height(), dds.depth());
faceCount = 1;
nvDebugBreak();
}
else
{
nvDebugCheck(dds.isTextureCube());
inputOptions.setTextureLayout(nvtt::TextureType_Cube, dds.width(), dds.height());
faceCount = 6;
}
uint mipmapCount = dds.mipmapCount();
nv::Image mipmap;
for (uint f = 0; f < faceCount; f++)
{
for (uint m = 0; m < mipmapCount; m++)
{
dds.mipmap(&mipmap, f, m); // @@ Load as float.
inputOptions.setMipmapData(mipmap.pixels(), mipmap.width(), mipmap.height(), mipmap.depth(), f, m);
}
}
}
else
{
// Regular image.
nv::Image image;
if (!image.load(input.str()))
if (nv::strCaseDiff(input.extension(), ".exr") == 0 || nv::strCaseDiff(input.extension(), ".hdr") == 0)
{
fprintf(stderr, "The file '%s' is not a supported image type.\n", input.str());
return 1;
loadAsFloat = true;
}
inputOptions.setTextureLayout(nvtt::TextureType_2D, image.width(), image.height());
inputOptions.setMipmapData(image.pixels(), image.width(), image.height());
if (loadAsFloat)
{
nv::AutoPtr<nv::FloatImage> image(nv::ImageIO::loadFloat(input.str()));
if (image == NULL)
{
fprintf(stderr, "The file '%s' is not a supported image type.\n", input.str());
return EXIT_FAILURE;
}
inputOptions.setFormat(nvtt::InputFormat_RGBA_32F);
inputOptions.setTextureLayout(nvtt::TextureType_2D, image->width(), image->height());
/*for (uint i = 0; i < image->componentNum(); i++)
{
inputOptions.setMipmapChannelData(image->channel(i), i, image->width(), image->height());
}*/
}
else
{
// Regular image.
nv::Image image;
if (!image.load(input.str()))
{
fprintf(stderr, "The file '%s' is not a supported image type.\n", input.str());
return 1;
}
inputOptions.setTextureLayout(nvtt::TextureType_2D, image.width(), image.height());
inputOptions.setMipmapData(image.pixels(), image.width(), image.height());
}
}
if (wrapRepeat)
{
inputOptions.setWrapMode(nvtt::WrapMode_Repeat);
}
else
{
inputOptions.setWrapMode(nvtt::WrapMode_Clamp);
}
if (alpha)
{
inputOptions.setAlphaMode(nvtt::AlphaMode_Transparency);
}
else
{
inputOptions.setAlphaMode(nvtt::AlphaMode_None);
}
// Block compressed textures with mipmaps must be powers of two.
if (!noMipmaps && format != nvtt::Format_RGB)
{
inputOptions.setRoundMode(nvtt::RoundMode_ToPreviousPowerOfTwo);
}
if (normal)
{
setNormalMap(inputOptions);
}
else if (color2normal)
{
setColorToNormalMap(inputOptions);
}
else
{
setColorMap(inputOptions);
}
if (noMipmaps)
{
inputOptions.setMipmapGeneration(false);
}
/*if (premultiplyAlpha)
{
inputOptions.setPremultiplyAlpha(true);
inputOptions.setAlphaMode(nvtt::AlphaMode_Premultiplied);
}*/
inputOptions.setMipmapFilter(mipmapFilter);
}
if (wrapRepeat)
{
inputOptions.setWrapMode(nvtt::WrapMode_Repeat);
}
else
{
inputOptions.setWrapMode(nvtt::WrapMode_Clamp);
}
if (alpha)
{
inputOptions.setAlphaMode(nvtt::AlphaMode_Transparency);
}
else
{
inputOptions.setAlphaMode(nvtt::AlphaMode_None);
}
// Block compressed textures with mipmaps must be powers of two.
if (!noMipmaps && format != nvtt::Format_RGB)
{
inputOptions.setRoundMode(nvtt::RoundMode_ToPreviousPowerOfTwo);
}
if (normal)
{
setNormalMap(inputOptions);
}
else if (color2normal)
{
setColorToNormalMap(inputOptions);
}
else
{
setColorMap(inputOptions);
}
if (noMipmaps)
{
inputOptions.setMipmapGeneration(false);
}
/*if (premultiplyAlpha)
{
inputOptions.setPremultiplyAlpha(true);
inputOptions.setAlphaMode(nvtt::AlphaMode_Premultiplied);
}*/
inputOptions.setMipmapFilter(mipmapFilter);
nvtt::CompressionOptions compressionOptions;
compressionOptions.setFormat(format);
@ -545,8 +630,25 @@ int main(int argc, char *argv[])
//compressionOptions.setQuantization(/*color dithering*/true, /*alpha dithering*/false, /*binary alpha*/false);
//compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm);
//compressionOptions.setPixelFormat(5, 6, 5, 0);
//compressionOptions.setPixelFormat(8, 8, 8, 8);
// A4R4G4B4
//compressionOptions.setPixelFormat(16, 0xF00, 0xF0, 0xF, 0xF000);
//compressionOptions.setPixelFormat(32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000);
// R10B20G10A2
//compressionOptions.setPixelFormat(10, 10, 10, 2);
// DXGI_FORMAT_R11G11B10_FLOAT
compressionOptions.setPixelType(nvtt::PixelType_Float);
compressionOptions.setPixelFormat(11, 11, 10, 0);
}
}
else if (format == nvtt::Format_BC6)
{
compressionOptions.setPixelType(nvtt::PixelType_UnsignedFloat);
}
if (fast)
{
@ -599,7 +701,15 @@ int main(int argc, char *argv[])
}
}
outputHandler.setTotal(context.estimateSize(inputOptions, compressionOptions));
int outputSize = 0;
if (useSurface) {
outputSize = context.estimateSize(image, 1, compressionOptions);
}
else {
outputSize = context.estimateSize(inputOptions, compressionOptions);
}
outputHandler.setTotal(outputSize);
outputHandler.setDisplayProgress(!silent);
nvtt::OutputOptions outputOptions;
@ -625,10 +735,22 @@ int main(int argc, char *argv[])
nv::Timer timer;
timer.start();
if (!context.process(inputOptions, compressionOptions, outputOptions))
{
return EXIT_FAILURE;
if (useSurface) {
if (!context.outputHeader(image, 1, compressionOptions, outputOptions)) {
fprintf(stderr, "Error writing file header.\n");
return EXIT_FAILURE;
}
if (!context.compress(image, 0, 0, compressionOptions, outputOptions)) {
fprintf(stderr, "Error compressing file.\n");
return EXIT_FAILURE;
}
}
else {
if (!context.process(inputOptions, compressionOptions, outputOptions)) {
return EXIT_FAILURE;
}
}
timer.stop();
if (!silent) {

View File

@ -29,6 +29,8 @@
#include <nvimage/ImageIO.h>
#include <nvtt/nvtt.h>
#include "cmdline.h"
#include <time.h> // clock
@ -42,6 +44,8 @@ int main(int argc, char *argv[])
bool mipmaps = false;
bool faces = false;
bool savePNG = false;
bool rgbm = false;
bool histogram = true;
nv::Path input;
nv::Path output;
@ -57,10 +61,18 @@ int main(int argc, char *argv[])
{
mipmaps = true;
}
else if (strcmp("-rgbm", argv[i]) == 0)
{
rgbm = true;
}
else if (strcmp("-faces", argv[i]) == 0)
{
faces = true;
}
else if (strcmp("-histogram", argv[i]) == 0)
{
histogram = true;
}
else if (strcmp("-format", argv[i]) == 0)
{
if (i+1 == argc) break;
@ -109,90 +121,125 @@ int main(int argc, char *argv[])
printf("Note: the .tga or .png extension is forced on outfile\n\n");
printf("Input options:\n");
printf(" -forcenormal \tThe input image is a normal map.\n");
printf(" -mipmaps \tDecompress all mipmaps.\n");
printf(" -faces \tDecompress all faces.\n");
printf(" -format <format>\tOutput format ('tga' or 'png').\n");
printf(" -forcenormal The input image is a normal map.\n");
printf(" -mipmaps Decompress all mipmaps.\n");
printf(" -faces Decompress all faces.\n");
printf(" -histogram Output histogram.\n");
printf(" -format <format> Output format ('tga' or 'png').\n");
return 1;
}
// Load surface.
// !!! DirectDrawSurface API doesn't support float images, so BC6 will be converted to 8-bit on load.
// Should use nvtt::Surface instead.
nv::DirectDrawSurface dds(input.str());
if (!dds.isValid())
{
fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str());
return 1;
}
if (!dds.isSupported() || dds.isTexture3D())
{
fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str());
return 1;
}
uint faceCount;
if (dds.isTexture2D())
{
faceCount = 1;
}
else
{
nvCheck(dds.isTextureCube());
faceCount = 6;
}
uint mipmapCount = dds.mipmapCount();
clock_t start = clock();
// apply arguments
if (forcenormal)
{
dds.setNormalFlag(true);
}
if (!faces)
{
faceCount = 1;
}
if (!mipmaps)
{
mipmapCount = 1;
}
if (histogram) {
nvtt::Surface img;
if (!img.load(input.str())) {
fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str());
return 1;
}
nv::Image mipmap;
nv::Path name;
float exposure = 2.2f;
float scale = 1.0f / exposure;
img.scaleBias(0, scale, 0);
img.scaleBias(1, scale, 0);
img.scaleBias(2, scale, 0);
// strip extension, we force the tga extension
output.stripExtension();
//img.toneMap(nvtt::ToneMapper_Reindhart, NULL);
//img.toSrgb();
img.toGamma(2.2f);
// extract faces and mipmaps
for (uint f = 0; f < faceCount; f++)
{
for (uint m = 0; m < mipmapCount; m++)
{
dds.mipmap(&mipmap, f, m);
// set output filename, if we are doing faces and/or mipmaps
name.copy(output);
if (faces) name.appendFormat("_face%d", f);
if (mipmaps) name.appendFormat("_mipmap%d", m);
name.append(savePNG ? ".png" : ".tga");
nv::StdOutputStream stream(name.str());
if (stream.isError()) {
fprintf(stderr, "Error opening '%s' for writting\n", name.str());
return 1;
}
nv::ImageIO::save(name.str(), stream, &mipmap);
}
}
nvtt::Surface hist = nvtt::histogram(img, 3*512, 128);
clock_t end = clock();
printf("\rtime taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC);
// Resize for pretier histograms.
hist.resize(512, 128, 1, nvtt::ResizeFilter_Box);
nv::Path name;
name.copy(output);
name.stripExtension();
name.append(".histogram");
name.append(savePNG ? ".png" : ".tga");
hist.save(name.str());
}
else {
// Load surface.
// !!! DirectDrawSurface API doesn't support float images, so BC6 will be converted to 8-bit on load.
// Should use nvtt::Surface instead.
nv::DirectDrawSurface dds(input.str());
if (!dds.isValid())
{
fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str());
return 1;
}
if (!dds.isSupported() || dds.isTexture3D())
{
fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str());
return 1;
}
uint faceCount;
if (dds.isTexture2D())
{
faceCount = 1;
}
else
{
nvCheck(dds.isTextureCube());
faceCount = 6;
}
uint mipmapCount = dds.mipmapCount();
clock_t start = clock();
// apply arguments
if (forcenormal)
{
dds.setNormalFlag(true);
}
if (!faces)
{
faceCount = 1;
}
if (!mipmaps)
{
mipmapCount = 1;
}
nv::Image mipmap;
nv::Path name;
// strip extension, we force the tga extension
output.stripExtension();
// extract faces and mipmaps
for (uint f = 0; f < faceCount; f++)
{
for (uint m = 0; m < mipmapCount; m++)
{
dds.mipmap(&mipmap, f, m);
// set output filename, if we are doing faces and/or mipmaps
name.copy(output);
if (faces) name.appendFormat("_face%d", f);
if (mipmaps) name.appendFormat("_mipmap%d", m);
name.append(savePNG ? ".png" : ".tga");
nv::StdOutputStream stream(name.str());
if (stream.isError()) {
fprintf(stderr, "Error opening '%s' for writting\n", name.str());
return 1;
}
nv::ImageIO::save(name.str(), stream, &mipmap);
}
}
clock_t end = clock();
printf("\rtime taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC);
}
return 0;
}

View File

@ -23,18 +23,15 @@
#include "cmdline.h"
#include "nvmath/Color.h"
#include "nvmath/Vector.inl"
#include "nvimage/Image.h"
#include "nvimage/DirectDrawSurface.h"
#include "nvtt/nvtt.h"
#include "nvcore/StrLib.h"
#include "nvcore/StdStream.h"
#include "nvmath/nvmath.h"
#include <string.h> // strstr
#include <math.h>
/*
static bool loadImage(nv::Image & image, const char * fileName)
{
if (nv::strCaseDiff(nv::Path::extension(fileName), ".dds") == 0)
@ -160,7 +157,7 @@ static float luma(const nv::Color32 & c) {
//return 0.333f * float(c.r) + 0.334f * float(c.g) + 0.333f * float(c.b);
//return 0.1f * float(c.r) + 0.8f * float(c.g) + 0.1f * float(c.g);
}
*/
int main(int argc, char *argv[])
{
@ -169,6 +166,7 @@ int main(int argc, char *argv[])
bool compareNormal = false;
bool compareAlpha = false;
bool rangescale = false;
nv::Path input0;
nv::Path input1;
@ -178,14 +176,18 @@ int main(int argc, char *argv[])
for (int i = 1; i < argc; i++)
{
// Input options.
if (strcmp("-normal", argv[i]) == 0)
if (nv::strEqual("-normal", argv[i]))
{
compareNormal = true;
}
else if (strcmp("-alpha", argv[i]) == 0)
else if (nv::strEqual("-alpha", argv[i]))
{
compareAlpha = true;
}
else if (nv::strEqual("-rangescale", argv[i]))
{
rangescale = true;
}
else if (argv[i][0] != '-')
{
input0 = argv[i];
@ -209,12 +211,105 @@ int main(int argc, char *argv[])
printf("usage: nvimgdiff [options] original_file updated_file [output]\n\n");
printf("Diff options:\n");
printf(" -normal \tCompare images as if they were normal maps.\n");
printf(" -alpha \tCompare alpha weighted images.\n");
printf(" -normal Compare images as if they were normal maps.\n");
printf(" -alpha Compare alpha weighted images.\n");
printf(" -rangescale Scale second image based on range of first one.\n");
return 1;
}
nvtt::Surface image0, image1;
if (!image0.load(input0.str())) {
printf("Error loading %s.", input0.str());
return 1;
}
if (!image1.load(input1.str())) {
printf("Error loading %s.", input1.str());
return 1;
}
if (compareNormal) {
image0.setNormalMap(true);
image1.setNormalMap(true);
}
if (compareAlpha) {
image0.setAlphaMode(nvtt::AlphaMode_Transparency);
}
// Do some transforms based on the naming convention of the file.
if (strstr(input1.str(), "rgbm")) {
//image0.toGamma(2);
image1.fromRGBM(1.0f, 0.25f);
image1.toLinear(2);
image1.copyChannel(image0, 3); // Copy alpha channel from source.
image1.setAlphaMode(nvtt::AlphaMode_Transparency);
rangescale = true;
}
if (strstr(input1.str(), "bc6")) {
// @@ Do any transform that we may have done before compression.
image1.copyChannel(image0, 3); // Copy alpha channel from source.
image1.setAlphaMode(nvtt::AlphaMode_Transparency);
}
// Scale second image to range of the first one.
if (rangescale) {
float min_color[3], max_color[3];
image0.range(0, &min_color[0], &max_color[0]);
image0.range(1, &min_color[1], &max_color[1]);
image0.range(2, &min_color[2], &max_color[2]);
float color_range = nv::max3(max_color[0], max_color[1], max_color[2]);
const float max_color_range = 16.0f;
if (color_range > max_color_range) color_range = max_color_range;
#if 0
for (int i = 0; i < 3; i++) {
image0.scaleBias(i, 1.0f / color_range, 0.0f);
}
image0.toneMap(nvtt::ToneMapper_Linear, NULL); // Clamp without changing the hue.
#else
for (int i = 0; i < 3; i++) {
image1.scaleBias(i, color_range, 0.0f);
}
#endif
}
float rmse = nvtt::rmsError(image0, image1);
//float rmsa = nvtt::rmsAlphaError(image0, image1);
// In The Witness:
// exposure = key_value / luminance
// key_value = 0.22
// min_luminance = 0.1 -> exposure = 2.2
// max_luminance = 1.0 -> exposure = 0.22
float rmse0 = nvtt::rmsToneMappedError(image0, image1, 2.2f);
float rmse1 = nvtt::rmsToneMappedError(image0, image1, 1.0f);
float rmse2 = nvtt::rmsToneMappedError(image0, image1, 0.22f);
printf("RMSE = %.5f %.5f %.5f -> %.5f | %.5f\n", rmse0, rmse1, rmse2, (rmse0 + rmse1 + rmse2)/3, rmse);
//printf("MSE = %f\n", rmse * rmse);
//printf("RMSE = %f\n", rmse);
//printf("PSNR = %f\n", (rmse == 0) ? 999.0 : 20.0 * log10(255.0 / rmse));
if (compareNormal) {
// @@ Does this assume normal maps are packed or unpacked?
float ae = nvtt::angularError(image0, image1);
printf("AE = %f\n", ae);
}
#if 0
nv::Image image0, image1;
if (!loadImage(image0, input0.str())) return 0;
if (!loadImage(image1, input1.str())) return 0;
@ -304,6 +399,7 @@ int main(int argc, char *argv[])
error_a.print();
}
#endif
// @@ Write image difference.
return 0;