Implement quantization.
This commit is contained in:
parent
95b5e1decd
commit
12bf7f9346
@ -341,21 +341,19 @@ void Compressor::Private::quantize(TexImage & img, const CompressionOptions::Pri
|
||||
{
|
||||
if (compressionOptions.enableColorDithering) {
|
||||
if (compressionOptions.format >= Format_BC1 && compressionOptions.format <= Format_BC3) {
|
||||
img.quantize(0, 5, true);
|
||||
img.quantize(1, 6, true);
|
||||
img.quantize(2, 5, true);
|
||||
img.quantize(0, 5, true, true);
|
||||
img.quantize(1, 6, true, true);
|
||||
img.quantize(2, 5, true, true);
|
||||
}
|
||||
else if (compressionOptions.format == Format_RGB) {
|
||||
img.quantize(0, compressionOptions.rsize, true);
|
||||
img.quantize(1, compressionOptions.gsize, true);
|
||||
img.quantize(2, compressionOptions.bsize, true);
|
||||
img.quantize(0, compressionOptions.rsize, true, true);
|
||||
img.quantize(1, compressionOptions.gsize, true, true);
|
||||
img.quantize(2, compressionOptions.bsize, true, true);
|
||||
}
|
||||
}
|
||||
if (compressionOptions.enableAlphaDithering) {
|
||||
if (compressionOptions.format == Format_RGB) {
|
||||
img.quantize(0, compressionOptions.rsize, true);
|
||||
img.quantize(1, compressionOptions.gsize, true);
|
||||
img.quantize(2, compressionOptions.bsize, true);
|
||||
img.quantize(3, compressionOptions.asize, true, true);
|
||||
}
|
||||
}
|
||||
else if (compressionOptions.binaryAlpha) {
|
||||
|
@ -1038,33 +1038,6 @@ void TexImage::scaleAlphaToCoverage(float coverage, float alphaRef/*= 0.5f*/)
|
||||
m->image->scaleAlphaToCoverage(coverage, alphaRef, 3);
|
||||
}
|
||||
|
||||
/*bool TexImage::normalizeRange(float * rangeMin, float * rangeMax)
|
||||
{
|
||||
if (m->image == NULL) return false;
|
||||
|
||||
range(0, rangeMin, rangeMax);
|
||||
|
||||
if (*rangeMin == *rangeMax) {
|
||||
// Single color image.
|
||||
return false;
|
||||
}
|
||||
|
||||
const float scale = 1.0f / (*rangeMax - *rangeMin);
|
||||
const float bias = *rangeMin * scale;
|
||||
|
||||
if (range.x == 0.0f && range.y == 1.0f) {
|
||||
// Already normalized.
|
||||
return true;
|
||||
}
|
||||
|
||||
detach();
|
||||
|
||||
// Scale to range.
|
||||
img->scaleBias(0, 4, scale, bias);
|
||||
//img->clamp(0, 4, 0.0f, 1.0f);
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
// Ideally you should compress/quantize the RGB and M portions independently.
|
||||
// Once you have M quantized, you would compute the corresponding RGB and quantize that.
|
||||
@ -1300,6 +1273,7 @@ void TexImage::abs(int channel)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void TexImage::blockLuminanceScale(float scale)
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
@ -1372,7 +1346,9 @@ void TexImage::blockLuminanceScale(float scale)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void TexImage::toJPEGLS()
|
||||
{
|
||||
if (m->image == NULL) return;
|
||||
@ -1418,17 +1394,127 @@ void TexImage::fromJPEGLS()
|
||||
b[i] = B+G;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void TexImage::binarize(int channel, float threshold, bool dither)
|
||||
{
|
||||
#pragma NV_MESSAGE("binarize not implemented")
|
||||
if (m->image == NULL) return;
|
||||
|
||||
detach();
|
||||
|
||||
FloatImage * img = m->image;
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
if (!dither) {
|
||||
float * c = img->channel(channel);
|
||||
const uint count = w * h;
|
||||
for (uint i = 0; i < count; i++) {
|
||||
c[i] = float(c[i] > threshold);
|
||||
}
|
||||
}
|
||||
else {
|
||||
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++) {
|
||||
|
||||
float & f = img->pixel(x, y, channel);
|
||||
|
||||
// Add error and quantize.
|
||||
float qf = float(f + row0[1+x] > threshold);
|
||||
|
||||
// Compute new error:
|
||||
float diff = f - qf;
|
||||
|
||||
// Store color.
|
||||
f = qf;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
void TexImage::quantize(int channel, int bits, bool dither)
|
||||
// Uniform quantizer.
|
||||
// Assumes input is in [0, 1] range. Output is in the [0, 1] range, but rounded to the middle of each bin.
|
||||
// If exactEndPoints is true, [0, 1] are represented exactly, and the correponding bins are half the size, so quantization is not truly uniform.
|
||||
void TexImage::quantize(int channel, int bits, bool exactEndPoints, bool dither)
|
||||
{
|
||||
#pragma NV_MESSAGE("quantize not implemented")
|
||||
if (m->image == NULL) return;
|
||||
|
||||
detach();
|
||||
|
||||
FloatImage * img = m->image;
|
||||
const uint w = img->width();
|
||||
const uint h = img->height();
|
||||
|
||||
float scale, offset;
|
||||
|
||||
if (exactEndPoints) {
|
||||
scale = (1 << bits) - 1;
|
||||
offset = 0.0f;
|
||||
}
|
||||
else {
|
||||
scale = (1 << bits);
|
||||
offset = 0.5f;
|
||||
}
|
||||
|
||||
if (!dither) {
|
||||
float * c = img->channel(channel);
|
||||
const uint count = w * h;
|
||||
for (uint i = 0; i < count; i++) {
|
||||
c[i] = floorf(c[i] * scale + offset) / scale;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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++) {
|
||||
|
||||
float & f = img->pixel(x, y, channel);
|
||||
|
||||
// Add error and quantize.
|
||||
float qf = floorf((f + row0[1+x]) * scale + offset) / scale;
|
||||
|
||||
// Compute new error:
|
||||
float diff = f - qf;
|
||||
|
||||
// Store color.
|
||||
f = qf;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,7 +443,6 @@ namespace nvtt
|
||||
NVTT_API void setBorder(float r, float g, float b, float a);
|
||||
NVTT_API void fill(float r, float g, float b, float a);
|
||||
NVTT_API void scaleAlphaToCoverage(float coverage, float alphaRef = 0.5f);
|
||||
//NVTT_API bool normalizeRange(float * rangeMin, float * rangeMax);
|
||||
NVTT_API void toRGBM(float range = 1.0f, float threshold = 0.0f);
|
||||
NVTT_API void fromRGBM(float range = 1.0f);
|
||||
NVTT_API void toYCoCg();
|
||||
@ -452,14 +451,12 @@ namespace nvtt
|
||||
NVTT_API void toLUVW(float range = 1.0f);
|
||||
NVTT_API void fromLUVW(float range = 1.0f);
|
||||
NVTT_API void abs(int channel);
|
||||
NVTT_API void toJPEGLS();
|
||||
NVTT_API void fromJPEGLS();
|
||||
|
||||
NVTT_API void blockLuminanceScale(float scale);
|
||||
//NVTT_API void blockLuminanceScale(float scale);
|
||||
|
||||
// Color quantization.
|
||||
NVTT_API void binarize(int channel, float threshold, bool dither);
|
||||
NVTT_API void quantize(int channel, int bits, bool dither);
|
||||
NVTT_API void quantize(int channel, int bits, bool exactEndPoints, bool dither);
|
||||
|
||||
// Normal map transforms.
|
||||
NVTT_API void toNormalMap(float sm, float medium, float big, float large);
|
||||
|
Loading…
Reference in New Issue
Block a user