From 4c759f999c6452083ae8087f992a6a1733f4ef78 Mon Sep 17 00:00:00 2001 From: castano Date: Fri, 11 Apr 2008 22:03:42 +0000 Subject: [PATCH] Integrate decompressor tool improvements submitted by Amorilia. --- src/nvimage/DirectDrawSurface.cpp | 29 +++++- src/nvimage/DirectDrawSurface.h | 2 + src/nvtt/tools/decompress.cpp | 150 +++++++++++++++++++++++++----- 3 files changed, 156 insertions(+), 25 deletions(-) diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index c75ce22..92b4751 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -730,6 +730,12 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } +void DirectDrawSurface::setNormalFlag(bool b) +{ + nvDebugCheck(isValid()); + header.setNormalFlag(b); +} + void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { nvDebugCheck(isValid()); @@ -780,7 +786,13 @@ void DirectDrawSurface::readLinearImage(Image * img) uint byteCount = (header.pf.bitcount + 7) / 8; - if (header.pf.amask != 0) + // set image format: RGB or ARGB + // alpha channel exists if and only if the alpha mask is non-zero + if (header.pf.amask == 0) + { + img->setFormat(Image::Format_RGB); + } + else { img->setFormat(Image::Format_ARGB); } @@ -808,7 +820,20 @@ void DirectDrawSurface::readBlockImage(Image * img) { nvDebugCheck(stream != NULL); nvDebugCheck(img != NULL); - + + // set image format: RGB or ARGB + if (header.pf.fourcc == FOURCC_RXGB || + header.pf.fourcc == FOURCC_ATI1 || + header.pf.fourcc == FOURCC_ATI2 || + header.pf.flags & DDPF_NORMAL) + { + img->setFormat(Image::Format_RGB); + } + else + { + img->setFormat(Image::Format_ARGB); + } + const uint w = img->width(); const uint h = img->height(); diff --git a/src/nvimage/DirectDrawSurface.h b/src/nvimage/DirectDrawSurface.h index b4f0df6..c07d40d 100644 --- a/src/nvimage/DirectDrawSurface.h +++ b/src/nvimage/DirectDrawSurface.h @@ -122,6 +122,8 @@ namespace nv bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; + + void setNormalFlag(bool b); void mipmap(Image * img, uint f, uint m); // void mipmap(FloatImage * img, uint f, uint m); diff --git a/src/nvtt/tools/decompress.cpp b/src/nvtt/tools/decompress.cpp index ffb2ceb..8589e23 100644 --- a/src/nvtt/tools/decompress.cpp +++ b/src/nvtt/tools/decompress.cpp @@ -31,41 +31,145 @@ #include "cmdline.h" +#include // clock + int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; - if (argc != 2) - { - printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); - printf("usage: nvdecompress 'ddsfile'\n\n"); - return 1; - } + bool forcenormal = false; + bool mipmaps = false; + bool faces = false; + nv::Path input; + nv::Path output; + + // Parse arguments. + for (int i = 1; i < argc; i++) + { + if (strcmp("-forcenormal", argv[i]) == 0) + { + forcenormal = true; + } + else if (strcmp("-mipmaps", argv[i]) == 0) + { + mipmaps = true; + } + else if (strcmp("-faces", argv[i]) == 0) + { + faces = true; + } + else if (argv[i][0] != '-') + { + input = argv[i]; + + if (i+1 < argc && argv[i+1][0] != '-') + { + output = argv[i+1]; + } + else + { + output.copy(input.str()); + output.stripExtension(); + output.append(".tga"); + } + + break; + } + } + + printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); + + if (input.isNull()) + { + printf("usage: nvdecompress [options] infile [outfile]\n\n"); + + printf("Note: the .tga extension is forced on outfile\n\n"); + + printf("Input options:\n"); + printf(" -forcenormal \tThe input image is a normal map.\n"); + printf(" -mipmaps \tDecompress all mipmaps.\n"); + printf(" -faces \tDecompress all faces.\n"); + + return 1; + } + // Load surface. - nv::DirectDrawSurface dds(argv[1]); + nv::DirectDrawSurface dds(input); if (!dds.isValid()) { - printf("The file '%s' is not a valid DDS file.\n", argv[1]); + fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str()); return 1; } - - nv::Path name(argv[1]); - name.stripExtension(); - name.append(".tga"); - - nv::StdOutputStream stream(name.str()); - if (stream.isError()) { - printf("Error opening '%s' for writting\n", name.str()); - return 1; - } - - // @@ TODO: Add command line options to output mipmaps, cubemap faces, etc. - nv::Image img; - dds.mipmap(&img, 0, 0); // get first image - nv::ImageIO::saveTGA(stream, &img); + if (!dds.isSupported() || dds.isTexture3D()) + { + fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str()); + return 1; + } + + uint faceCount; + if (dds.isTexture2D()) + { + faceCount = 1; + } + else + { + nvCheck(dds.isTextureCube()); + faceCount = 6; + } + + uint mipmapCount = dds.mipmapCount(); + + clock_t start = clock(); + + // apply arguments + if (forcenormal) + { + dds.setNormalFlag(true); + } + if (!faces) + { + faceCount = 1; + } + if (!mipmaps) + { + mipmapCount = 1; + } + + nv::Image mipmap; + nv::Path name; + + // strip extension, we force the tga extension + output.stripExtension(); + + // extract faces and mipmaps + for (uint f = 0; f < faceCount; f++) + { + for (uint m = 0; m < mipmapCount; m++) + { + dds.mipmap(&mipmap, f, m); + + // set output filename, if we are doing faces and/or mipmaps + name.copy(output); + if (faces) name.appendFormat("_face%d", f); + if (mipmaps) name.appendFormat("_mipmap%d", m); + name.append(".tga"); + + nv::StdOutputStream stream(name.str()); + if (stream.isError()) { + fprintf(stderr, "Error opening '%s' for writting\n", name.str()); + return 1; + } + + nv::ImageIO::saveTGA(stream, &mipmap); + } + } + + clock_t end = clock(); + printf("\rtime taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC); + return 0; }