Fix errors in new implementation of InputOptions.

Output cube map faces in DDS order. Fixes issue 147.
pull/216/head
castano 14 years ago
parent 5225f4810f
commit c1204bfb66

@ -129,16 +129,19 @@ Image * FloatImage::createImageGammaCorrect(float gamma/*= 2.2f*/) const
return img.release(); return img.release();
} }
/// Allocate a 2d float image of the given format and the given extents. /// Allocate a 2D float image of the given format and the given extents.
void FloatImage::allocate(uint c, uint w, uint h) void FloatImage::allocate(uint c, uint w, uint h)
{ {
free(); if (m_componentNum != c || m_width != w || m_height != h)
{
free();
m_width = w; m_width = w;
m_height = h; m_height = h;
m_componentNum = c; m_componentNum = c;
m_count = w * h * c; m_count = w * h * c;
m_mem = malloc<float>(m_count); m_mem = malloc<float>(m_count);
}
} }
/// Free the image, but don't clear the members. /// Free the image, but don't clear the members.
@ -1034,16 +1037,9 @@ void FloatImage::scaleAlphaToCoverage(float desiredCoverage, float alphaRef, int
FloatImage* FloatImage::clone() const FloatImage* FloatImage::clone() const
{ {
FloatImage* copy = new FloatImage(); FloatImage* copy = new FloatImage();
copy->m_width = m_width;
copy->m_height = m_height;
copy->m_componentNum = m_componentNum;
copy->m_count = m_count;
if(m_mem) copy->allocate(m_componentNum, m_width, m_height);
{ memcpy(copy->m_mem, m_mem, m_count * sizeof(float));
copy->allocate(m_componentNum, m_width, m_height);
memcpy(copy->m_mem, m_mem, m_count * sizeof(float));
}
return copy; return copy;
} }

@ -52,59 +52,10 @@
#include "nvcore/Memory.h" #include "nvcore/Memory.h"
#include "nvcore/Ptr.h" #include "nvcore/Ptr.h"
using namespace nv; using namespace nv;
using namespace nvtt; using namespace nvtt;
namespace
{
static int blockSize(Format format)
{
if (format == Format_DXT1 || format == Format_DXT1a || format == Format_DXT1n) {
return 8;
}
else if (format == Format_DXT3) {
return 16;
}
else if (format == Format_DXT5 || format == Format_DXT5n) {
return 16;
}
else if (format == Format_BC4) {
return 8;
}
else if (format == Format_BC5) {
return 16;
}
else if (format == Format_CTX1) {
return 8;
}
else if (format == Format_BC6) {
return 16;
}
else if (format == Format_BC7) {
return 16;
}
return 0;
}
static int computeImageSize(uint w, uint h, uint d, uint bitCount, uint alignment, Format format)
{
if (format == Format_RGBA) {
return d * h * computePitch(w, bitCount, alignment);
}
else {
// @@ Handle 3D textures. DXT and VTC have different behaviors.
return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format);
}
}
} // namespace
Compressor::Compressor() : m(*new Compressor::Private()) Compressor::Compressor() : m(*new Compressor::Private())
{ {
@ -166,12 +117,12 @@ bool Compressor::process(const InputOptions & inputOptions, const CompressionOpt
int Compressor::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const int Compressor::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const
{ {
// @@ Compute w, h, mipmapCount based on inputOptions settings. int w = inputOptions.m.width;
const int w = 0; int h = inputOptions.m.height;
const int h = 0; int d = inputOptions.m.depth;
const int d = 1; getTargetExtent(w, h, d, inputOptions.m.maxExtent, inputOptions.m.roundMode, inputOptions.m.textureType);
int mipmapCount = 1;
int mipmapCount = countMipmaps(w, h, d);
return inputOptions.m.faceCount * estimateSize(w, h, d, mipmapCount, compressionOptions); return inputOptions.m.faceCount * estimateSize(w, h, d, mipmapCount, compressionOptions);
} }
@ -179,7 +130,7 @@ int Compressor::estimateSize(const InputOptions & inputOptions, const Compressio
// TexImage API. // TexImage API.
bool Compressor::outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const bool Compressor::outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
{ {
return m.outputHeader(tex, mipmapCount, compressionOptions.m, outputOptions.m); return m.outputHeader(TextureType_2D, tex.width(), tex.height(), tex.depth(), mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m);
} }
bool Compressor::compress(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const bool Compressor::compress(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
@ -192,9 +143,8 @@ int Compressor::estimateSize(const TexImage & tex, int mipmapCount, const Compre
const int w = tex.width(); const int w = tex.width();
const int h = tex.height(); const int h = tex.height();
const int d = tex.depth(); const int d = tex.depth();
const int faceCount = tex.faceCount();
return faceCount * estimateSize(w, h, d, mipmapCount, compressionOptions); return estimateSize(w, h, d, mipmapCount, compressionOptions);
} }
@ -244,7 +194,6 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
} }
nvtt::TexImage img; nvtt::TexImage img;
img.setTextureType(inputOptions.textureType);
img.setWrapMode(inputOptions.wrapMode); img.setWrapMode(inputOptions.wrapMode);
img.setAlphaMode(inputOptions.alphaMode); img.setAlphaMode(inputOptions.alphaMode);
img.setNormalMap(inputOptions.isNormalMap); img.setNormalMap(inputOptions.isNormalMap);
@ -254,108 +203,112 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
int h = inputOptions.height; int h = inputOptions.height;
int d = inputOptions.depth; int d = inputOptions.depth;
for (int f = 0; f < faceCount; f++) nv::getTargetExtent(w, h, d, inputOptions.maxExtent, inputOptions.roundMode, inputOptions.textureType);
{
img.setImage2D(inputOptions.inputFormat, w, h, f, inputOptions.images[f]);
}
// To linear space.
if (!inputOptions.isNormalMap) {
img.toLinear(inputOptions.inputGamma);
}
// Resize input.
img.resize(inputOptions.maxExtent, inputOptions.roundMode, ResizeFilter_Box);
// If the extents have not change we can use source images for the mipmaps. // If the extents have not changed, then we can use source images for all mipmaps.
bool canUseSourceImages = (img.width() == w && img.height() == h); bool canUseSourceImages = (inputOptions.width == w && inputOptions.height == h && inputOptions.depth == d);
int mipmapCount = 1; int mipmapCount = 1;
if (inputOptions.generateMipmaps) { if (inputOptions.generateMipmaps) {
mipmapCount = img.countMipmaps(); mipmapCount = countMipmaps(w, h, d);
if (inputOptions.maxLevel > 0) mipmapCount = min(mipmapCount, inputOptions.maxLevel); if (inputOptions.maxLevel > 0) mipmapCount = min(mipmapCount, inputOptions.maxLevel);
} }
if (!outputHeader(img, mipmapCount, compressionOptions, outputOptions)) if (!outputHeader(inputOptions.textureType, w, h, d, mipmapCount, img.isNormalMap(), compressionOptions, outputOptions))
{ {
return false; return false;
} }
nvtt::TexImage tmp = img;
if (!inputOptions.isNormalMap) {
tmp.toGamma(inputOptions.outputGamma);
}
// @@ Fix order of cubemap faces! // Output images.
for (int f = 0; f < faceCount; f++)
{
img.setImage2D(inputOptions.inputFormat, inputOptions.width, inputOptions.height, inputOptions.images[f]);
// To normal map.
if (inputOptions.convertToNormalMap) {
img.toGreyScale(inputOptions.heightFactors.x, inputOptions.heightFactors.y, inputOptions.heightFactors.z, inputOptions.heightFactors.w);
img.toNormalMap(inputOptions.bumpFrequencyScale.x, inputOptions.bumpFrequencyScale.y, inputOptions.bumpFrequencyScale.z, inputOptions.bumpFrequencyScale.w);
}
quantize(tmp, compressionOptions); // To linear space.
compress(tmp, compressionOptions, outputOptions); if (!img.isNormalMap()) {
img.toLinear(inputOptions.inputGamma);
}
for (int m = 1; m < mipmapCount; m++) { // Resize input.
w = max(1, w/2); img.resize(w, h, ResizeFilter_Box);
h = max(1, h/2);
d = max(1, d/2); nvtt::TexImage tmp = img;
if (!img.isNormalMap()) {
tmp.toGamma(inputOptions.outputGamma);
}
int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format); int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format);
outputOptions.beginImage(size, w, h, d, 0, m); outputOptions.beginImage(size, w, h, d, f, 0);
quantize(tmp, compressionOptions);
compress(tmp, compressionOptions, outputOptions);
bool useSourceImages = false; for (int m = 1; m < mipmapCount; m++) {
if (canUseSourceImages) { w = max(1, w/2);
useSourceImages = true; h = max(1, h/2);
for (int f = 0; f < faceCount; f++) { d = max(1, d/2);
int idx = m * faceCount + f;
int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format);
outputOptions.beginImage(size, w, h, d, f, m);
int idx = m * faceCount + f;
bool useSourceImages = false;
if (canUseSourceImages) {
useSourceImages = true;
if (inputOptions.images[idx] == NULL) { // One face is missing in this mipmap level. if (inputOptions.images[idx] == NULL) { // One face is missing in this mipmap level.
useSourceImages = false; useSourceImages = false;
canUseSourceImages = false; // If one level is missing, ignore the following source images. canUseSourceImages = false; // If one level is missing, ignore the following source images.
break;
} }
} }
}
if (useSourceImages) { if (useSourceImages) {
for (int f = 0; f < faceCount; f++) { img.setImage2D(inputOptions.inputFormat, w, h, inputOptions.images[idx]);
int idx = m * faceCount + f;
img.setImage2D(inputOptions.inputFormat, w, h, f, inputOptions.images[idx]);
}
}
else {
if (inputOptions.mipmapFilter == MipmapFilter_Kaiser) {
float params[2] = { inputOptions.kaiserStretch, inputOptions.kaiserAlpha };
img.buildNextMipmap(MipmapFilter_Kaiser, inputOptions.kaiserWidth, params);
} }
else { else {
img.buildNextMipmap(inputOptions.mipmapFilter); if (inputOptions.mipmapFilter == MipmapFilter_Kaiser) {
float params[2] = { inputOptions.kaiserStretch, inputOptions.kaiserAlpha };
img.buildNextMipmap(MipmapFilter_Kaiser, inputOptions.kaiserWidth, params);
}
else {
img.buildNextMipmap(inputOptions.mipmapFilter);
}
} }
} nvDebugCheck(img.width() == w);
nvDebugCheck(img.width() == w); nvDebugCheck(img.height() == h);
nvDebugCheck(img.height() == h);
if (inputOptions.isNormalMap) { if (img.isNormalMap()) {
if (inputOptions.normalizeMipmaps) { if (inputOptions.normalizeMipmaps) {
img.normalizeNormalMap(); img.normalizeNormalMap();
}
tmp = img;
}
else {
tmp = img;
tmp.toGamma(inputOptions.outputGamma);
} }
tmp = img;
}
else {
tmp = img;
tmp.toGamma(inputOptions.outputGamma);
}
quantize(tmp, compressionOptions); quantize(tmp, compressionOptions);
compress(tmp, compressionOptions, outputOptions); compress(tmp, compressionOptions, outputOptions);
}; }
}
return true; return true;
} }
bool Compressor::Private::compress(const TexImage & tex, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const bool Compressor::Private::compress(const TexImage & tex, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
{ {
foreach(i, tex.m->imageArray) { if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), tex.data(), compressionOptions, outputOptions)) {
FloatImage * image = tex.m->imageArray[i]; return false;
if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), image->channel(0), compressionOptions, outputOptions)) {
return false;
}
} }
return true; return true;
} }
@ -414,9 +367,9 @@ bool Compressor::Private::quantize(TexImage & img, const CompressionOptions::Pri
} }
bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
{ {
if (tex.width() <= 0 || tex.height() <= 0 || tex.depth() <= 0 || mipmapCount <= 0) if (w <= 0 || h <= 0 || d <= 0 || mipmapCount <= 0)
{ {
outputOptions.error(Error_InvalidInput); outputOptions.error(Error_InvalidInput);
return false; return false;
@ -434,19 +387,19 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
header.setUserVersion(outputOptions.version); header.setUserVersion(outputOptions.version);
if (tex.textureType() == TextureType_2D) { if (textureType == TextureType_2D) {
header.setTexture2D(); header.setTexture2D();
} }
else if (tex.textureType() == TextureType_Cube) { else if (textureType == TextureType_Cube) {
header.setTextureCube(); header.setTextureCube();
} }
/*else if (tex.textureType() == TextureType_3D) { /*else if (textureType == TextureType_3D) {
header.setTexture3D(); header.setTexture3D();
header.setDepth(tex.depth()); header.setDepth(d);
}*/ }*/
header.setWidth(tex.width()); header.setWidth(w);
header.setHeight(tex.height()); header.setHeight(h);
header.setMipmapCount(mipmapCount); header.setMipmapCount(mipmapCount);
bool supported = true; bool supported = true;
@ -490,7 +443,7 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) { if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) {
header.setDX10Format(70); // DXGI_FORMAT_BC1_TYPELESS header.setDX10Format(70); // DXGI_FORMAT_BC1_TYPELESS
if (compressionOptions.format == Format_DXT1a) header.setHasAlphaFlag(true); if (compressionOptions.format == Format_DXT1a) header.setHasAlphaFlag(true);
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else if (compressionOptions.format == Format_DXT3) { else if (compressionOptions.format == Format_DXT3) {
header.setDX10Format(73); // DXGI_FORMAT_BC2_TYPELESS header.setDX10Format(73); // DXGI_FORMAT_BC2_TYPELESS
@ -500,21 +453,21 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
} }
else if (compressionOptions.format == Format_DXT5n) { else if (compressionOptions.format == Format_DXT5n) {
header.setDX10Format(76); // DXGI_FORMAT_BC3_TYPELESS header.setDX10Format(76); // DXGI_FORMAT_BC3_TYPELESS
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else if (compressionOptions.format == Format_BC4) { else if (compressionOptions.format == Format_BC4) {
header.setDX10Format(79); // DXGI_FORMAT_BC4_TYPELESS header.setDX10Format(79); // DXGI_FORMAT_BC4_TYPELESS
} }
else if (compressionOptions.format == Format_BC5) { else if (compressionOptions.format == Format_BC5) {
header.setDX10Format(82); // DXGI_FORMAT_BC5_TYPELESS header.setDX10Format(82); // DXGI_FORMAT_BC5_TYPELESS
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else if (compressionOptions.format == Format_BC6) { else if (compressionOptions.format == Format_BC6) {
header.setDX10Format(94); // DXGI_FORMAT_BC6H_TYPELESS header.setDX10Format(94); // DXGI_FORMAT_BC6H_TYPELESS
} }
else if (compressionOptions.format == Format_BC7) { else if (compressionOptions.format == Format_BC7) {
header.setDX10Format(97); // DXGI_FORMAT_BC7_TYPELESS header.setDX10Format(97); // DXGI_FORMAT_BC7_TYPELESS
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else { else {
supported = false; supported = false;
@ -526,7 +479,7 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
if (compressionOptions.format == Format_RGBA) if (compressionOptions.format == Format_RGBA)
{ {
// Get output bit count. // Get output bit count.
header.setPitch(computePitch(tex.width(), compressionOptions.getBitCount(), compressionOptions.pitchAlignment)); header.setPitch(computePitch(w, compressionOptions.getBitCount(), compressionOptions.pitchAlignment));
if (compressionOptions.pixelType == PixelType_Float) if (compressionOptions.pixelType == PixelType_Float)
{ {
@ -591,11 +544,11 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
} }
else else
{ {
header.setLinearSize(computeImageSize(tex.width(), tex.height(), tex.depth(), compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format)); header.setLinearSize(computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format));
if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) { if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) {
header.setFourCC('D', 'X', 'T', '1'); header.setFourCC('D', 'X', 'T', '1');
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else if (compressionOptions.format == Format_DXT3) { else if (compressionOptions.format == Format_DXT3) {
header.setFourCC('D', 'X', 'T', '3'); header.setFourCC('D', 'X', 'T', '3');
@ -605,7 +558,7 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
} }
else if (compressionOptions.format == Format_DXT5n) { else if (compressionOptions.format == Format_DXT5n) {
header.setFourCC('D', 'X', 'T', '5'); header.setFourCC('D', 'X', 'T', '5');
if (tex.isNormalMap()) { if (isNormalMap) {
header.setNormalFlag(true); header.setNormalFlag(true);
header.setSwizzleCode('A', '2', 'D', '5'); header.setSwizzleCode('A', '2', 'D', '5');
//header.setSwizzleCode('x', 'G', 'x', 'R'); //header.setSwizzleCode('x', 'G', 'x', 'R');
@ -616,7 +569,7 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
} }
else if (compressionOptions.format == Format_BC5) { else if (compressionOptions.format == Format_BC5) {
header.setFourCC('A', 'T', 'I', '2'); header.setFourCC('A', 'T', 'I', '2');
if (tex.isNormalMap()) { if (isNormalMap) {
header.setNormalFlag(true); header.setNormalFlag(true);
header.setSwizzleCode('A', '2', 'X', 'Y'); header.setSwizzleCode('A', '2', 'X', 'Y');
} }
@ -626,11 +579,11 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
} }
else if (compressionOptions.format == Format_BC7) { else if (compressionOptions.format == Format_BC7) {
header.setFourCC('Z', 'O', 'L', 'A'); header.setFourCC('Z', 'O', 'L', 'A');
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else if (compressionOptions.format == Format_CTX1) { else if (compressionOptions.format == Format_CTX1) {
header.setFourCC('C', 'T', 'X', '1'); header.setFourCC('C', 'T', 'X', '1');
if (tex.isNormalMap()) header.setNormalFlag(true); if (isNormalMap) header.setNormalFlag(true);
} }
else { else {
supported = false; supported = false;

@ -49,8 +49,8 @@ namespace nvtt
bool quantize(TexImage & tex, const CompressionOptions::Private & compressionOptions) const; bool quantize(TexImage & tex, const CompressionOptions::Private & compressionOptions) const;
bool outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; bool outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
bool outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; //bool outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
nv::CompressorInterface * chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const; nv::CompressorInterface * chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const;
nv::CompressorInterface * chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const; nv::CompressorInterface * chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const;

@ -143,36 +143,12 @@ void InputOptions::setTextureLayout(TextureType type, int width, int height, int
m.depth = depth; m.depth = depth;
// Allocate images. // Allocate images.
m.faceCount = (type == TextureType_2D) ? 1 : 6; m.faceCount = (type == TextureType_Cube) ? 6 : 1;
m.mipmapCount = countMipmaps(width, height, depth); m.mipmapCount = countMipmaps(width, height, depth);
m.imageCount = m.mipmapCount * m.faceCount; m.imageCount = m.mipmapCount * m.faceCount;
m.images = new void *[m.imageCount]; m.images = new void *[m.imageCount];
memset(m.images, 0, sizeof(void *) * m.imageCount); memset(m.images, 0, sizeof(void *) * m.imageCount);
/*for (uint f = 0; f < m.faceCount; f++)
{
uint w = width;
uint h = height;
uint d = depth;
for (uint mipLevel = 0; mipLevel < m.mipmapCount; mipLevel++)
{
Private::InputImage & img = m.images[f * m.mipmapCount + mipLevel];
img.width = w;
img.height = h;
img.depth = d;
img.mipLevel = mipLevel;
img.face = f;
img.uint8data = NULL;
img.floatdata = NULL;
w = max(1U, w / 2);
h = max(1U, h / 2);
d = max(1U, d / 2);
}
}*/
} }
@ -180,6 +156,11 @@ void InputOptions::resetTextureLayout()
{ {
if (m.images != NULL) if (m.images != NULL)
{ {
// Delete images.
for (int i = 0; i < m.imageCount; i++) {
free(m.images[i]);
}
// Delete image array. // Delete image array.
delete [] m.images; delete [] m.images;
m.images = NULL; m.images = NULL;
@ -240,7 +221,7 @@ bool InputOptions::setMipmapData(const void * data, int width, int height, int d
return false; return false;
} }
m.images[idx] = new uint8[imageSize]; m.images[idx] = realloc(m.images[idx], imageSize);
if (m.images[idx] == NULL) { if (m.images[idx] == NULL) {
// Out of memory. // Out of memory.
return false; return false;

@ -28,27 +28,27 @@ using namespace nvtt;
OutputOptions::OutputOptions() : m(*new OutputOptions::Private()) OutputOptions::OutputOptions() : m(*new OutputOptions::Private())
{ {
reset(); reset();
} }
OutputOptions::~OutputOptions() OutputOptions::~OutputOptions()
{ {
// Cleanup output handler. // Cleanup output handler.
setOutputHandler(NULL); setOutputHandler(NULL);
delete &m; delete &m;
} }
/// Set default output options. /// Set default output options.
void OutputOptions::reset() void OutputOptions::reset()
{ {
m.fileName.reset(); m.fileName.reset();
m.outputHandler = NULL; m.outputHandler = NULL;
m.errorHandler = NULL; m.errorHandler = NULL;
m.outputHeader = true; m.outputHeader = true;
m.container = Container_DDS; m.container = Container_DDS;
m.version = 0; m.version = 0;
} }
@ -56,78 +56,78 @@ void OutputOptions::reset()
/// Set output file name. /// Set output file name.
void OutputOptions::setFileName(const char * fileName) void OutputOptions::setFileName(const char * fileName)
{ {
if (!m.fileName.isNull()) if (!m.fileName.isNull())
{ {
// To close the file and avoid leak. // To close the file and avoid leak.
delete m.outputHandler; delete m.outputHandler;
} }
m.fileName = fileName; m.fileName = fileName;
m.outputHandler = NULL; m.outputHandler = NULL;
DefaultOutputHandler * oh = new DefaultOutputHandler(fileName); DefaultOutputHandler * oh = new DefaultOutputHandler(fileName);
if (!oh->stream.isError()) if (!oh->stream.isError())
{ {
m.outputHandler = oh; m.outputHandler = oh;
} }
} }
/// Set output handler. /// Set output handler.
void OutputOptions::setOutputHandler(OutputHandler * outputHandler) void OutputOptions::setOutputHandler(OutputHandler * outputHandler)
{ {
if (!m.fileName.isNull()) if (!m.fileName.isNull())
{ {
delete m.outputHandler; delete m.outputHandler;
m.fileName.reset(); m.fileName.reset();
} }
m.outputHandler = outputHandler; m.outputHandler = outputHandler;
} }
/// Set error handler. /// Set error handler.
void OutputOptions::setErrorHandler(ErrorHandler * errorHandler) void OutputOptions::setErrorHandler(ErrorHandler * errorHandler)
{ {
m.errorHandler = errorHandler; m.errorHandler = errorHandler;
} }
/// Set output header. /// Set output header.
void OutputOptions::setOutputHeader(bool outputHeader) void OutputOptions::setOutputHeader(bool outputHeader)
{ {
m.outputHeader = outputHeader; m.outputHeader = outputHeader;
} }
/// Set container. /// Set container.
void OutputOptions::setContainer(Container container) void OutputOptions::setContainer(Container container)
{ {
m.container = container; m.container = container;
} }
/// Set user version. /// Set user version.
void OutputOptions::setUserVersion(int version) void OutputOptions::setUserVersion(int version)
{ {
m.version = version; m.version = version;
} }
bool OutputOptions::Private::hasValidOutputHandler() const bool OutputOptions::Private::hasValidOutputHandler() const
{ {
if (!fileName.isNull()) if (!fileName.isNull())
{ {
return outputHandler != NULL; return outputHandler != NULL;
} }
return true; return true;
} }
void OutputOptions::Private::beginImage(int size, int width, int height, int depth, int face, int miplevel) const void OutputOptions::Private::beginImage(int size, int width, int height, int depth, int face, int miplevel) const
{ {
if (outputHandler != NULL) outputHandler->beginImage(size, width, height, depth, face, miplevel); if (outputHandler != NULL) outputHandler->beginImage(size, width, height, depth, face, miplevel);
} }
bool OutputOptions::Private::writeData(const void * data, int size) const bool OutputOptions::Private::writeData(const void * data, int size) const
{ {
return outputHandler == NULL || outputHandler->writeData(data, size); return outputHandler == NULL || outputHandler->writeData(data, size);
} }
void OutputOptions::Private::error(Error e) const void OutputOptions::Private::error(Error e) const
{ {
if (errorHandler != NULL) errorHandler->error(e); if (errorHandler != NULL) errorHandler->error(e);
} }

File diff suppressed because it is too large Load Diff

@ -49,7 +49,7 @@ namespace nvtt
alphaMode = AlphaMode_None; alphaMode = AlphaMode_None;
isNormalMap = false; isNormalMap = false;
imageArray.resize(1, NULL); image = NULL;
} }
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0. Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
{ {
@ -60,17 +60,11 @@ namespace nvtt
alphaMode = p.alphaMode; alphaMode = p.alphaMode;
isNormalMap = p.isNormalMap; isNormalMap = p.isNormalMap;
imageArray.reserve(p.imageArray.count()); image = p.image->clone();
foreach(i, p.imageArray) {
imageArray.append(p.imageArray[i]->clone());
}
} }
~Private() ~Private()
{ {
const uint count = imageArray.count(); delete image;
for (uint i = 0; i < count; i++) {
delete imageArray[i];
}
} }
TextureType type; TextureType type;
@ -78,11 +72,16 @@ namespace nvtt
AlphaMode alphaMode; AlphaMode alphaMode;
bool isNormalMap; bool isNormalMap;
nv::Array<nv::FloatImage *> imageArray; nv::FloatImage * image;
}; };
} // nvtt namespace } // nvtt namespace
namespace nv {
uint countMipmaps(uint w, uint h, uint d);
uint computeImageSize(uint w, uint h, uint d, uint bitCount, uint alignment, nvtt::Format format);
void getTargetExtent(int & w, int & h, int & d, int maxExtent, nvtt::RoundMode roundMode, nvtt::TextureType textureType);
}
#endif // NVTT_TEXIMAGE_H #endif // NVTT_TEXIMAGE_H

@ -28,30 +28,30 @@ using namespace nvtt;
/// Return a string for the given error. /// Return a string for the given error.
const char * nvtt::errorString(Error e) const char * nvtt::errorString(Error e)
{ {
switch(e) switch(e)
{ {
case Error_Unknown: case Error_Unknown:
return "Unknown error"; return "Unknown error";
case Error_InvalidInput: case Error_InvalidInput:
return "Invalid input"; return "Invalid input";
case Error_UnsupportedFeature: case Error_UnsupportedFeature:
return "Unsupported feature"; return "Unsupported feature";
case Error_CudaError: case Error_CudaError:
return "CUDA error"; return "CUDA error";
case Error_FileOpen: case Error_FileOpen:
return "Error opening file"; return "Error opening file";
case Error_FileWrite: case Error_FileWrite:
return "Error writing through output handler"; return "Error writing through output handler";
case Error_UnsupportedOutputFormat: case Error_UnsupportedOutputFormat:
return "The container file does not support the selected output format"; return "The container file does not support the selected output format";
} }
return "Invalid error"; return "Invalid error";
} }
/// Return NVTT version. /// Return NVTT version.
unsigned int nvtt::version() unsigned int nvtt::version()
{ {
return NVTT_VERSION; return NVTT_VERSION;
} }

@ -379,29 +379,28 @@ namespace nvtt
NVTT_API void operator=(const TexImage & tex); NVTT_API void operator=(const TexImage & tex);
// Texture parameters. // Texture parameters.
NVTT_API void setTextureType(TextureType type);
NVTT_API void setWrapMode(WrapMode mode); NVTT_API void setWrapMode(WrapMode mode);
NVTT_API void setAlphaMode(AlphaMode alphaMode); NVTT_API void setAlphaMode(AlphaMode alphaMode);
NVTT_API void setNormalMap(bool isNormalMap); NVTT_API void setNormalMap(bool isNormalMap);
// Accessors. // Queries.
NVTT_API int width() const; NVTT_API int width() const;
NVTT_API int height() const; NVTT_API int height() const;
NVTT_API int depth() const; NVTT_API int depth() const;
NVTT_API int faceCount() const;
NVTT_API TextureType textureType() const;
NVTT_API WrapMode wrapMode() const; NVTT_API WrapMode wrapMode() const;
NVTT_API AlphaMode alphaMode() const; NVTT_API AlphaMode alphaMode() const;
NVTT_API bool isNormalMap() const; NVTT_API bool isNormalMap() const;
NVTT_API int countMipmaps() const; NVTT_API int countMipmaps() const;
NVTT_API float alphaTestCoverage(float alphaRef = 0.5) const; NVTT_API float alphaTestCoverage(float alphaRef = 0.5) const;
NVTT_API float average(int channel) const;
NVTT_API const float * data() const;
// Texture data. // Texture data.
NVTT_API bool load(const char * fileName); NVTT_API bool load(const char * fileName);
NVTT_API bool save(const char * fileName) const; NVTT_API bool save(const char * fileName) const;
NVTT_API bool setImage2D(InputFormat format, int w, int h, int idx, const void * data); NVTT_API bool setImage2D(InputFormat format, int w, int h, const void * data);
NVTT_API bool setImage2D(InputFormat format, int w, int h, int idx, const void * r, const void * g, const void * b, const void * a); NVTT_API bool setImage2D(InputFormat format, int w, int h, const void * r, const void * g, const void * b, const void * a);
NVTT_API bool setImage2D(Format format, Decoder decoder, int w, int h, int idx, const void * data); NVTT_API bool setImage2D(Format format, Decoder decoder, int w, int h, const void * data);
// Resizing methods. // Resizing methods.
NVTT_API void resize(int w, int h, ResizeFilter filter); NVTT_API void resize(int w, int h, ResizeFilter filter);
@ -452,7 +451,6 @@ namespace nvtt
private: private:
void detach(); void detach();
friend struct Compressor::Private;
struct Private; struct Private;
Private * m; Private * m;

@ -463,8 +463,8 @@ int main(int argc, char *argv[])
context.process(inputOptions, compressionOptions, outputOptions); context.process(inputOptions, compressionOptions, outputOptions);
timer.stop(); timer.stop();
printf(" Time: \t%.3f sec\n", float(timer.elapsed()) / 1000); printf(" Time: \t%.3f sec\n", timer.elapsed());
totalTime += float(timer.elapsed()) / 1000; totalTime += timer.elapsed();
AutoPtr<Image> img_out( outputHandler.decompress(s_imageSets[set].format, decoder) ); AutoPtr<Image> img_out( outputHandler.decompress(s_imageSets[set].format, decoder) );

Loading…
Cancel
Save