diff --git a/project/vc8/nvimage/nvimage.vcproj b/project/vc8/nvimage/nvimage.vcproj
index 1b5d677..8f0f44e 100644
--- a/project/vc8/nvimage/nvimage.vcproj
+++ b/project/vc8/nvimage/nvimage.vcproj
@@ -355,6 +355,10 @@
RelativePath="..\..\..\src\nvimage\nvimage.h"
>
+
+
diff --git a/src/nvimage/Quantize.cpp b/src/nvimage/Quantize.cpp
index 8dd3a67..ce15d1c 100644
--- a/src/nvimage/Quantize.cpp
+++ b/src/nvimage/Quantize.cpp
@@ -16,6 +16,7 @@ http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT
#include
#include
+#include
using namespace nv;
@@ -47,94 +48,20 @@ void nv::Quantize::BinaryAlpha( Image * image, int alpha_threshold /*= 127*/ )
// Simple quantization.
void nv::Quantize::RGB16( Image * image )
{
- nvCheck(image != NULL);
-
- const uint w = image->width();
- const uint h = image->height();
-
- for(uint y = 0; y < h; y++) {
- for(uint x = 0; x < w; x++) {
-
- Color32 pixel32 = image->pixel(x, y);
-
- // Convert to 16 bit and back to 32 using regular bit expansion.
- Color32 pixel16 = toColor32( toColor16(pixel32) );
-
- // Store color.
- image->pixel(x, y) = pixel16;
- }
- }
+ Truncate(image, 5, 6, 5, 8);
}
// Alpha quantization.
void nv::Quantize::Alpha4( Image * image )
{
- nvCheck(image != NULL);
-
- const uint w = image->width();
- const uint h = image->height();
-
- for(uint y = 0; y < h; y++) {
- for(uint x = 0; x < w; x++) {
-
- Color32 pixel = image->pixel(x, y);
-
- // Convert to 4 bit using regular bit expansion.
- pixel.a = (pixel.a & 0xF0) | ((pixel.a & 0xF0) >> 4);
-
- // Store color.
- image->pixel(x, y) = pixel;
- }
- }
+ Truncate(image, 8, 8, 8, 4);
}
// Error diffusion. Floyd Steinberg.
void nv::Quantize::FloydSteinberg_RGB16( Image * image )
{
- nvCheck(image != NULL);
-
- const uint w = image->width();
- const uint h = image->height();
-
- // @@ Use fixed point?
- Vector3 * row0 = new Vector3[w+2];
- Vector3 * row1 = new Vector3[w+2];
- memset(row0, 0, sizeof(Vector3)*(w+2));
- memset(row1, 0, sizeof(Vector3)*(w+2));
-
- for(uint y = 0; y < h; y++) {
- for(uint x = 0; x < w; x++) {
-
- Color32 pixel32 = image->pixel(x, y);
-
- // Add error. // @@ We shouldn't clamp here!
- pixel32.r = clamp(int(pixel32.r) + int(row0[1+x].x()), 0, 255);
- pixel32.g = clamp(int(pixel32.g) + int(row0[1+x].y()), 0, 255);
- pixel32.b = clamp(int(pixel32.b) + int(row0[1+x].z()), 0, 255);
-
- // Convert to 16 bit. @@ Use regular clamp?
- Color32 pixel16 = toColor32( toColor16(pixel32) );
-
- // Store color.
- image->pixel(x, y) = pixel16;
-
- // Compute new error.
- Vector3 diff(float(pixel32.r - pixel16.r), float(pixel32.g - pixel16.g), float(pixel32.b - pixel16.b));
-
- // Propagate new error.
- row0[1+x+1] += 7.0f / 16.0f * diff;
- row1[1+x-1] += 3.0f / 16.0f * diff;
- row1[1+x+0] += 5.0f / 16.0f * diff;
- row1[1+x+1] += 1.0f / 16.0f * diff;
- }
-
- swap(row0, row1);
- memset(row1, 0, sizeof(Vector3)*(w+2));
- }
-
- delete [] row0;
- delete [] row1;
+ FloydSteinberg(image, 5, 6, 5, 8);
}
@@ -188,47 +115,102 @@ void nv::Quantize::FloydSteinberg_BinaryAlpha( Image * image, int alpha_threshol
// Error diffusion. Floyd Steinberg.
void nv::Quantize::FloydSteinberg_Alpha4( Image * image )
+{
+ FloydSteinberg(image, 8, 8, 8, 4);
+}
+
+
+void nv::Quantize::Truncate(Image * image, uint rsize, uint gsize, uint bsize, uint asize)
{
nvCheck(image != NULL);
const uint w = image->width();
const uint h = image->height();
- // @@ Use fixed point?
- float * row0 = new float[(w+2)];
- float * row1 = new float[(w+2)];
- memset(row0, 0, sizeof(float)*(w+2));
- memset(row1, 0, sizeof(float)*(w+2));
-
for(uint y = 0; y < h; y++) {
for(uint x = 0; x < w; x++) {
Color32 pixel = image->pixel(x, y);
-
- // Add error.
- int alpha = int(pixel.a) + int(row0[1+x]);
-
- // Convert to 4 bit using regular bit expansion.
- pixel.a = (pixel.a & 0xF0) | ((pixel.a & 0xF0) >> 4);
-
+
+ // Convert to our desired size, and reconstruct.
+ pixel.r = PixelFormat::convert(pixel.r, 8, rsize);
+ pixel.r = PixelFormat::convert(pixel.r, rsize, 8);
+
+ pixel.g = PixelFormat::convert(pixel.g, 8, gsize);
+ pixel.g = PixelFormat::convert(pixel.g, gsize, 8);
+
+ pixel.b = PixelFormat::convert(pixel.b, 8, bsize);
+ pixel.b = PixelFormat::convert(pixel.b, bsize, 8);
+
+ pixel.a = PixelFormat::convert(pixel.a, 8, asize);
+ pixel.a = PixelFormat::convert(pixel.a, asize, 8);
+
// Store color.
image->pixel(x, y) = pixel;
-
- // Compute new error.
- float diff = float(alpha - pixel.a);
-
- // Propagate new error.
- row0[1+x+1] += 7.0f / 16.0f * diff;
- row1[1+x-1] += 3.0f / 16.0f * diff;
- row1[1+x+0] += 5.0f / 16.0f * diff;
- row1[1+x+1] += 1.0f / 16.0f * diff;
}
-
- swap(row0, row1);
- memset(row1, 0, sizeof(float)*(w+2));
}
-
- delete [] row0;
- delete [] row1;
}
+
+// Error diffusion. Floyd Steinberg.
+void nv::Quantize::FloydSteinberg(Image * image, uint rsize, uint gsize, uint bsize, uint asize)
+{
+ nvCheck(image != NULL);
+
+ const uint w = image->width();
+ const uint h = image->height();
+
+ Vector4 * row0 = new Vector4[w+2];
+ Vector4 * row1 = new Vector4[w+2];
+ memset(row0, 0, sizeof(Vector4)*(w+2));
+ memset(row1, 0, sizeof(Vector4)*(w+2));
+
+ for (uint y = 0; y < h; y++) {
+ for (uint x = 0; x < w; x++) {
+
+ Color32 pixel = image->pixel(x, y);
+
+ // Add error.
+ pixel.r = clamp(int(pixel.r) + int(row0[1+x].x()), 0, 255);
+ pixel.g = clamp(int(pixel.g) + int(row0[1+x].y()), 0, 255);
+ pixel.b = clamp(int(pixel.b) + int(row0[1+x].z()), 0, 255);
+ pixel.a = clamp(int(pixel.a) + int(row0[1+x].w()), 0, 255);
+
+ int r = pixel.r;
+ int g = pixel.g;
+ int b = pixel.b;
+ int a = pixel.a;
+
+ // Convert to our desired size, and reconstruct.
+ r = PixelFormat::convert(r, 8, rsize);
+ r = PixelFormat::convert(r, rsize, 8);
+
+ g = PixelFormat::convert(g, 8, gsize);
+ g = PixelFormat::convert(g, gsize, 8);
+
+ b = PixelFormat::convert(b, 8, bsize);
+ b = PixelFormat::convert(b, bsize, 8);
+
+ a = PixelFormat::convert(a, 8, asize);
+ a = PixelFormat::convert(a, asize, 8);
+
+ // Store color.
+ image->pixel(x, y) = Color32(r, g, b, a);
+
+ // Compute new error.
+ Vector4 diff(float(int(pixel.r) - r), float(int(pixel.g) - g), float(int(pixel.b) - b), float(int(pixel.a) - a));
+
+ // Propagate new error.
+ row0[1+x+1] += 7.0f / 16.0f * diff;
+ row1[1+x-1] += 3.0f / 16.0f * diff;
+ row1[1+x+0] += 5.0f / 16.0f * diff;
+ row1[1+x+1] += 1.0f / 16.0f * diff;
+ }
+
+ swap(row0, row1);
+ memset(row1, 0, sizeof(Vector4)*(w+2));
+ }
+
+ delete [] row0;
+ delete [] row1;
+}
diff --git a/src/nvimage/Quantize.h b/src/nvimage/Quantize.h
index 0ffa8d7..4ce7c2f 100644
--- a/src/nvimage/Quantize.h
+++ b/src/nvimage/Quantize.h
@@ -17,6 +17,9 @@ namespace nv
void FloydSteinberg_BinaryAlpha(Image * img, int alpha_threshold = 127);
void FloydSteinberg_Alpha4(Image * img);
+ void Truncate(Image * image, uint rsize, uint gsize, uint bsize, uint asize);
+ void FloydSteinberg(Image * image, uint rsize, uint gsize, uint bsize, uint asize);
+
// @@ Add palette quantization algorithms!
}
}
diff --git a/src/nvtt/CompressRGB.cpp b/src/nvtt/CompressRGB.cpp
index f45f5b6..35239c4 100644
--- a/src/nvtt/CompressRGB.cpp
+++ b/src/nvtt/CompressRGB.cpp
@@ -123,7 +123,7 @@ void nv::compressRGB(const Image * image, const OutputOptions::Private & outputO
}
// Zero padding.
- for (uint x = w; x < pitch; x++)
+ for (uint x = w * byteCount; x < pitch; x++)
{
*(dst + x) = 0;
}
diff --git a/src/nvtt/Compressor.cpp b/src/nvtt/Compressor.cpp
index bc681ce..a4eb3e0 100644
--- a/src/nvtt/Compressor.cpp
+++ b/src/nvtt/Compressor.cpp
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
#include "Compressor.h"
#include "InputOptions.h"
@@ -617,13 +618,6 @@ void Compressor::Private::quantizeMipmap(Mipmap & mipmap, const CompressionOptio
{
nvDebugCheck(mipmap.asFixedImage() != NULL);
- if (compressionOptions.enableColorDithering)
- {
- if (compressionOptions.format >= Format_DXT1 && compressionOptions.format <= Format_DXT5)
- {
- Quantize::FloydSteinberg_RGB16(mipmap.asMutableFixedImage());
- }
- }
if (compressionOptions.binaryAlpha)
{
if (compressionOptions.enableAlphaDithering)
@@ -635,19 +629,50 @@ void Compressor::Private::quantizeMipmap(Mipmap & mipmap, const CompressionOptio
Quantize::BinaryAlpha(mipmap.asMutableFixedImage(), compressionOptions.alphaThreshold);
}
}
- else
+
+ if (compressionOptions.enableColorDithering || compressionOptions.enableAlphaDithering)
{
+ uint rsize = 8;
+ uint gsize = 8;
+ uint bsize = 8;
+ uint asize = 8;
+
+ if (compressionOptions.enableColorDithering)
+ {
+ if (compressionOptions.format >= Format_DXT1 && compressionOptions.format <= Format_DXT5)
+ {
+ rsize = 5;
+ gsize = 6;
+ bsize = 5;
+ }
+ else if (compressionOptions.format == Format_RGB)
+ {
+ uint rshift, gshift, bshift;
+ PixelFormat::maskShiftAndSize(compressionOptions.rmask, &rshift, &rsize);
+ PixelFormat::maskShiftAndSize(compressionOptions.gmask, &gshift, &gsize);
+ PixelFormat::maskShiftAndSize(compressionOptions.bmask, &bshift, &bsize);
+ }
+ }
+
if (compressionOptions.enableAlphaDithering)
{
if (compressionOptions.format == Format_DXT3)
{
- Quantize::Alpha4(mipmap.asMutableFixedImage());
+ asize = 4;
}
- else if (compressionOptions.format == Format_DXT1a)
+ else if (compressionOptions.format == Format_RGB)
{
- Quantize::BinaryAlpha(mipmap.asMutableFixedImage(), compressionOptions.alphaThreshold);
+ uint ashift;
+ PixelFormat::maskShiftAndSize(compressionOptions.amask, &ashift, &asize);
}
}
+
+ if (compressionOptions.binaryAlpha)
+ {
+ asize = 8; // Already quantized.
+ }
+
+ Quantize::FloydSteinberg(mipmap.asMutableFixedImage(), rsize, gsize, bsize, asize);
}
}
diff --git a/src/nvtt/tools/compress.cpp b/src/nvtt/tools/compress.cpp
index 4141249..b7a36e8 100644
--- a/src/nvtt/tools/compress.cpp
+++ b/src/nvtt/tools/compress.cpp
@@ -373,7 +373,6 @@ int main(int argc, char *argv[])
inputOptions.setMipmapGeneration(false);
}
-
nvtt::CompressionOptions compressionOptions;
compressionOptions.setFormat(format);
if (fast)
@@ -397,6 +396,21 @@ int main(int argc, char *argv[])
compressionOptions.setExternalCompressor(externalCompressor);
}
+ if (format == nvtt::Format_RGB)
+ {
+ compressionOptions.setQuantization(true, false, false);
+ //compressionOptions.setPixelFormat(16, 0xF000, 0x0F00, 0x00F0, 0x000F);
+ compressionOptions.setPixelFormat(16,
+ 0x0F00,
+ 0x00F0,
+ 0x000F,
+ 0xF000);
+ // 0x003F0000,
+ // 0x00003F00,
+ // 0x0000003F,
+ // 0x3F000000);
+ }
+
MyErrorHandler errorHandler;
MyOutputHandler outputHandler(output);