Cleanup filters.
This commit is contained in:
parent
3359090581
commit
067f3abf54
@ -100,6 +100,10 @@ Filter::Filter(float width) : m_width(width)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Filter::~Filter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
float Filter::sample(float x, float scale, int samples) const
|
float Filter::sample(float x, float scale, int samples) const
|
||||||
{
|
{
|
||||||
// return evaluate(x * scale);
|
// return evaluate(x * scale);
|
||||||
@ -223,11 +227,9 @@ KaiserFilter::KaiserFilter(float w) : Filter(w) { setParameters(4.0f, 1.0f); }
|
|||||||
float KaiserFilter::evaluate(float x) const
|
float KaiserFilter::evaluate(float x) const
|
||||||
{
|
{
|
||||||
const float sinc_value = sincf(PI * x * stretch);
|
const float sinc_value = sincf(PI * x * stretch);
|
||||||
float t = x / m_width;
|
const float t = x / m_width;
|
||||||
if (t * t <= 1.0f)
|
if ((1 - t * t) >= 0) return sinc_value * bessel0(alpha * sqrtf(1 - t * t)) / bessel0(alpha);
|
||||||
return sinc_value * bessel0(alpha * sqrtf(1 - t * t)) / bessel0(alpha);
|
else return 0;
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KaiserFilter::setParameters(float alpha, float stretch)
|
void KaiserFilter::setParameters(float alpha, float stretch)
|
||||||
@ -239,17 +241,31 @@ void KaiserFilter::setParameters(float alpha, float stretch)
|
|||||||
|
|
||||||
|
|
||||||
/// Ctor.
|
/// Ctor.
|
||||||
Kernel1::Kernel1(uint ws) : m_windowSize(ws)
|
Kernel1::Kernel1(const Filter & f, int iscale, int samples/*= 32*/)
|
||||||
{
|
{
|
||||||
m_data = new float[m_windowSize];
|
nvDebugCheck(iscale > 1);
|
||||||
}
|
nvDebugCheck(samples > 0);
|
||||||
|
|
||||||
/// Copy ctor.
|
const float scale = 1.0f / iscale;
|
||||||
Kernel1::Kernel1(const Kernel1 & k) : m_windowSize(k.m_windowSize)
|
|
||||||
{
|
m_width = f.width() * iscale;
|
||||||
|
m_windowSize = ceilf(2 * m_width);
|
||||||
m_data = new float[m_windowSize];
|
m_data = new float[m_windowSize];
|
||||||
for(uint i = 0; i < m_windowSize; i++) {
|
|
||||||
m_data[i] = k.m_data[i];
|
const float offset = float(m_windowSize) / 2;
|
||||||
|
|
||||||
|
float total = 0.0f;
|
||||||
|
for (int i = 0; i < m_windowSize; i++)
|
||||||
|
{
|
||||||
|
const float sample = f.sample(i - offset, scale, samples);
|
||||||
|
m_data[i] = sample;
|
||||||
|
total += sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float inv = 1.0f / total;
|
||||||
|
for (int i = 0; i < m_windowSize; i++)
|
||||||
|
{
|
||||||
|
m_data[i] *= inv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,103 +275,10 @@ Kernel1::~Kernel1()
|
|||||||
delete m_data;
|
delete m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalize the filter.
|
|
||||||
void Kernel1::normalize()
|
|
||||||
{
|
|
||||||
float total = 0.0f;
|
|
||||||
for(uint i = 0; i < m_windowSize; i++) {
|
|
||||||
total += m_data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
float inv = 1.0f / total;
|
|
||||||
for(uint i = 0; i < m_windowSize; i++) {
|
|
||||||
m_data[i] *= inv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/// Init 1D filter.
|
|
||||||
void Kernel1::initFilter(Filter::Enum f, int samples /*= 1*/)
|
|
||||||
{
|
|
||||||
nvDebugCheck(f < Filter::Num);
|
|
||||||
nvDebugCheck(samples >= 1);
|
|
||||||
|
|
||||||
float (* filter_function)(float) = s_filter_array[f].function;
|
|
||||||
const float support = s_filter_array[f].support;
|
|
||||||
|
|
||||||
const float halfWindowSize = float(m_windowSize) / 2.0f;
|
|
||||||
const float scale = support / halfWindowSize;
|
|
||||||
|
|
||||||
for(uint i = 0; i < m_windowSize; i++)
|
|
||||||
{
|
|
||||||
m_data[i] = sampleFilter(filter_function, i - halfWindowSize, scale, samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Init 1D sinc filter.
|
|
||||||
void Kernel1::initSinc(float stretch /*= 1*/)
|
|
||||||
{
|
|
||||||
const float halfWindowSize = float(m_windowSize) / 2;
|
|
||||||
const float nudge = 0.5f;
|
|
||||||
|
|
||||||
for(uint i = 0; i < m_windowSize; i++) {
|
|
||||||
const float x = (i - halfWindowSize) + nudge;
|
|
||||||
m_data[i] = sincf(PI * x * stretch);
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Init 1D Kaiser-windowed sinc filter.
|
|
||||||
void Kernel1::initKaiser(float alpha /*= 4*/, float stretch /*= 0.5*/, int samples/*= 1*/)
|
|
||||||
{
|
|
||||||
const float halfWindowSize = float(m_windowSize) / 2;
|
|
||||||
|
|
||||||
const float s_scale = 1.0f / float(samples);
|
|
||||||
const float x_scale = 1.0f / halfWindowSize;
|
|
||||||
|
|
||||||
for(uint i = 0; i < m_windowSize; i++)
|
|
||||||
{
|
|
||||||
float sum = 0;
|
|
||||||
for(int s = 0; s < samples; s++)
|
|
||||||
{
|
|
||||||
float x = i - halfWindowSize + (s + 0.5f) * s_scale;
|
|
||||||
|
|
||||||
const float sinc_value = sincf(PI * x * stretch);
|
|
||||||
const float window_value = filter_kaiser(x * x_scale, alpha); // @@ should the window be streched? I don't think so.
|
|
||||||
|
|
||||||
sum += sinc_value * window_value;
|
|
||||||
}
|
|
||||||
m_data[i] = sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Init 1D Mitchell filter.
|
|
||||||
void Kernel1::initMitchell(float b, float c)
|
|
||||||
{
|
|
||||||
const float halfWindowSize = float(m_windowSize) / 2;
|
|
||||||
const float nudge = 0.5f;
|
|
||||||
|
|
||||||
for (uint i = 0; i < m_windowSize; i++) {
|
|
||||||
const float x = (i - halfWindowSize) + nudge;
|
|
||||||
m_data[i] = filter_mitchell(x / halfWindowSize, b, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Print the kernel for debugging purposes.
|
/// Print the kernel for debugging purposes.
|
||||||
void Kernel1::debugPrint()
|
void Kernel1::debugPrint()
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < m_windowSize; i++) {
|
for (int i = 0; i < m_windowSize; i++) {
|
||||||
nvDebug("%d: %f\n", i, m_data[i]);
|
nvDebug("%d: %f\n", i, m_data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,41 +513,13 @@ void Kernel2::initBlendedSobel(const Vector4 & scale)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static float frac(float f)
|
PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples/*= 32*/)
|
||||||
{
|
{
|
||||||
return f - floorf(f);
|
nvCheck(srcLength >= dstLength); // @@ Upsampling not implemented!
|
||||||
}
|
nvDebugCheck(samples > 0);
|
||||||
|
|
||||||
static bool isMonoPhase(float w)
|
const float scale = float(dstLength) / float(srcLength);
|
||||||
{
|
const float iscale = 1.0f / scale;
|
||||||
return isZero(frac(w));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
PolyphaseKernel::PolyphaseKernel(float w, uint l) :
|
|
||||||
m_width(w),
|
|
||||||
m_size(ceilf(w) + 1),
|
|
||||||
m_length(l)
|
|
||||||
{
|
|
||||||
// size = width + (length - 1) * phase
|
|
||||||
m_data = new float[m_size * m_length];
|
|
||||||
}
|
|
||||||
|
|
||||||
PolyphaseKernel::PolyphaseKernel(const PolyphaseKernel & k) :
|
|
||||||
m_width(k.m_width),
|
|
||||||
m_size(k.m_size),
|
|
||||||
m_length(k.m_length)
|
|
||||||
{
|
|
||||||
m_data = new float[m_size * m_length];
|
|
||||||
memcpy(m_data, k.m_data, sizeof(float) * m_size * m_length);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength)
|
|
||||||
{
|
|
||||||
float scale = float(dstLength) / float(srcLength);
|
|
||||||
float iscale = 1.0f / scale;
|
|
||||||
|
|
||||||
m_length = dstLength;
|
m_length = dstLength;
|
||||||
m_width = f.width() * iscale;
|
m_width = f.width() * iscale;
|
||||||
@ -637,14 +532,14 @@ PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLengt
|
|||||||
{
|
{
|
||||||
const float center = (0.5f + i) * iscale;
|
const float center = (0.5f + i) * iscale;
|
||||||
|
|
||||||
int left = floor(center - m_width);
|
const int left = floorf(center - m_width);
|
||||||
int right = ceil(center + m_width);
|
const int right = ceilf(center + m_width);
|
||||||
nvCheck(right - left <= (int)m_windowSize);
|
nvDebugCheck(right - left <= m_windowSize);
|
||||||
|
|
||||||
float total = 0.0f;
|
float total = 0.0f;
|
||||||
for (int j = 0; j < m_windowSize; j++)
|
for (int j = 0; j < m_windowSize; j++)
|
||||||
{
|
{
|
||||||
float sample = f.sample(left + j - center, scale, 40);
|
const float sample = f.sample(left + j - center, scale, samples);
|
||||||
|
|
||||||
m_data[i * m_windowSize + j] = sample;
|
m_data[i * m_windowSize + j] = sample;
|
||||||
total += sample;
|
total += sample;
|
||||||
@ -670,7 +565,7 @@ void PolyphaseKernel::debugPrint() const
|
|||||||
for (uint i = 0; i < m_length; i++)
|
for (uint i = 0; i < m_length; i++)
|
||||||
{
|
{
|
||||||
nvDebug("%d: ", i);
|
nvDebug("%d: ", i);
|
||||||
for (uint j = 0; j < m_windowSize; j++)
|
for (int j = 0; j < m_windowSize; j++)
|
||||||
{
|
{
|
||||||
nvDebug(" %6.4f", m_data[i * m_windowSize + j]);
|
nvDebug(" %6.4f", m_data[i * m_windowSize + j]);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#define NV_IMAGE_FILTER_H
|
#define NV_IMAGE_FILTER_H
|
||||||
|
|
||||||
#include <nvimage/nvimage.h>
|
#include <nvimage/nvimage.h>
|
||||||
|
#include <nvcore/Debug.h>
|
||||||
|
|
||||||
namespace nv
|
namespace nv
|
||||||
{
|
{
|
||||||
@ -14,6 +15,7 @@ namespace nv
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NVIMAGE_API Filter(float width);
|
NVIMAGE_API Filter(float width);
|
||||||
|
NVIMAGE_API virtual ~Filter();
|
||||||
|
|
||||||
NVIMAGE_API float width() const { return m_width; }
|
NVIMAGE_API float width() const { return m_width; }
|
||||||
NVIMAGE_API float sample(float x, float scale, int samples) const;
|
NVIMAGE_API float sample(float x, float scale, int samples) const;
|
||||||
@ -116,31 +118,29 @@ namespace nv
|
|||||||
/// A 1D kernel. Used to precompute filter weights.
|
/// A 1D kernel. Used to precompute filter weights.
|
||||||
class Kernel1
|
class Kernel1
|
||||||
{
|
{
|
||||||
|
NV_FORBID_COPY(Kernel1);
|
||||||
public:
|
public:
|
||||||
NVIMAGE_API Kernel1(uint windowSize);
|
NVIMAGE_API Kernel1(const Filter & f, int iscale, int samples = 32);
|
||||||
NVIMAGE_API Kernel1(const Kernel1 & k);
|
|
||||||
NVIMAGE_API ~Kernel1();
|
NVIMAGE_API ~Kernel1();
|
||||||
|
|
||||||
NVIMAGE_API void normalize();
|
|
||||||
|
|
||||||
float valueAt(uint x) const {
|
float valueAt(uint x) const {
|
||||||
|
nvDebugCheck(x < (uint)m_windowSize);
|
||||||
return m_data[x];
|
return m_data[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint windowSize() const {
|
int windowSize() const {
|
||||||
return m_windowSize;
|
return m_windowSize;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
NVIMAGE_API void initFilter(Filter::Enum filter, int samples = 1);
|
float width() const {
|
||||||
NVIMAGE_API void initSinc(float stretch = 1);
|
return m_width;
|
||||||
NVIMAGE_API void initKaiser(float alpha = 4.0f, float stretch = 1.0f, int sampes = 1);
|
}
|
||||||
NVIMAGE_API void initMitchell(float b = 1.0f/3.0f, float c = 1.0f/3.0f);
|
|
||||||
*/
|
|
||||||
|
|
||||||
NVIMAGE_API void debugPrint();
|
NVIMAGE_API void debugPrint();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint m_windowSize;
|
int m_windowSize;
|
||||||
|
float m_width;
|
||||||
float * m_data;
|
float * m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,12 +180,12 @@ namespace nv
|
|||||||
/// A 1D polyphase kernel
|
/// A 1D polyphase kernel
|
||||||
class PolyphaseKernel
|
class PolyphaseKernel
|
||||||
{
|
{
|
||||||
NV_FORBID_COPY(PolyphaseKernel)
|
NV_FORBID_COPY(PolyphaseKernel);
|
||||||
public:
|
public:
|
||||||
NVIMAGE_API PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength);
|
NVIMAGE_API PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples = 32);
|
||||||
NVIMAGE_API ~PolyphaseKernel();
|
NVIMAGE_API ~PolyphaseKernel();
|
||||||
|
|
||||||
uint windowSize() const {
|
int windowSize() const {
|
||||||
return m_windowSize;
|
return m_windowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,14 +199,14 @@ namespace nv
|
|||||||
|
|
||||||
float valueAt(uint column, uint x) const {
|
float valueAt(uint column, uint x) const {
|
||||||
nvDebugCheck(column < m_length);
|
nvDebugCheck(column < m_length);
|
||||||
nvDebugCheck(x < m_windowSize);
|
nvDebugCheck(x < (uint)m_windowSize);
|
||||||
return m_data[column * m_windowSize + x];
|
return m_data[column * m_windowSize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
NVIMAGE_API void debugPrint() const;
|
NVIMAGE_API void debugPrint() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint m_windowSize;
|
int m_windowSize;
|
||||||
uint m_length;
|
uint m_length;
|
||||||
float m_width;
|
float m_width;
|
||||||
float * m_data;
|
float * m_data;
|
||||||
|
@ -599,17 +599,18 @@ FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm) const
|
|||||||
return downSample(filter, w, h, wm);
|
return downSample(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::downSample(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
|
||||||
|
|
||||||
PolyphaseKernel xkernel(filter, m_width, w);
|
|
||||||
PolyphaseKernel ykernel(filter, m_height, h);
|
|
||||||
|
|
||||||
AutoPtr<FloatImage> tmp_image( new FloatImage() );
|
AutoPtr<FloatImage> tmp_image( new FloatImage() );
|
||||||
AutoPtr<FloatImage> dst_image( new FloatImage() );
|
AutoPtr<FloatImage> dst_image( new FloatImage() );
|
||||||
|
|
||||||
|
PolyphaseKernel xkernel(filter, m_width, w, 32);
|
||||||
|
PolyphaseKernel ykernel(filter, m_height, h, 32);
|
||||||
|
|
||||||
// @@ Select fastest filtering order:
|
// @@ Select fastest filtering order:
|
||||||
//if (w * m_height <= h * m_width)
|
//if (w * m_height <= h * m_width)
|
||||||
{
|
{
|
||||||
@ -748,12 +749,12 @@ float FloatImage::applyKernelHorizontal(const Kernel1 * k, int x, int y, int c,
|
|||||||
/// Apply 1D vertical kernel at the given coordinates and return result.
|
/// Apply 1D vertical kernel at the given coordinates and return result.
|
||||||
void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, int c, WrapMode wm, float * output) const
|
void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, int c, WrapMode wm, float * output) const
|
||||||
{
|
{
|
||||||
uint length = k.length();
|
const uint length = k.length();
|
||||||
float scale = float(length) / float(m_height);
|
const float scale = float(length) / float(m_height);
|
||||||
float iscale = 1.0f / scale;
|
const float iscale = 1.0f / scale;
|
||||||
|
|
||||||
float width = k.width();
|
const float width = k.width();
|
||||||
float windowSize = k.windowSize();
|
const int windowSize = k.windowSize();
|
||||||
|
|
||||||
const float * channel = this->channel(c);
|
const float * channel = this->channel(c);
|
||||||
|
|
||||||
@ -761,9 +762,8 @@ void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, int c, Wr
|
|||||||
{
|
{
|
||||||
const float center = (0.5f + i) * iscale;
|
const float center = (0.5f + i) * iscale;
|
||||||
|
|
||||||
int left = floor(center - width);
|
const int left = floor(center - width);
|
||||||
int right = ceil(center + width);
|
const int right = ceil(center + width);
|
||||||
|
|
||||||
nvCheck(right - left <= windowSize);
|
nvCheck(right - left <= windowSize);
|
||||||
|
|
||||||
float sum = 0;
|
float sum = 0;
|
||||||
@ -776,43 +776,17 @@ void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, int c, Wr
|
|||||||
|
|
||||||
output[i] = sum;
|
output[i] = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
const float kernelWidth = k->width();
|
|
||||||
const float kernelOffset = kernelWidth * 0.5f;
|
|
||||||
const int kernelLength = k->length();
|
|
||||||
const int kernelWindow = k->windowSize();
|
|
||||||
|
|
||||||
//const float offset = 0.5f * scale * (1 - kw);
|
|
||||||
const float offset = (0.5f * scale) - kernelOffset;
|
|
||||||
|
|
||||||
const float * channel = this->channel(c);
|
|
||||||
|
|
||||||
for (int y = 0; y < kernelLength; y++)
|
|
||||||
{
|
|
||||||
float sum = 0.0f;
|
|
||||||
for (int i = 0; i < kernelWindow; i++)
|
|
||||||
{
|
|
||||||
const int src_y = int(y * scale + offset) + i;
|
|
||||||
const int idx = this->index(x, src_y, wm);
|
|
||||||
|
|
||||||
sum += k->valueAt(y, i) * channel[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
output[y] = sum;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
||||||
void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, int c, WrapMode wm, float * output) const
|
void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, int c, WrapMode wm, float * output) const
|
||||||
{
|
{
|
||||||
uint length = k.length();
|
const uint length = k.length();
|
||||||
float scale = float(length) / float(m_width);
|
const float scale = float(length) / float(m_width);
|
||||||
float iscale = 1.0f / scale;
|
const float iscale = 1.0f / scale;
|
||||||
|
|
||||||
float width = k.width();
|
const float width = k.width();
|
||||||
float windowSize = k.windowSize();
|
const int windowSize = k.windowSize();
|
||||||
|
|
||||||
const float * channel = this->channel(c);
|
const float * channel = this->channel(c);
|
||||||
|
|
||||||
@ -820,9 +794,9 @@ void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, int c,
|
|||||||
{
|
{
|
||||||
const float center = (0.5f + i) * iscale;
|
const float center = (0.5f + i) * iscale;
|
||||||
|
|
||||||
int left = floor(center - width);
|
const int left = floorf(center - width);
|
||||||
int right = ceil(center + width);
|
const int right = ceilf(center + width);
|
||||||
nvCheck(right - left <= (int)windowSize);
|
nvDebugCheck(right - left <= windowSize);
|
||||||
|
|
||||||
float sum = 0;
|
float sum = 0;
|
||||||
for (int j = 0; j < windowSize; ++j)
|
for (int j = 0; j < windowSize; ++j)
|
||||||
@ -834,30 +808,5 @@ void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, int c,
|
|||||||
|
|
||||||
output[i] = sum;
|
output[i] = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
const float kernelWidth = k->width();
|
|
||||||
const float kernelOffset = kernelWidth * 0.5f;
|
|
||||||
const int kernelLength = k->length();
|
|
||||||
const int kernelWindow = k->windowSize();
|
|
||||||
|
|
||||||
const float offset = (0.5f * scale) - kernelOffset;
|
|
||||||
|
|
||||||
const float * channel = this->channel(c);
|
|
||||||
|
|
||||||
for (int x = 0; x < kernelLength; x++)
|
|
||||||
{
|
|
||||||
float sum = 0.0f;
|
|
||||||
for (int e = 0; e < kernelWindow; e++)
|
|
||||||
{
|
|
||||||
const int src_x = int(x * scale + offset) + e;
|
|
||||||
const int idx = this->index(src_x, y, wm);
|
|
||||||
|
|
||||||
sum += k->valueAt(x, e) * channel[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
output[x] = sum;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user