diff --git a/src/nvtt/Context.cpp b/src/nvtt/Context.cpp index 6819461..9713cf0 100644 --- a/src/nvtt/Context.cpp +++ b/src/nvtt/Context.cpp @@ -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) { diff --git a/src/nvtt/TexImage.cpp b/src/nvtt/TexImage.cpp index e198472..6b5ad5f 100644 --- a/src/nvtt/TexImage.cpp +++ b/src/nvtt/TexImage.cpp @@ -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; + } } diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index f47ef4f..a67a5c6 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -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);