Fix errors in new implementation of InputOptions.
Output cube map faces in DDS order. Fixes issue 147.
This commit is contained in:
parent
5225f4810f
commit
c1204bfb66
@ -129,16 +129,19 @@ Image * FloatImage::createImageGammaCorrect(float gamma/*= 2.2f*/) const
|
||||
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)
|
||||
{
|
||||
free();
|
||||
if (m_componentNum != c || m_width != w || m_height != h)
|
||||
{
|
||||
free();
|
||||
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_componentNum = c;
|
||||
m_count = w * h * c;
|
||||
m_mem = malloc<float>(m_count);
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_componentNum = c;
|
||||
m_count = w * h * c;
|
||||
m_mem = malloc<float>(m_count);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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* 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;
|
||||
}
|
||||
|
@ -52,59 +52,10 @@
|
||||
#include "nvcore/Memory.h"
|
||||
#include "nvcore/Ptr.h"
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace nv;
|
||||
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())
|
||||
{
|
||||
@ -166,12 +117,12 @@ bool Compressor::process(const InputOptions & inputOptions, const CompressionOpt
|
||||
|
||||
int Compressor::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const
|
||||
{
|
||||
// @@ Compute w, h, mipmapCount based on inputOptions settings.
|
||||
const int w = 0;
|
||||
const int h = 0;
|
||||
const int d = 1;
|
||||
int mipmapCount = 1;
|
||||
int w = inputOptions.m.width;
|
||||
int h = inputOptions.m.height;
|
||||
int d = inputOptions.m.depth;
|
||||
getTargetExtent(w, h, d, inputOptions.m.maxExtent, inputOptions.m.roundMode, inputOptions.m.textureType);
|
||||
|
||||
int mipmapCount = countMipmaps(w, h, d);
|
||||
return inputOptions.m.faceCount * estimateSize(w, h, d, mipmapCount, compressionOptions);
|
||||
}
|
||||
|
||||
@ -179,7 +130,7 @@ int Compressor::estimateSize(const InputOptions & inputOptions, const Compressio
|
||||
// TexImage API.
|
||||
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
|
||||
@ -192,9 +143,8 @@ int Compressor::estimateSize(const TexImage & tex, int mipmapCount, const Compre
|
||||
const int w = tex.width();
|
||||
const int h = tex.height();
|
||||
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;
|
||||
img.setTextureType(inputOptions.textureType);
|
||||
img.setWrapMode(inputOptions.wrapMode);
|
||||
img.setAlphaMode(inputOptions.alphaMode);
|
||||
img.setNormalMap(inputOptions.isNormalMap);
|
||||
@ -254,108 +203,112 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c
|
||||
int h = inputOptions.height;
|
||||
int d = inputOptions.depth;
|
||||
|
||||
for (int f = 0; f < faceCount; f++)
|
||||
{
|
||||
img.setImage2D(inputOptions.inputFormat, w, h, f, inputOptions.images[f]);
|
||||
}
|
||||
nv::getTargetExtent(w, h, d, inputOptions.maxExtent, inputOptions.roundMode, inputOptions.textureType);
|
||||
|
||||
// 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.
|
||||
bool canUseSourceImages = (img.width() == w && img.height() == h);
|
||||
// If the extents have not changed, then we can use source images for all mipmaps.
|
||||
bool canUseSourceImages = (inputOptions.width == w && inputOptions.height == h && inputOptions.depth == d);
|
||||
|
||||
int mipmapCount = 1;
|
||||
if (inputOptions.generateMipmaps) {
|
||||
mipmapCount = img.countMipmaps();
|
||||
mipmapCount = countMipmaps(w, h, d);
|
||||
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;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
quantize(tmp, compressionOptions);
|
||||
compress(tmp, compressionOptions, outputOptions);
|
||||
|
||||
for (int m = 1; m < mipmapCount; m++) {
|
||||
w = max(1, w/2);
|
||||
h = max(1, h/2);
|
||||
d = max(1, d/2);
|
||||
|
||||
int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format);
|
||||
outputOptions.beginImage(size, w, h, d, 0, m);
|
||||
|
||||
bool useSourceImages = false;
|
||||
if (canUseSourceImages) {
|
||||
useSourceImages = true;
|
||||
for (int f = 0; f < faceCount; f++) {
|
||||
int idx = m * faceCount + f;
|
||||
if (inputOptions.images[idx] == NULL) { // One face is missing in this mipmap level.
|
||||
useSourceImages = false;
|
||||
canUseSourceImages = false; // If one level is missing, ignore the following source images.
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (useSourceImages) {
|
||||
for (int f = 0; f < faceCount; f++) {
|
||||
int idx = m * faceCount + f;
|
||||
img.setImage2D(inputOptions.inputFormat, w, h, f, inputOptions.images[idx]);
|
||||
}
|
||||
// To linear space.
|
||||
if (!img.isNormalMap()) {
|
||||
img.toLinear(inputOptions.inputGamma);
|
||||
}
|
||||
else {
|
||||
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.height() == h);
|
||||
|
||||
if (inputOptions.isNormalMap) {
|
||||
if (inputOptions.normalizeMipmaps) {
|
||||
img.normalizeNormalMap();
|
||||
}
|
||||
tmp = img;
|
||||
}
|
||||
else {
|
||||
tmp = img;
|
||||
// Resize input.
|
||||
img.resize(w, h, ResizeFilter_Box);
|
||||
|
||||
nvtt::TexImage tmp = img;
|
||||
if (!img.isNormalMap()) {
|
||||
tmp.toGamma(inputOptions.outputGamma);
|
||||
}
|
||||
|
||||
int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format);
|
||||
outputOptions.beginImage(size, w, h, d, f, 0);
|
||||
|
||||
quantize(tmp, compressionOptions);
|
||||
compress(tmp, compressionOptions, outputOptions);
|
||||
};
|
||||
|
||||
for (int m = 1; m < mipmapCount; m++) {
|
||||
w = max(1, w/2);
|
||||
h = max(1, h/2);
|
||||
d = max(1, d/2);
|
||||
|
||||
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.
|
||||
useSourceImages = false;
|
||||
canUseSourceImages = false; // If one level is missing, ignore the following source images.
|
||||
}
|
||||
}
|
||||
|
||||
if (useSourceImages) {
|
||||
img.setImage2D(inputOptions.inputFormat, w, h, inputOptions.images[idx]);
|
||||
}
|
||||
else {
|
||||
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.height() == h);
|
||||
|
||||
if (img.isNormalMap()) {
|
||||
if (inputOptions.normalizeMipmaps) {
|
||||
img.normalizeNormalMap();
|
||||
}
|
||||
tmp = img;
|
||||
}
|
||||
else {
|
||||
tmp = img;
|
||||
tmp.toGamma(inputOptions.outputGamma);
|
||||
}
|
||||
|
||||
quantize(tmp, compressionOptions);
|
||||
compress(tmp, compressionOptions, outputOptions);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Compressor::Private::compress(const TexImage & tex, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
|
||||
{
|
||||
foreach(i, tex.m->imageArray) {
|
||||
FloatImage * image = tex.m->imageArray[i];
|
||||
if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), image->channel(0), compressionOptions, outputOptions)) {
|
||||
return false;
|
||||
}
|
||||
if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), tex.data(), compressionOptions, outputOptions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
return false;
|
||||
@ -434,19 +387,19 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
|
||||
|
||||
header.setUserVersion(outputOptions.version);
|
||||
|
||||
if (tex.textureType() == TextureType_2D) {
|
||||
if (textureType == TextureType_2D) {
|
||||
header.setTexture2D();
|
||||
}
|
||||
else if (tex.textureType() == TextureType_Cube) {
|
||||
else if (textureType == TextureType_Cube) {
|
||||
header.setTextureCube();
|
||||
}
|
||||
/*else if (tex.textureType() == TextureType_3D) {
|
||||
/*else if (textureType == TextureType_3D) {
|
||||
header.setTexture3D();
|
||||
header.setDepth(tex.depth());
|
||||
header.setDepth(d);
|
||||
}*/
|
||||
|
||||
header.setWidth(tex.width());
|
||||
header.setHeight(tex.height());
|
||||
header.setWidth(w);
|
||||
header.setHeight(h);
|
||||
header.setMipmapCount(mipmapCount);
|
||||
|
||||
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) {
|
||||
header.setDX10Format(70); // DXGI_FORMAT_BC1_TYPELESS
|
||||
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) {
|
||||
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) {
|
||||
header.setDX10Format(76); // DXGI_FORMAT_BC3_TYPELESS
|
||||
if (tex.isNormalMap()) header.setNormalFlag(true);
|
||||
if (isNormalMap) header.setNormalFlag(true);
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC4) {
|
||||
header.setDX10Format(79); // DXGI_FORMAT_BC4_TYPELESS
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC5) {
|
||||
header.setDX10Format(82); // DXGI_FORMAT_BC5_TYPELESS
|
||||
if (tex.isNormalMap()) header.setNormalFlag(true);
|
||||
if (isNormalMap) header.setNormalFlag(true);
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC6) {
|
||||
header.setDX10Format(94); // DXGI_FORMAT_BC6H_TYPELESS
|
||||
}
|
||||
else if (compressionOptions.format == Format_BC7) {
|
||||
header.setDX10Format(97); // DXGI_FORMAT_BC7_TYPELESS
|
||||
if (tex.isNormalMap()) header.setNormalFlag(true);
|
||||
if (isNormalMap) header.setNormalFlag(true);
|
||||
}
|
||||
else {
|
||||
supported = false;
|
||||
@ -526,7 +479,7 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
|
||||
if (compressionOptions.format == Format_RGBA)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
@ -591,11 +544,11 @@ bool Compressor::Private::outputHeader(const TexImage & tex, int mipmapCount, co
|
||||
}
|
||||
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) {
|
||||
header.setFourCC('D', 'X', 'T', '1');
|
||||
if (tex.isNormalMap()) header.setNormalFlag(true);
|
||||
if (isNormalMap) header.setNormalFlag(true);
|
||||
}
|
||||
else if (compressionOptions.format == Format_DXT3) {
|
||||
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) {
|
||||
header.setFourCC('D', 'X', 'T', '5');
|
||||
if (tex.isNormalMap()) {
|
||||
if (isNormalMap) {
|
||||
header.setNormalFlag(true);
|
||||
header.setSwizzleCode('A', '2', 'D', '5');
|
||||
//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) {
|
||||
header.setFourCC('A', 'T', 'I', '2');
|
||||
if (tex.isNormalMap()) {
|
||||
if (isNormalMap) {
|
||||
header.setNormalFlag(true);
|
||||
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) {
|
||||
header.setFourCC('Z', 'O', 'L', 'A');
|
||||
if (tex.isNormalMap()) header.setNormalFlag(true);
|
||||
if (isNormalMap) header.setNormalFlag(true);
|
||||
}
|
||||
else if (compressionOptions.format == Format_CTX1) {
|
||||
header.setFourCC('C', 'T', 'X', '1');
|
||||
if (tex.isNormalMap()) header.setNormalFlag(true);
|
||||
if (isNormalMap) header.setNormalFlag(true);
|
||||
}
|
||||
else {
|
||||
supported = false;
|
||||
|
@ -49,8 +49,8 @@ namespace nvtt
|
||||
|
||||
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(const InputOptions::Private & inputOptions, 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;
|
||||
|
||||
nv::CompressorInterface * chooseCpuCompressor(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;
|
||||
|
||||
// Allocate images.
|
||||
m.faceCount = (type == TextureType_2D) ? 1 : 6;
|
||||
m.faceCount = (type == TextureType_Cube) ? 6 : 1;
|
||||
m.mipmapCount = countMipmaps(width, height, depth);
|
||||
m.imageCount = m.mipmapCount * m.faceCount;
|
||||
m.images = new 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)
|
||||
{
|
||||
// Delete images.
|
||||
for (int i = 0; i < m.imageCount; i++) {
|
||||
free(m.images[i]);
|
||||
}
|
||||
|
||||
// Delete image array.
|
||||
delete [] m.images;
|
||||
m.images = NULL;
|
||||
@ -240,7 +221,7 @@ bool InputOptions::setMipmapData(const void * data, int width, int height, int d
|
||||
return false;
|
||||
}
|
||||
|
||||
m.images[idx] = new uint8[imageSize];
|
||||
m.images[idx] = realloc(m.images[idx], imageSize);
|
||||
if (m.images[idx] == NULL) {
|
||||
// Out of memory.
|
||||
return false;
|
||||
|
@ -28,27 +28,27 @@ using namespace nvtt;
|
||||
|
||||
OutputOptions::OutputOptions() : m(*new OutputOptions::Private())
|
||||
{
|
||||
reset();
|
||||
reset();
|
||||
}
|
||||
|
||||
OutputOptions::~OutputOptions()
|
||||
{
|
||||
// Cleanup output handler.
|
||||
setOutputHandler(NULL);
|
||||
// Cleanup output handler.
|
||||
setOutputHandler(NULL);
|
||||
|
||||
delete &m;
|
||||
delete &m;
|
||||
}
|
||||
|
||||
/// Set default output options.
|
||||
void OutputOptions::reset()
|
||||
{
|
||||
m.fileName.reset();
|
||||
m.fileName.reset();
|
||||
|
||||
m.outputHandler = NULL;
|
||||
m.errorHandler = NULL;
|
||||
m.outputHandler = NULL;
|
||||
m.errorHandler = NULL;
|
||||
|
||||
m.outputHeader = true;
|
||||
m.container = Container_DDS;
|
||||
m.outputHeader = true;
|
||||
m.container = Container_DDS;
|
||||
m.version = 0;
|
||||
}
|
||||
|
||||
@ -56,78 +56,78 @@ void OutputOptions::reset()
|
||||
/// Set output file name.
|
||||
void OutputOptions::setFileName(const char * fileName)
|
||||
{
|
||||
if (!m.fileName.isNull())
|
||||
{
|
||||
if (!m.fileName.isNull())
|
||||
{
|
||||
// To close the file and avoid leak.
|
||||
delete m.outputHandler;
|
||||
}
|
||||
delete m.outputHandler;
|
||||
}
|
||||
|
||||
m.fileName = fileName;
|
||||
m.outputHandler = NULL;
|
||||
m.fileName = fileName;
|
||||
m.outputHandler = NULL;
|
||||
|
||||
DefaultOutputHandler * oh = new DefaultOutputHandler(fileName);
|
||||
if (!oh->stream.isError())
|
||||
{
|
||||
m.outputHandler = oh;
|
||||
}
|
||||
DefaultOutputHandler * oh = new DefaultOutputHandler(fileName);
|
||||
if (!oh->stream.isError())
|
||||
{
|
||||
m.outputHandler = oh;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set output handler.
|
||||
void OutputOptions::setOutputHandler(OutputHandler * outputHandler)
|
||||
{
|
||||
if (!m.fileName.isNull())
|
||||
{
|
||||
delete m.outputHandler;
|
||||
m.fileName.reset();
|
||||
}
|
||||
m.outputHandler = outputHandler;
|
||||
if (!m.fileName.isNull())
|
||||
{
|
||||
delete m.outputHandler;
|
||||
m.fileName.reset();
|
||||
}
|
||||
m.outputHandler = outputHandler;
|
||||
}
|
||||
|
||||
/// Set error handler.
|
||||
void OutputOptions::setErrorHandler(ErrorHandler * errorHandler)
|
||||
{
|
||||
m.errorHandler = errorHandler;
|
||||
m.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
/// Set output header.
|
||||
void OutputOptions::setOutputHeader(bool outputHeader)
|
||||
{
|
||||
m.outputHeader = outputHeader;
|
||||
m.outputHeader = outputHeader;
|
||||
}
|
||||
|
||||
/// Set container.
|
||||
void OutputOptions::setContainer(Container container)
|
||||
{
|
||||
m.container = container;
|
||||
m.container = container;
|
||||
}
|
||||
|
||||
/// Set user version.
|
||||
void OutputOptions::setUserVersion(int version)
|
||||
{
|
||||
m.version = version;
|
||||
m.version = version;
|
||||
}
|
||||
|
||||
bool OutputOptions::Private::hasValidOutputHandler() const
|
||||
{
|
||||
if (!fileName.isNull())
|
||||
{
|
||||
return outputHandler != NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!fileName.isNull())
|
||||
{
|
||||
return outputHandler != NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return outputHandler == NULL || outputHandler->writeData(data, size);
|
||||
return outputHandler == NULL || outputHandler->writeData(data, size);
|
||||
}
|
||||
|
||||
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;
|
||||
isNormalMap = false;
|
||||
|
||||
imageArray.resize(1, NULL);
|
||||
image = NULL;
|
||||
}
|
||||
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
|
||||
{
|
||||
@ -60,17 +60,11 @@ namespace nvtt
|
||||
alphaMode = p.alphaMode;
|
||||
isNormalMap = p.isNormalMap;
|
||||
|
||||
imageArray.reserve(p.imageArray.count());
|
||||
foreach(i, p.imageArray) {
|
||||
imageArray.append(p.imageArray[i]->clone());
|
||||
}
|
||||
image = p.image->clone();
|
||||
}
|
||||
~Private()
|
||||
{
|
||||
const uint count = imageArray.count();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
delete imageArray[i];
|
||||
}
|
||||
delete image;
|
||||
}
|
||||
|
||||
TextureType type;
|
||||
@ -78,11 +72,16 @@ namespace nvtt
|
||||
AlphaMode alphaMode;
|
||||
bool isNormalMap;
|
||||
|
||||
nv::Array<nv::FloatImage *> imageArray;
|
||||
nv::FloatImage * image;
|
||||
};
|
||||
|
||||
|
||||
} // 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
|
||||
|
@ -28,30 +28,30 @@ using namespace nvtt;
|
||||
/// Return a string for the given error.
|
||||
const char * nvtt::errorString(Error e)
|
||||
{
|
||||
switch(e)
|
||||
{
|
||||
case Error_Unknown:
|
||||
return "Unknown error";
|
||||
case Error_InvalidInput:
|
||||
return "Invalid input";
|
||||
case Error_UnsupportedFeature:
|
||||
return "Unsupported feature";
|
||||
case Error_CudaError:
|
||||
return "CUDA error";
|
||||
case Error_FileOpen:
|
||||
return "Error opening file";
|
||||
case Error_FileWrite:
|
||||
return "Error writing through output handler";
|
||||
switch(e)
|
||||
{
|
||||
case Error_Unknown:
|
||||
return "Unknown error";
|
||||
case Error_InvalidInput:
|
||||
return "Invalid input";
|
||||
case Error_UnsupportedFeature:
|
||||
return "Unsupported feature";
|
||||
case Error_CudaError:
|
||||
return "CUDA error";
|
||||
case Error_FileOpen:
|
||||
return "Error opening file";
|
||||
case Error_FileWrite:
|
||||
return "Error writing through output handler";
|
||||
case Error_UnsupportedOutputFormat:
|
||||
return "The container file does not support the selected output format";
|
||||
}
|
||||
|
||||
return "Invalid error";
|
||||
}
|
||||
|
||||
return "Invalid error";
|
||||
}
|
||||
|
||||
/// Return 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);
|
||||
|
||||
// Texture parameters.
|
||||
NVTT_API void setTextureType(TextureType type);
|
||||
NVTT_API void setWrapMode(WrapMode mode);
|
||||
NVTT_API void setAlphaMode(AlphaMode alphaMode);
|
||||
NVTT_API void setNormalMap(bool isNormalMap);
|
||||
|
||||
// Accessors.
|
||||
// Queries.
|
||||
NVTT_API int width() const;
|
||||
NVTT_API int height() const;
|
||||
NVTT_API int depth() const;
|
||||
NVTT_API int faceCount() const;
|
||||
NVTT_API TextureType textureType() const;
|
||||
NVTT_API WrapMode wrapMode() const;
|
||||
NVTT_API AlphaMode alphaMode() const;
|
||||
NVTT_API bool isNormalMap() const;
|
||||
NVTT_API int countMipmaps() 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.
|
||||
NVTT_API bool load(const char * fileName);
|
||||
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, int idx, 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(InputFormat format, int w, int h, const void * data);
|
||||
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, const void * data);
|
||||
|
||||
// Resizing methods.
|
||||
NVTT_API void resize(int w, int h, ResizeFilter filter);
|
||||
@ -452,7 +451,6 @@ namespace nvtt
|
||||
|
||||
private:
|
||||
void detach();
|
||||
friend struct Compressor::Private;
|
||||
|
||||
struct Private;
|
||||
Private * m;
|
||||
|
@ -463,8 +463,8 @@ int main(int argc, char *argv[])
|
||||
context.process(inputOptions, compressionOptions, outputOptions);
|
||||
|
||||
timer.stop();
|
||||
printf(" Time: \t%.3f sec\n", float(timer.elapsed()) / 1000);
|
||||
totalTime += float(timer.elapsed()) / 1000;
|
||||
printf(" Time: \t%.3f sec\n", timer.elapsed());
|
||||
totalTime += timer.elapsed();
|
||||
|
||||
AutoPtr<Image> img_out( outputHandler.decompress(s_imageSets[set].format, decoder) );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user