Implement general scale filter, including upsampling
This commit is contained in:
parent
d38e970221
commit
c59e4db15a
|
@ -2,6 +2,7 @@ NVIDIA Texture Tools version 2.0.4
|
||||||
* Fix error in RGB format output; reported by jonsoh. See issue 49.
|
* Fix error in RGB format output; reported by jonsoh. See issue 49.
|
||||||
* Added support RGB format dithering by jonsoh. Fixes issue 50 and 51.
|
* Added support RGB format dithering by jonsoh. Fixes issue 50 and 51.
|
||||||
* Prevent infinite loop in indexMirror when width equal 1. Fixes issue 65.
|
* Prevent infinite loop in indexMirror when width equal 1. Fixes issue 65.
|
||||||
|
* Implement general scale filter, including upsampling.
|
||||||
|
|
||||||
NVIDIA Texture Tools version 2.0.3
|
NVIDIA Texture Tools version 2.0.3
|
||||||
* More accurate DXT3 compressor. Fixes issue 38.
|
* More accurate DXT3 compressor. Fixes issue 38.
|
||||||
|
|
|
@ -541,12 +541,17 @@ void Kernel2::initBlendedSobel(const Vector4 & scale)
|
||||||
|
|
||||||
PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples/*= 32*/)
|
PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples/*= 32*/)
|
||||||
{
|
{
|
||||||
nvCheck(srcLength >= dstLength); // @@ Upsampling not implemented!
|
|
||||||
nvDebugCheck(samples > 0);
|
nvDebugCheck(samples > 0);
|
||||||
|
|
||||||
const float scale = float(dstLength) / float(srcLength);
|
float scale = float(dstLength) / float(srcLength);
|
||||||
const float iscale = 1.0f / scale;
|
const float iscale = 1.0f / scale;
|
||||||
|
|
||||||
|
if (scale > 1) {
|
||||||
|
// Upsampling.
|
||||||
|
samples = 1;
|
||||||
|
scale = 1;
|
||||||
|
}
|
||||||
|
|
||||||
m_length = dstLength;
|
m_length = dstLength;
|
||||||
m_width = f.width() * iscale;
|
m_width = f.width() * iscale;
|
||||||
m_windowSize = (int)ceilf(m_width * 2) + 1;
|
m_windowSize = (int)ceilf(m_width * 2) + 1;
|
||||||
|
@ -577,6 +582,7 @@ PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLengt
|
||||||
m_data[i * m_windowSize + j] /= total;
|
m_data[i * m_windowSize + j] /= total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PolyphaseKernel::~PolyphaseKernel()
|
PolyphaseKernel::~PolyphaseKernel()
|
||||||
|
|
|
@ -540,73 +540,18 @@ FloatImage * FloatImage::fastDownSample() const
|
||||||
return dst_image.release();
|
return dst_image.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Downsample applying a 1D kernel separately in each dimension.
|
|
||||||
FloatImage * FloatImage::downSample(const Kernel1 & kernel, WrapMode wm) const
|
|
||||||
{
|
|
||||||
const uint w = max(1, m_width / 2);
|
|
||||||
const uint h = max(1, m_height / 2);
|
|
||||||
|
|
||||||
return downSample(kernel, w, h, wm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Downsample applying a 1D kernel separately in each dimension.
|
|
||||||
FloatImage * FloatImage::downSample(const Kernel1 & kernel, uint w, uint h, WrapMode wm) const
|
|
||||||
{
|
|
||||||
nvCheck(!(kernel.windowSize() & 1)); // Make sure that kernel m_width is even.
|
|
||||||
|
|
||||||
AutoPtr<FloatImage> tmp_image( new FloatImage() );
|
|
||||||
tmp_image->allocate(m_componentNum, w, m_height);
|
|
||||||
|
|
||||||
AutoPtr<FloatImage> dst_image( new FloatImage() );
|
|
||||||
dst_image->allocate(m_componentNum, w, h);
|
|
||||||
|
|
||||||
const float xscale = float(m_width) / float(w);
|
|
||||||
const float yscale = float(m_height) / float(h);
|
|
||||||
|
|
||||||
for(uint c = 0; c < m_componentNum; c++) {
|
|
||||||
float * tmp_channel = tmp_image->channel(c);
|
|
||||||
|
|
||||||
for(uint y = 0; y < m_height; y++) {
|
|
||||||
for(uint x = 0; x < w; x++) {
|
|
||||||
|
|
||||||
float sum = this->applyKernelHorizontal(&kernel, uint(x*xscale), y, c, wm);
|
|
||||||
|
|
||||||
const uint tmp_index = tmp_image->index(x, y);
|
|
||||||
tmp_channel[tmp_index] = sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float * dst_channel = dst_image->channel(c);
|
|
||||||
|
|
||||||
for(uint y = 0; y < h; y++) {
|
|
||||||
for(uint x = 0; x < w; x++) {
|
|
||||||
|
|
||||||
float sum = tmp_image->applyKernelVertical(&kernel, uint(x*xscale), uint(y*yscale), c, wm);
|
|
||||||
|
|
||||||
const uint dst_index = dst_image->index(x, y);
|
|
||||||
dst_channel[dst_index] = sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst_image.release();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Downsample applying a 1D kernel separately in each dimension.
|
/// Downsample applying a 1D kernel separately in each dimension.
|
||||||
FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm) const
|
FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm) const
|
||||||
{
|
{
|
||||||
const uint w = max(1, m_width / 2);
|
const uint w = max(1, m_width / 2);
|
||||||
const uint h = max(1, m_height / 2);
|
const uint h = max(1, m_height / 2);
|
||||||
|
|
||||||
return downSample(filter, w, h, wm);
|
return resize(filter, w, h, wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Downsample applying a 1D kernel separately in each dimension.
|
/// Downsample applying a 1D kernel separately in each dimension.
|
||||||
FloatImage * FloatImage::downSample(const Filter & filter, uint w, uint h, WrapMode wm) const
|
FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode wm) const
|
||||||
{
|
{
|
||||||
// @@ Use monophase filters when frac(m_width / w) == 0
|
// @@ Use monophase filters when frac(m_width / w) == 0
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
|
|
||||||
NVIMAGE_API FloatImage * fastDownSample() const;
|
NVIMAGE_API FloatImage * fastDownSample() const;
|
||||||
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const;
|
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const;
|
||||||
NVIMAGE_API FloatImage * downSample(const Filter & filter, uint w, uint h, WrapMode wm) const;
|
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const;
|
||||||
|
|
||||||
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const;
|
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const;
|
||||||
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const;
|
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const;
|
||||||
|
|
|
@ -571,7 +571,7 @@ void Compressor::Private::scaleMipmap(Mipmap & mipmap, const InputOptions::Priva
|
||||||
|
|
||||||
// Resize image.
|
// Resize image.
|
||||||
BoxFilter boxFilter;
|
BoxFilter boxFilter;
|
||||||
mipmap.setImage(mipmap.asFloatImage()->downSample(boxFilter, w, h, (FloatImage::WrapMode)inputOptions.wrapMode));
|
mipmap.setImage(mipmap.asFloatImage()->resize(boxFilter, w, h, (FloatImage::WrapMode)inputOptions.wrapMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
float scale = 0.5f;
|
float scale = 0.5f;
|
||||||
float gamma = 2.2f;
|
float gamma = 2.2f;
|
||||||
nv::Filter * filter = NULL;
|
nv::AutoPtr<nv::Filter> filter;
|
||||||
nv::Path input;
|
nv::Path input;
|
||||||
nv::Path output;
|
nv::Path output;
|
||||||
|
|
||||||
|
nv::FloatImage::WrapMode wrapMode = nv::FloatImage::WrapMode_Mirror;
|
||||||
|
|
||||||
// Parse arguments.
|
// Parse arguments.
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
|
@ -108,9 +110,18 @@ int main(int argc, char *argv[])
|
||||||
else if (strcmp("lanczos", argv[i]) == 0) filter = new nv::LanczosFilter();
|
else if (strcmp("lanczos", argv[i]) == 0) filter = new nv::LanczosFilter();
|
||||||
else if (strcmp("kaiser", argv[i]) == 0) {
|
else if (strcmp("kaiser", argv[i]) == 0) {
|
||||||
filter = new nv::KaiserFilter(3);
|
filter = new nv::KaiserFilter(3);
|
||||||
((nv::KaiserFilter *)filter)->setParameters(4.0f, 1.0f);
|
((nv::KaiserFilter *)filter.ptr())->setParameters(4.0f, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
{
|
||||||
|
if (i+1 == argc) break;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (strcmp("mirror", argv[i]) == 0) wrapMode = nv::FloatImage::WrapMode_Mirror;
|
||||||
|
else if (strcmp("repeat", argv[i]) == 0) wrapMode = nv::FloatImage::WrapMode_Repeat;
|
||||||
|
else if (strcmp("clamp", argv[i]) == 0) wrapMode = nv::FloatImage::WrapMode_Clamp;
|
||||||
|
}
|
||||||
else if (argv[i][0] != '-')
|
else if (argv[i][0] != '-')
|
||||||
{
|
{
|
||||||
input = argv[i];
|
input = argv[i];
|
||||||
|
@ -140,6 +151,10 @@ int main(int argc, char *argv[])
|
||||||
printf(" * mitchell\n");
|
printf(" * mitchell\n");
|
||||||
printf(" * lanczos\n");
|
printf(" * lanczos\n");
|
||||||
printf(" * kaiser\n");
|
printf(" * kaiser\n");
|
||||||
|
printf(" -w mode One of the following: (default = 'mirror')\n");
|
||||||
|
printf(" * mirror\n");
|
||||||
|
printf(" * repeat\n");
|
||||||
|
printf(" * clamp\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -155,15 +170,14 @@ int main(int argc, char *argv[])
|
||||||
nv::FloatImage fimage(&image);
|
nv::FloatImage fimage(&image);
|
||||||
fimage.toLinear(0, 3, gamma);
|
fimage.toLinear(0, 3, gamma);
|
||||||
|
|
||||||
nv::AutoPtr<nv::FloatImage> fresult(fimage.downSample(*filter, uint(image.width() * scale), uint(image.height() * scale), nv::FloatImage::WrapMode_Mirror));
|
nv::AutoPtr<nv::FloatImage> fresult(fimage.resize(*filter, uint(image.width() * scale), uint(image.height() * scale), wrapMode));
|
||||||
|
|
||||||
nv::AutoPtr<nv::Image> result(fresult->createImageGammaCorrect(gamma));
|
nv::AutoPtr<nv::Image> result(fresult->createImageGammaCorrect(gamma));
|
||||||
|
result->setFormat(nv::Image::Format_ARGB);
|
||||||
|
|
||||||
nv::StdOutputStream stream(output);
|
nv::StdOutputStream stream(output);
|
||||||
nv::ImageIO::saveTGA(stream, result.ptr()); // @@ Add generic save function. Add support for png too.
|
nv::ImageIO::saveTGA(stream, result.ptr()); // @@ Add generic save function. Add support for png too.
|
||||||
|
|
||||||
delete filter;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user