initial commit
This commit is contained in:
74
d2/filter/box.h
Normal file
74
d2/filter/box.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __d2_filter_box_h__
|
||||
#define __d2_filter_box_h__
|
||||
|
||||
/*
|
||||
* A box filter class.
|
||||
*/
|
||||
|
||||
class box : public filter {
|
||||
private:
|
||||
ale_pos half_width;
|
||||
|
||||
/*
|
||||
* Box filter.
|
||||
*/
|
||||
ale_real _box(ale_pos p) const {
|
||||
if (fabs(p) > half_width)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ale_real _box(point p) const {
|
||||
return _box(p[0]) * _box(p[1]);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
ale_pos support() const {
|
||||
return half_width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return _box(p);
|
||||
}
|
||||
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) == typeid(*this))
|
||||
return ((box *)f)->half_width == half_width;
|
||||
return 0;
|
||||
}
|
||||
|
||||
box(ale_pos half_width) {
|
||||
this->half_width = half_width;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
47
d2/filter/filter.h
Normal file
47
d2/filter/filter.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __filterclass_h__
|
||||
#define __filterclass_h__
|
||||
|
||||
/*
|
||||
* A superclass for all filtering classes.
|
||||
*/
|
||||
|
||||
class filter {
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
virtual ale_pos support() const = 0;
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const = 0;
|
||||
|
||||
virtual int equals(const filter *f) const = 0;
|
||||
|
||||
virtual ~filter(){
|
||||
}
|
||||
};
|
||||
#endif
|
||||
92
d2/filter/gauss.h
Normal file
92
d2/filter/gauss.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// code by HJ Hornbeck, based on code copyright David Hilvert
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __d2_filter_gauss_h__
|
||||
#define __d2_filter_gauss_h__
|
||||
|
||||
/*
|
||||
* A Gaussian filter.
|
||||
*/
|
||||
|
||||
class gauss : public filter {
|
||||
private:
|
||||
ale_pos sigma;
|
||||
ale_pos diameter; /** measured in standard deviations **/
|
||||
|
||||
/*
|
||||
* The heavy-lifting function:
|
||||
*/
|
||||
ale_real _calc(ale_pos p) const {
|
||||
|
||||
/** catch the trivial cases **/
|
||||
if ( p == 0 ) return 1;
|
||||
/** if ( p > (sigma*diameter) ) return 0;
|
||||
^^ unnecessary, gauss is well-behaved
|
||||
outside its radius **/
|
||||
|
||||
/** calculate the rest **/
|
||||
|
||||
ale_pos p2 = p * p;
|
||||
ale_pos sigma2 = sigma * sigma;
|
||||
|
||||
return exp( -(p2/sigma2) );
|
||||
|
||||
}
|
||||
|
||||
/** extend the heavy-lifting function to handle a coordinate **/
|
||||
ale_real _calc(point p) const {
|
||||
|
||||
return _calc( sqrt( (p[0]*p[0]) + (p[1]*p[1]) ) );
|
||||
|
||||
/** doesn't work as well:
|
||||
return _calc( p[0] ) * _calc( p[1] ); **/
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, or how big a radius does this filter
|
||||
* touch?
|
||||
*/
|
||||
ale_pos support() const {
|
||||
return sigma*diameter;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return _calc(p);
|
||||
}
|
||||
|
||||
/** only compare standard deviations, since this version fixes
|
||||
the diameter across all instances **/
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) == typeid(*this))
|
||||
return ((gauss *)f)->sigma == sigma;
|
||||
return 0;
|
||||
}
|
||||
|
||||
gauss(ale_pos sigma) {
|
||||
this->sigma = sigma;
|
||||
this->diameter = 2; /** fixed, standard for imaging **/
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
81
d2/filter/lanczos.h
Normal file
81
d2/filter/lanczos.h
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __lanczos_h__
|
||||
#define __lanczos_h__
|
||||
|
||||
/*
|
||||
* A lanczos filter class.
|
||||
*
|
||||
* Notes on Lanczos and Sinc by Dave Martindale et alia are available here:
|
||||
*
|
||||
* http://www.binbooks.com/books/photo/i/l/57186AF8DE
|
||||
* http://www.binbooks.com/books/photo/i/l/57186AE7E6&orig=1
|
||||
*/
|
||||
|
||||
class lanczos : public filter {
|
||||
private:
|
||||
ale_pos half_width;
|
||||
|
||||
/*
|
||||
* Lanczos function
|
||||
*
|
||||
* The lanczos function is the central lobe of the sinc function.
|
||||
*/
|
||||
ale_real _lanczos(ale_pos p) const {
|
||||
if (fabs(p) >= half_width)
|
||||
return 0;
|
||||
|
||||
return sinc::_sinc(p / half_width);
|
||||
}
|
||||
|
||||
ale_real _lanczos(point p) const {
|
||||
return _lanczos(p[0]) * _lanczos(p[1]);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
ale_pos support() const {
|
||||
return half_width;
|
||||
}
|
||||
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) == typeid(*this))
|
||||
return ((lanczos *)f)->half_width == half_width;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return _lanczos(p);
|
||||
}
|
||||
|
||||
lanczos(double half_width) {
|
||||
this->half_width = half_width;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
75
d2/filter/mult.h
Normal file
75
d2/filter/mult.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __mult_h__
|
||||
#define __mult_h__
|
||||
|
||||
/*
|
||||
* A class for pointwise multiplication of filters.
|
||||
*/
|
||||
|
||||
class mult : public filter {
|
||||
private:
|
||||
ale_pos _support;
|
||||
filter *f1, *f2;
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
virtual ale_pos support() const {
|
||||
return _support;
|
||||
}
|
||||
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) != typeid(*this))
|
||||
return 0;
|
||||
|
||||
const mult *m = (const mult *)f;
|
||||
|
||||
/*
|
||||
* XXX: if we wished, we could recognize commutativity.
|
||||
*/
|
||||
return (m->f1->equals(f1)
|
||||
&& m->f2->equals(f2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return f1->response(p) * f2->response(p);
|
||||
}
|
||||
|
||||
mult(filter *f1, filter *f2) {
|
||||
this->f1 = f1;
|
||||
this->f2 = f2;
|
||||
assert (f1 != NULL);
|
||||
assert (f2 != NULL);
|
||||
|
||||
_support = f1->support();
|
||||
|
||||
if (f2->support() < _support)
|
||||
_support = f2->support();
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
477
d2/filter/scaled_filter.h
Normal file
477
d2/filter/scaled_filter.h
Normal file
@@ -0,0 +1,477 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __scaled_filter_h__
|
||||
#define __scaled_filter_h__
|
||||
|
||||
#include "filter.h"
|
||||
#include "mult.h"
|
||||
#include "sinc.h"
|
||||
#include "triangle.h"
|
||||
#include "box.h"
|
||||
#include "gauss.h"
|
||||
#include "lanczos.h"
|
||||
|
||||
/*
|
||||
* Useful constants.
|
||||
*/
|
||||
|
||||
// static const ale_pos sqrt2 = (ale_pos) 1.41421356237309504880;
|
||||
// static const ale_pos one_over_sqrt2 = (ale_pos) 0.70710678118654752440;
|
||||
|
||||
static const ale_pos sqrt2 = sqrt((ale_pos) 2);
|
||||
static const ale_pos one_over_sqrt2 = 1 / sqrt2;
|
||||
|
||||
/*
|
||||
* Scaled filter class.
|
||||
*/
|
||||
|
||||
class scaled_filter {
|
||||
private:
|
||||
/*
|
||||
* Frequency limit:
|
||||
*
|
||||
* 0: indicates the higher limit (identical to output frequency)
|
||||
*
|
||||
* 1: indicates the safer limit (minimum of input and output
|
||||
* frequencies)
|
||||
*
|
||||
* 2: indicates a limit dynamically derived from subsequent chain
|
||||
* elements.
|
||||
*/
|
||||
int frequency_limit;
|
||||
filter *f;
|
||||
|
||||
/*
|
||||
* filter function parameters
|
||||
*
|
||||
* Parameters include data regarding the current image and
|
||||
* transformation. All parameters are mutable.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A pointer to the current image is stored, as well as the image
|
||||
* offset and bayer type.
|
||||
*/
|
||||
|
||||
mutable const image *im;
|
||||
mutable unsigned int bayer;
|
||||
mutable point offset;
|
||||
|
||||
/* We are either using one transformation or a combination of two
|
||||
* transformations. T_TWO indicates whether two transformations are
|
||||
* being used. T[] stores the transformations. When only one
|
||||
* transformation is used, OFFSET stores the image offset.
|
||||
*/
|
||||
|
||||
mutable unsigned int t_two;
|
||||
mutable transformation t0, t1;
|
||||
mutable int _is_projective;
|
||||
|
||||
/*
|
||||
* Transform a point using the current transformation.
|
||||
*/
|
||||
point transform(point p, const trans_single &ts0, const trans_single &ts1) const {
|
||||
if (t_two)
|
||||
return ts1.unscaled_inverse_transform(ts0.transform_unscaled(p));
|
||||
|
||||
return ts0.transform_unscaled(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inverse of the above.
|
||||
*/
|
||||
point transform_inverse(point p, const trans_single &ts0, const trans_single &ts1) const {
|
||||
if (t_two)
|
||||
return ts0.unscaled_inverse_transform(ts1.transform_unscaled(p));
|
||||
|
||||
return ts0.unscaled_inverse_transform(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero if the transformation might be non-Euclidean.
|
||||
*/
|
||||
int is_projective() const {
|
||||
return _is_projective;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are limiting to source frequencies, then scale a filter to
|
||||
* accept only frequencies we know to be expressible in the source.
|
||||
* (Or do this approximately.)
|
||||
*/
|
||||
void freq_limit(point p, point mapped_p, ale_pos *hscale_g,
|
||||
ale_pos *hscale_rb, ale_pos *wscale_g, ale_pos *wscale_rb,
|
||||
const trans_single &ts0, const trans_single &ts1) const {
|
||||
|
||||
if (frequency_limit == 0)
|
||||
return;
|
||||
|
||||
ale_pos hnorm, wnorm;
|
||||
|
||||
point dh = transform_inverse(p + point(1, 0), ts0, ts1);
|
||||
point dw = transform_inverse(p + point(0, 1), ts0, ts1);
|
||||
|
||||
hnorm = (mapped_p - dh).norm();
|
||||
wnorm = (mapped_p - dw).norm();
|
||||
|
||||
if (bayer == IMAGE_BAYER_NONE) {
|
||||
if (hnorm < 1) {
|
||||
*hscale_g = hnorm;
|
||||
*hscale_rb = hnorm;
|
||||
}
|
||||
if (wnorm < 1) {
|
||||
*wscale_g = wnorm;
|
||||
*wscale_rb = wnorm;
|
||||
}
|
||||
} else {
|
||||
if (hnorm < sqrt2) {
|
||||
*hscale_g = hnorm / sqrt2;
|
||||
*hscale_rb = hnorm / 2;
|
||||
} else if (hnorm < 2) {
|
||||
*hscale_rb = hnorm / 2;
|
||||
}
|
||||
if (wnorm < sqrt2) {
|
||||
*wscale_g = wnorm / sqrt2;
|
||||
*wscale_rb = wnorm / 2;
|
||||
} else if (wnorm < 2) {
|
||||
*wscale_rb = wnorm / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void filter_channel(point p, point mapped_p, unsigned int k, ale_pos hscale,
|
||||
ale_pos wscale, pixel *result, pixel *weight, int honor_exclusion,
|
||||
int frame, ale_real prev_value, ale_real prev_weight,
|
||||
const trans_single &ts0, const trans_single &ts1) const {
|
||||
|
||||
ale_real temp_result = (*result)[k], temp_weight = (*weight)[k];
|
||||
ale_real certainty;
|
||||
|
||||
if (prev_weight > 0)
|
||||
certainty = im->exp().confidence(k, prev_value);
|
||||
else
|
||||
certainty = 1; /* We calculate certainty later */
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* This test matches the technical description.
|
||||
*/
|
||||
if (hscale < 1 && wscale < 1) {
|
||||
#else
|
||||
/*
|
||||
* This approach is ~33% faster for Euclidean transformations,
|
||||
* but is likely to produce different results in some cases.
|
||||
*/
|
||||
if (hscale <= 1 && wscale <= 1) {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle the especially coarse case.
|
||||
*/
|
||||
|
||||
ale_pos fscale;
|
||||
|
||||
if (frequency_limit) {
|
||||
fscale = (bayer == IMAGE_BAYER_NONE)
|
||||
? (ale_pos) 1
|
||||
: (k == 1) ? sqrt2 : (ale_pos) 2;
|
||||
} else {
|
||||
fscale = 1;
|
||||
}
|
||||
|
||||
int min_i, max_i, min_j, max_j;
|
||||
|
||||
ale_pos support = f->support() * fscale;
|
||||
|
||||
if (1 / support == 0) {
|
||||
min_i = 0;
|
||||
max_i = im->height() - 1;
|
||||
min_j = 0;
|
||||
max_j = im->width() - 1;
|
||||
} else {
|
||||
|
||||
point min = mapped_p - point(support, support);
|
||||
point max = mapped_p + point(support, support);
|
||||
|
||||
/*
|
||||
* lrintf() may be faster than ceil/floor() on some architectures.
|
||||
* See render/psf/raster.h for more details.
|
||||
*/
|
||||
|
||||
min_i = (int) lrintf(min[0]);
|
||||
max_i = (int) lrintf(max[0]);
|
||||
min_j = (int) lrintf(min[1]);
|
||||
max_j = (int) lrintf(max[1]);
|
||||
|
||||
if (min_i < 0)
|
||||
min_i = 0;
|
||||
if (max_i > (int) im->height() - 1)
|
||||
max_i = (int) im->height() - 1;
|
||||
if (min_j < 0)
|
||||
min_j = 0;
|
||||
if (max_j > (int) im->width() - 1)
|
||||
max_j = (int) im->width() - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the source pixels.
|
||||
*/
|
||||
|
||||
for (int i = min_i; i <= max_i; i++)
|
||||
for (int j = min_j; j <= max_j; j++) {
|
||||
|
||||
if (honor_exclusion && render::is_excluded_f(i, j, frame))
|
||||
continue;
|
||||
|
||||
if (bayer != IMAGE_BAYER_NONE
|
||||
&& (im->get_channels(i, j) & (1 << k)) == 0)
|
||||
continue;
|
||||
|
||||
point a = point(i, j);
|
||||
|
||||
ale_real v = im->get_chan(i, j, k);
|
||||
|
||||
ale_real response = f->response((a - mapped_p) / fscale);
|
||||
|
||||
ale_real w = certainty * response;
|
||||
|
||||
temp_weight += w;
|
||||
temp_result += w * v;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Establish the boundaries of filtering in the source.
|
||||
*/
|
||||
|
||||
point min = mapped_p;
|
||||
point max = mapped_p;
|
||||
|
||||
int imin[2];
|
||||
int imax[2];
|
||||
|
||||
ale_pos sup = f->support();
|
||||
|
||||
if (1 / sup == 0) {
|
||||
imin[0] = 0;
|
||||
imax[0] = im->height() - 1;
|
||||
imin[1] = 0;
|
||||
imax[1] = im->width() - 1;
|
||||
} else {
|
||||
|
||||
ale_pos hsup = sup / hscale;
|
||||
ale_pos wsup = sup / wscale;
|
||||
|
||||
for (int ii = -1; ii <= +1; ii+=2)
|
||||
for (int jj = -1; jj <= +1; jj+=2) {
|
||||
|
||||
point b = transform_inverse(point(hsup * ii, wsup * jj) + p, ts0, ts1);
|
||||
for (int d = 0; d < 2; d++) {
|
||||
if (b[d] < min[d])
|
||||
min[d] = b[d];
|
||||
if (b[d] > max[d])
|
||||
max[d] = b[d];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* lrintf() may be faster than ceil/floor() on some architectures.
|
||||
* See render/psf/raster.h for more details.
|
||||
*/
|
||||
|
||||
imin[0] = lrintf(min[0]);
|
||||
imax[0] = lrintf(max[0]);
|
||||
imin[1] = lrintf(min[1]);
|
||||
imax[1] = lrintf(max[1]);
|
||||
|
||||
if (imin[0] < 0)
|
||||
imin[0] = 0;
|
||||
if (imax[0] > (int) im->height() - 1)
|
||||
imax[0] = (int) im->height() - 1;
|
||||
if (imin[1] < 0)
|
||||
imin[1] = 0;
|
||||
if (imax[1] > (int) im->width() - 1)
|
||||
imax[1] = (int) im->width() - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the source pixels.
|
||||
*/
|
||||
|
||||
for (int i = imin[0]; i <= imax[0]; i++)
|
||||
for (int j = imin[1]; j <= imax[1]; j++) {
|
||||
|
||||
if (honor_exclusion && render::is_excluded_f(i, j, frame))
|
||||
continue;
|
||||
|
||||
if (bayer != IMAGE_BAYER_NONE
|
||||
&& (im->get_channels(i, j) & (1 << k)) == 0)
|
||||
continue;
|
||||
|
||||
point a = transform(point(i, j), ts0, ts1);
|
||||
|
||||
ale_real v = im->get_chan(i, j, k);
|
||||
|
||||
ale_real response = f->response((a - p) * point(hscale, wscale));
|
||||
|
||||
ale_real w = certainty * response;
|
||||
|
||||
temp_weight += w;
|
||||
temp_result += w * v;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(prev_weight > 0)
|
||||
&& d2::exposure::get_confidence() != 0
|
||||
&& temp_weight > 0) {
|
||||
|
||||
/*
|
||||
* Calculate certainty for the first pass.
|
||||
*/
|
||||
|
||||
certainty = im->exp().confidence(k, temp_result / temp_weight);
|
||||
temp_weight *= certainty;
|
||||
temp_result *= certainty;
|
||||
}
|
||||
|
||||
(*result)[k] = temp_result;
|
||||
(*weight)[k] = temp_weight;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
scaled_filter(filter *f, int frequency_limit) :
|
||||
t0(transformation::eu_identity()),
|
||||
t1(transformation::eu_identity()) {
|
||||
|
||||
this->frequency_limit = frequency_limit;
|
||||
this->f = f;
|
||||
}
|
||||
|
||||
const filter *get_filter() const {
|
||||
return f;
|
||||
}
|
||||
|
||||
int equals(scaled_filter *s) {
|
||||
return (frequency_limit == s->frequency_limit
|
||||
&& f->equals(s->f));
|
||||
}
|
||||
|
||||
int is_coarse() const {
|
||||
return frequency_limit == 1;
|
||||
}
|
||||
|
||||
int is_fine() const {
|
||||
return frequency_limit == 0;
|
||||
}
|
||||
|
||||
int is_dynamic() const {
|
||||
return frequency_limit == 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the transformation T and image IM.
|
||||
*/
|
||||
void set_parameters(transformation _t, const image *_im, point _offset) const {
|
||||
t_two = 0;
|
||||
t0 = _t;
|
||||
im = _im;
|
||||
|
||||
bayer = im->get_bayer();
|
||||
offset = _offset;
|
||||
|
||||
_is_projective = _t.is_projective();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the transformations T and S, and image IM.
|
||||
*/
|
||||
void set_parameters(transformation _t, transformation _s, const image *_im) const {
|
||||
t_two = 1;
|
||||
t0 = _t;
|
||||
t1 = _s;
|
||||
im = _im;
|
||||
|
||||
bayer = im->get_bayer();
|
||||
offset = point(0, 0);
|
||||
|
||||
_is_projective = t0.is_projective() || t1.is_projective();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return filtered RESULT and WEIGHT at point P in a coordinate system
|
||||
* specified by the inverse of transformation T based on data taken
|
||||
* from image IM.
|
||||
*/
|
||||
void filtered(int i, int j, pixel *result, pixel *weight,
|
||||
int honor_exclusion, int frame,
|
||||
pixel prev_value = pixel(0, 0, 0),
|
||||
pixel prev_weight = pixel(0, 0, 0)) const {
|
||||
|
||||
trans_single ts0, ts1;
|
||||
pixel tm;
|
||||
|
||||
point p = point(i, j) + offset;
|
||||
|
||||
*result = pixel(0, 0, 0);
|
||||
*weight = pixel(0, 0, 0);
|
||||
|
||||
ale_pos hscale_g = 1;
|
||||
ale_pos hscale_rb = 1;
|
||||
ale_pos wscale_g = 1;
|
||||
ale_pos wscale_rb = 1;
|
||||
|
||||
if (t_two) {
|
||||
ts1 = t1.t_at_point(p);
|
||||
ts0 = t0.t_at_inv_point(ts1.transform_unscaled(p));
|
||||
tm = ts0.get_tonal_multiplier(point(0, 0)) / ts1.get_tonal_multiplier(point(0, 0));
|
||||
} else {
|
||||
ts0 = t0.t_at_inv_point(p);
|
||||
tm = ts0.get_tonal_multiplier(point(0, 0));
|
||||
}
|
||||
|
||||
prev_value /= tm;
|
||||
|
||||
point mapped_p = transform_inverse(p, ts0, ts1);
|
||||
|
||||
/*
|
||||
* Allowing points such as these results in problems that are
|
||||
* annoying to resolve. Solving such problems is not obviously
|
||||
* worth the effort, given that they can be avoided entirely by
|
||||
* disallowing the points.
|
||||
*/
|
||||
|
||||
if (mapped_p[0] < 0 || mapped_p[0] > im->height() - 1
|
||||
|| mapped_p[1] < 0 || mapped_p[1] > im->width() - 1)
|
||||
return;
|
||||
|
||||
freq_limit(p, mapped_p, &hscale_g, &hscale_rb, &wscale_g, &wscale_rb, ts0, ts1);
|
||||
|
||||
filter_channel(p, mapped_p, 0, hscale_rb, wscale_rb, result, weight, honor_exclusion, frame, prev_value[0], prev_weight[0], ts0, ts1);
|
||||
filter_channel(p, mapped_p, 2, hscale_rb, hscale_rb, result, weight, honor_exclusion, frame, prev_value[2], prev_weight[2], ts0, ts1);
|
||||
filter_channel(p, mapped_p, 1, hscale_g , hscale_g , result, weight, honor_exclusion, frame, prev_value[1], prev_weight[1], ts0, ts1);
|
||||
|
||||
(*result) *= tm;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
76
d2/filter/sinc.h
Normal file
76
d2/filter/sinc.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __sinc_h__
|
||||
#define __sinc_h__
|
||||
|
||||
/*
|
||||
* A filtering class for the sinc function.
|
||||
*
|
||||
* Notes on Lanczos and Sinc by Dave Martindale et alia are available here:
|
||||
*
|
||||
* http://www.binbooks.com/books/photo/i/l/57186AF8DE
|
||||
* http://www.binbooks.com/books/photo/i/l/57186AE7E6&orig=1
|
||||
*/
|
||||
|
||||
class sinc : public filter {
|
||||
public:
|
||||
|
||||
/*
|
||||
* Sinc filter.
|
||||
*
|
||||
* Width is infinite.
|
||||
*/
|
||||
static double _sinc(ale_pos p) {
|
||||
if (fabs(p) < 0.001)
|
||||
return 1;
|
||||
return sin(M_PI * p) / (M_PI * p);
|
||||
}
|
||||
|
||||
static double _sinc(point p) {
|
||||
return _sinc(p[0]) * _sinc(p[1]);
|
||||
}
|
||||
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) == typeid(*this))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
virtual ale_pos support() const {
|
||||
double zero = 0;
|
||||
double infinity = 1 / zero;
|
||||
assert (!isnan(infinity));
|
||||
assert (1 < infinity);
|
||||
return (ale_pos) infinity;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return _sinc(p);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
98
d2/filter/ssfe.h
Normal file
98
d2/filter/ssfe.h
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ssfe_h__
|
||||
#define __ssfe_h__
|
||||
|
||||
#include "scaled_filter.h"
|
||||
#include "filter.h"
|
||||
|
||||
/*
|
||||
* Scaled filter class with exclusion.
|
||||
*/
|
||||
|
||||
class ssfe {
|
||||
private:
|
||||
/*
|
||||
* Honor exclusion?
|
||||
*/
|
||||
int honor_exclusion;
|
||||
scaled_filter *f;
|
||||
mutable point _offset;
|
||||
mutable int have_offset;
|
||||
|
||||
public:
|
||||
|
||||
ssfe(scaled_filter *f, int honor_exclusion) {
|
||||
this->honor_exclusion = honor_exclusion;
|
||||
this->f = f;
|
||||
}
|
||||
|
||||
const scaled_filter *get_scaled_filter() const {
|
||||
return f;
|
||||
}
|
||||
|
||||
int equals(const ssfe *s) {
|
||||
return (honor_exclusion == s->honor_exclusion
|
||||
&& f->equals(s->f));
|
||||
}
|
||||
|
||||
int ex_is_honored() const {
|
||||
return honor_exclusion;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the parameters for filtering.
|
||||
*/
|
||||
void set_parameters(transformation t, const image *im, point offset) const {
|
||||
have_offset = 1;
|
||||
_offset = offset;
|
||||
f->set_parameters(t, im, offset);
|
||||
}
|
||||
void set_parameters(transformation t, transformation s, const image *im) const {
|
||||
have_offset = 0;
|
||||
f->set_parameters(t, s, im);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return filtered RESULT and WEIGHT at point P in a coordinate system
|
||||
* specified by the inverse of transformation T based on data taken
|
||||
* from image IM.
|
||||
*/
|
||||
void filtered(int i, int j, int frame, pixel *result,
|
||||
pixel *weight, pixel prev_value = pixel(0, 0, 0), pixel prev_weight = pixel(0, 0, 0)) const {
|
||||
|
||||
/*
|
||||
* We need a valid offset in order to determine exclusion
|
||||
* regions.
|
||||
*/
|
||||
|
||||
assert (have_offset || !honor_exclusion);
|
||||
|
||||
*result = pixel(0, 0, 0);
|
||||
*weight = pixel(0, 0, 0);
|
||||
|
||||
if (honor_exclusion && render::is_excluded_r(_offset, i, j, frame))
|
||||
return;
|
||||
|
||||
f->filtered(i, j, result, weight, honor_exclusion, frame, prev_value, prev_weight);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
76
d2/filter/triangle.h
Normal file
76
d2/filter/triangle.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __triangle_h__
|
||||
#define __triangle_h__
|
||||
|
||||
/*
|
||||
* A triangle filter class.
|
||||
*/
|
||||
|
||||
class triangle : public filter {
|
||||
private:
|
||||
ale_pos half_width;
|
||||
|
||||
/*
|
||||
* Triangle filter.
|
||||
*/
|
||||
ale_real _triangle(ale_pos p) const {
|
||||
ale_pos fabs_p = fabs(p);
|
||||
|
||||
if (fabs_p >= half_width)
|
||||
return 0;
|
||||
|
||||
return (1 - fabs_p / half_width);
|
||||
}
|
||||
|
||||
ale_real _triangle(point p) const {
|
||||
return _triangle(p[0]) * _triangle(p[1]);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
virtual ale_pos support() const {
|
||||
return half_width;
|
||||
}
|
||||
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) == typeid(*this))
|
||||
return ((triangle *)f)->half_width == half_width;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return _triangle(p);
|
||||
}
|
||||
|
||||
triangle(ale_pos half_width) {
|
||||
this->half_width = half_width;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
52
d2/filter/zero.h
Normal file
52
d2/filter/zero.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
|
||||
// <dhilvert@ugcs.caltech.edu>
|
||||
|
||||
/* This file is part of the Anti-Lamenessing Engine.
|
||||
|
||||
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Anti-Lamenessing Engine; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __zero_h__
|
||||
#define __zero_h__
|
||||
|
||||
/*
|
||||
* A zero filter.
|
||||
*/
|
||||
|
||||
class zero : public filter {
|
||||
public:
|
||||
|
||||
/*
|
||||
* Size of filter support, in number of half-cycles to each side of the
|
||||
* filter center.
|
||||
*/
|
||||
ale_pos support() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int equals(const filter *f) const {
|
||||
if (typeid(*f) == typeid(*this))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response of filter at point p
|
||||
*/
|
||||
virtual ale_real response(point p) const {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user