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();
|
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 the extents have not changed, then we can use source images for all mipmaps.
|
||||||
if (!inputOptions.isNormalMap) {
|
bool canUseSourceImages = (inputOptions.width == w && inputOptions.height == h && inputOptions.depth == d);
|
||||||
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);
|
|
||||||
|
|
||||||
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]);
|
||||||
|
|
||||||
quantize(tmp, compressionOptions);
|
// To normal map.
|
||||||
compress(tmp, compressionOptions, outputOptions);
|
if (inputOptions.convertToNormalMap) {
|
||||||
|
img.toGreyScale(inputOptions.heightFactors.x, inputOptions.heightFactors.y, inputOptions.heightFactors.z, inputOptions.heightFactors.w);
|
||||||
for (int m = 1; m < mipmapCount; m++) {
|
img.toNormalMap(inputOptions.bumpFrequencyScale.x, inputOptions.bumpFrequencyScale.y, inputOptions.bumpFrequencyScale.z, inputOptions.bumpFrequencyScale.w);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useSourceImages) {
|
// To linear space.
|
||||||
for (int f = 0; f < faceCount; f++) {
|
if (!img.isNormalMap()) {
|
||||||
int idx = m * faceCount + f;
|
img.toLinear(inputOptions.inputGamma);
|
||||||
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 {
|
|
||||||
img.buildNextMipmap(inputOptions.mipmapFilter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nvDebugCheck(img.width() == w);
|
|
||||||
nvDebugCheck(img.height() == h);
|
|
||||||
|
|
||||||
if (inputOptions.isNormalMap) {
|
// Resize input.
|
||||||
if (inputOptions.normalizeMipmaps) {
|
img.resize(w, h, ResizeFilter_Box);
|
||||||
img.normalizeNormalMap();
|
|
||||||
}
|
nvtt::TexImage tmp = img;
|
||||||
tmp = img;
|
if (!img.isNormalMap()) {
|
||||||
}
|
|
||||||
else {
|
|
||||||
tmp = img;
|
|
||||||
tmp.toGamma(inputOptions.outputGamma);
|
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);
|
quantize(tmp, compressionOptions);
|
||||||
compress(tmp, compressionOptions, outputOptions);
|
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;
|
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…
Reference in New Issue
Block a user