Integrate branch 2.0 to trunk.
This commit is contained in:
parent
f402f28643
commit
5234060618
@ -243,7 +243,7 @@ SincFilter::SincFilter(float w) : Filter(w) {}
|
|||||||
|
|
||||||
float SincFilter::evaluate(float x) const
|
float SincFilter::evaluate(float x) const
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return sincf(PI * x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -540,12 +540,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;
|
||||||
|
@ -592,73 +592,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
|
||||||
|
|
||||||
|
@ -73,7 +73,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;
|
||||||
@ -239,11 +239,15 @@ inline uint FloatImage::indexRepeat(int x, int y) const
|
|||||||
|
|
||||||
inline uint FloatImage::indexMirror(int x, int y) const
|
inline uint FloatImage::indexMirror(int x, int y) const
|
||||||
{
|
{
|
||||||
|
if (m_width == 1) x = 0;
|
||||||
|
|
||||||
x = abs(x);
|
x = abs(x);
|
||||||
while (x >= m_width) {
|
while (x >= m_width) {
|
||||||
x = abs(m_width + m_width - x - 2);
|
x = abs(m_width + m_width - x - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_height == 1) y = 0;
|
||||||
|
|
||||||
y = abs(y);
|
y = abs(y);
|
||||||
while (y >= m_height) {
|
while (y >= m_height) {
|
||||||
y = abs(m_height + m_height - y - 2);
|
y = abs(m_height + m_height - y - 2);
|
||||||
|
@ -14,12 +14,12 @@ http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT
|
|||||||
|
|
||||||
#include <nvimage/Quantize.h>
|
#include <nvimage/Quantize.h>
|
||||||
#include <nvimage/Image.h>
|
#include <nvimage/Image.h>
|
||||||
|
#include <nvimage/PixelFormat.h>
|
||||||
|
|
||||||
#include <nvmath/Color.h>
|
#include <nvmath/Color.h>
|
||||||
|
|
||||||
#include <nvcore/Containers.h> // swap
|
#include <nvcore/Containers.h> // swap
|
||||||
|
|
||||||
#include <string.h> // memset
|
|
||||||
|
|
||||||
using namespace nv;
|
using namespace nv;
|
||||||
|
|
||||||
@ -51,94 +51,20 @@ void nv::Quantize::BinaryAlpha( Image * image, int alpha_threshold /*= 127*/ )
|
|||||||
// Simple quantization.
|
// Simple quantization.
|
||||||
void nv::Quantize::RGB16( Image * image )
|
void nv::Quantize::RGB16( Image * image )
|
||||||
{
|
{
|
||||||
nvCheck(image != NULL);
|
Truncate(image, 5, 6, 5, 8);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alpha quantization.
|
// Alpha quantization.
|
||||||
void nv::Quantize::Alpha4( Image * image )
|
void nv::Quantize::Alpha4( Image * image )
|
||||||
{
|
{
|
||||||
nvCheck(image != NULL);
|
Truncate(image, 8, 8, 8, 4);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Error diffusion. Floyd Steinberg.
|
// Error diffusion. Floyd Steinberg.
|
||||||
void nv::Quantize::FloydSteinberg_RGB16( Image * image )
|
void nv::Quantize::FloydSteinberg_RGB16( Image * image )
|
||||||
{
|
{
|
||||||
nvCheck(image != NULL);
|
FloydSteinberg(image, 5, 6, 5, 8);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -192,34 +118,90 @@ void nv::Quantize::FloydSteinberg_BinaryAlpha( Image * image, int alpha_threshol
|
|||||||
|
|
||||||
// Error diffusion. Floyd Steinberg.
|
// Error diffusion. Floyd Steinberg.
|
||||||
void nv::Quantize::FloydSteinberg_Alpha4( Image * image )
|
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);
|
nvCheck(image != NULL);
|
||||||
|
|
||||||
const uint w = image->width();
|
const uint w = image->width();
|
||||||
const uint h = image->height();
|
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 y = 0; y < h; y++) {
|
||||||
for(uint x = 0; x < w; x++) {
|
for(uint x = 0; x < w; x++) {
|
||||||
|
|
||||||
Color32 pixel = image->pixel(x, y);
|
Color32 pixel = image->pixel(x, y);
|
||||||
|
|
||||||
// Add error.
|
// Convert to our desired size, and reconstruct.
|
||||||
int alpha = int(pixel.a) + int(row0[1+x]);
|
pixel.r = PixelFormat::convert(pixel.r, 8, rsize);
|
||||||
|
pixel.r = PixelFormat::convert(pixel.r, rsize, 8);
|
||||||
|
|
||||||
// Convert to 4 bit using regular bit expansion.
|
pixel.g = PixelFormat::convert(pixel.g, 8, gsize);
|
||||||
pixel.a = (pixel.a & 0xF0) | ((pixel.a & 0xF0) >> 4);
|
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.
|
// Store color.
|
||||||
image->pixel(x, y) = pixel;
|
image->pixel(x, y) = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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.
|
// Compute new error.
|
||||||
float diff = float(alpha - pixel.a);
|
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.
|
// Propagate new error.
|
||||||
row0[1+x+1] += 7.0f / 16.0f * diff;
|
row0[1+x+1] += 7.0f / 16.0f * diff;
|
||||||
@ -229,10 +211,9 @@ void nv::Quantize::FloydSteinberg_Alpha4( Image * image )
|
|||||||
}
|
}
|
||||||
|
|
||||||
swap(row0, row1);
|
swap(row0, row1);
|
||||||
memset(row1, 0, sizeof(float)*(w+2));
|
memset(row1, 0, sizeof(Vector4)*(w+2));
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] row0;
|
delete [] row0;
|
||||||
delete [] row1;
|
delete [] row1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#ifndef NV_IMAGE_QUANTIZE_H
|
#ifndef NV_IMAGE_QUANTIZE_H
|
||||||
#define NV_IMAGE_QUANTIZE_H
|
#define NV_IMAGE_QUANTIZE_H
|
||||||
|
|
||||||
|
#include <nvimage/nvimage.h>
|
||||||
|
|
||||||
|
|
||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
class Image;
|
class Image;
|
||||||
@ -17,6 +20,9 @@ namespace nv
|
|||||||
void FloydSteinberg_BinaryAlpha(Image * img, int alpha_threshold = 127);
|
void FloydSteinberg_BinaryAlpha(Image * img, int alpha_threshold = 127);
|
||||||
void FloydSteinberg_Alpha4(Image * img);
|
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!
|
// @@ Add palette quantization algorithms!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <nvimage/Filter.h>
|
#include <nvimage/Filter.h>
|
||||||
#include <nvimage/Quantize.h>
|
#include <nvimage/Quantize.h>
|
||||||
#include <nvimage/NormalMap.h>
|
#include <nvimage/NormalMap.h>
|
||||||
|
#include <nvimage/PixelFormat.h>
|
||||||
#include <nvimage/ColorSpace.h>
|
#include <nvimage/ColorSpace.h>
|
||||||
|
|
||||||
#include "Compressor.h"
|
#include "Compressor.h"
|
||||||
@ -728,7 +729,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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -822,13 +823,6 @@ void Compressor::Private::quantizeMipmap(Mipmap & mipmap, const CompressionOptio
|
|||||||
{
|
{
|
||||||
nvDebugCheck(mipmap.asFixedImage() != NULL);
|
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.binaryAlpha)
|
||||||
{
|
{
|
||||||
if (compressionOptions.enableAlphaDithering)
|
if (compressionOptions.enableAlphaDithering)
|
||||||
@ -840,19 +834,50 @@ void Compressor::Private::quantizeMipmap(Mipmap & mipmap, const CompressionOptio
|
|||||||
Quantize::BinaryAlpha(mipmap.asMutableFixedImage(), compressionOptions.alphaThreshold);
|
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.enableAlphaDithering)
|
||||||
{
|
{
|
||||||
if (compressionOptions.format == Format_DXT3)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,8 +937,8 @@ bool Compressor::Private::compressMipmap(const Mipmap & mipmap, const InputOptio
|
|||||||
{
|
{
|
||||||
nvDebugCheck(cudaSupported);
|
nvDebugCheck(cudaSupported);
|
||||||
cuda->setImage(image, inputOptions.alphaMode);
|
cuda->setImage(image, inputOptions.alphaMode);
|
||||||
//cuda->compressDXT1(compressionOptions, outputOptions);
|
cuda->compressDXT1(compressionOptions, outputOptions);
|
||||||
cuda->compressDXT1_Tex(compressionOptions, outputOptions);
|
//cuda->compressDXT1_Tex(compressionOptions, outputOptions);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -231,16 +231,16 @@ inline __device__ bool singleColor(const float3 * colors)
|
|||||||
inline __device__ void colorSums(const float3 * colors, float3 * sums)
|
inline __device__ void colorSums(const float3 * colors, float3 * sums)
|
||||||
{
|
{
|
||||||
#if __DEVICE_EMULATION__
|
#if __DEVICE_EMULATION__
|
||||||
float3 color_sum = make_float3(0.0f, 0.0f, 0.0f);
|
float3 color_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
color_sum += colors[i];
|
color_sum += colors[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
sums[i] = color_sum;
|
sums[i] = color_sum;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
const int idx = threadIdx.x;
|
const int idx = threadIdx.x;
|
||||||
|
@ -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