diff --git a/src/nvtt/Compressor.cpp b/src/nvtt/Compressor.cpp index 003b737..fb86871 100644 --- a/src/nvtt/Compressor.cpp +++ b/src/nvtt/Compressor.cpp @@ -478,6 +478,11 @@ bool Compressor::Private::initMipmap(Mipmap & mipmap, const InputOptions::Privat // Convert linear float image to fixed image ready for compression. mipmap.toFixedImage(inputOptions); + if (inputOptions.premultiplyAlpha) + { + premultiplyAlphaMipmap(mipmap, inputOptions); + } + return true; } @@ -582,6 +587,29 @@ void Compressor::Private::scaleMipmap(Mipmap & mipmap, const InputOptions::Priva } +void Compressor::Private::premultiplyAlphaMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const +{ + nvDebugCheck(mipmap.asFixedImage() != NULL); + + Image * image = mipmap.asMutableFixedImage(); + + const uint w = image->width(); + const uint h = image->height(); + + const uint count = w * h; + + for (uint i = 0; i < count; ++i) + { + Color32 c = image->pixel(i); + + c.r = (uint(c.r) * uint(c.a)) >> 8; + c.g = (uint(c.g) * uint(c.a)) >> 8; + c.b = (uint(c.b) * uint(c.a)) >> 8; + + image->pixel(i) = c; + } +} + // Process an input image: Convert to normal map, normalize, or convert to linear space. void Compressor::Private::processInputImage(Mipmap & mipmap, const InputOptions::Private & inputOptions) const { diff --git a/src/nvtt/Compressor.h b/src/nvtt/Compressor.h index 326b498..6da7dd1 100644 --- a/src/nvtt/Compressor.h +++ b/src/nvtt/Compressor.h @@ -58,6 +58,7 @@ namespace nvtt void downsampleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const; void scaleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d) const; + void premultiplyAlphaMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const; void processInputImage(Mipmap & mipmap, const InputOptions::Private & inputOptions) const; void quantizeMipmap(Mipmap & mipmap, const CompressionOptions::Private & compressionOptions) const; bool compressMipmap(const Mipmap & mipmap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; diff --git a/src/nvtt/InputOptions.cpp b/src/nvtt/InputOptions.cpp index 61ec767..196a00a 100644 --- a/src/nvtt/InputOptions.cpp +++ b/src/nvtt/InputOptions.cpp @@ -118,6 +118,8 @@ void InputOptions::reset() m.maxExtent = 0; m.roundMode = RoundMode_None; + + m.premultiplyAlpha = false; } @@ -329,6 +331,10 @@ void InputOptions::setRoundMode(RoundMode mode) m.roundMode = mode; } +void InputOptions::setPremultiplyAlpha(bool b) +{ + m.premultiplyAlpha = b; +} void InputOptions::Private::computeTargetExtents() const { diff --git a/src/nvtt/InputOptions.h b/src/nvtt/InputOptions.h index 2c922af..b8c5525 100644 --- a/src/nvtt/InputOptions.h +++ b/src/nvtt/InputOptions.h @@ -78,6 +78,8 @@ namespace nvtt uint maxExtent; RoundMode roundMode; + bool premultiplyAlpha; + // @@ These are computed in nvtt::compress, so they should be mutable or stored elsewhere... mutable uint targetWidth; mutable uint targetHeight; @@ -89,7 +91,7 @@ namespace nvtt int realMipmapCount() const; const nv::Image * image(uint face, uint mipmap) const; - const nv::Image * image(uint idx) const; + const nv::Image * image(uint idx) const; }; diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 44dbdd9..12fcc71 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -227,6 +227,9 @@ namespace nvtt // Set resizing options. NVTT_API void setMaxExtents(int d); NVTT_API void setRoundMode(RoundMode mode); + + // Set whether or not to premultiply color by alpha + NVTT_API void setPremultiplyAlpha(bool b); }; diff --git a/src/nvtt/tools/compress.cpp b/src/nvtt/tools/compress.cpp index 44a880a..0d091c8 100644 --- a/src/nvtt/tools/compress.cpp +++ b/src/nvtt/tools/compress.cpp @@ -140,6 +140,7 @@ int main(int argc, char *argv[]) bool silent = false; bool bc1n = false; nvtt::Format format = nvtt::Format_BC1; + bool premultiplyAlpha = false; const char * externalCompressor = NULL; @@ -173,6 +174,10 @@ int main(int argc, char *argv[]) { noMipmaps = true; } + else if (strcmp("-premula", argv[i]) == 0) + { + premultiplyAlpha = true; + } // Compression options. else if (strcmp("-fast", argv[i]) == 0) @@ -266,7 +271,8 @@ int main(int argc, char *argv[]) printf(" -tonormal\tConvert input to normal map.\n"); printf(" -clamp \tClamp wrapping mode (default).\n"); printf(" -repeat \tRepeat wrapping mode.\n"); - printf(" -nomips \tDisable mipmap generation.\n\n"); + printf(" -nomips \tDisable mipmap generation.\n"); + printf(" -premula \tPremultiply alpha into color channel.\n\n"); printf("Compression options:\n"); printf(" -fast \tFast compression.\n"); @@ -373,6 +379,11 @@ int main(int argc, char *argv[]) inputOptions.setMipmapGeneration(false); } + if (premultiplyAlpha) + { + inputOptions.setPremultiplyAlpha(true); + inputOptions.setAlphaMode(nvtt::AlphaMode_Premultiplied); + } nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(format);