/************************************************************************/
/* */
/* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */
/* This file is part of the VIGRA computer vision library. */
/* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */
/* Please direct questions, bug reports, and contributions to */
/* koethe@informatik.uni-hamburg.de or */
/* vigra@kogs1.informatik.uni-hamburg.de */
/* */
/* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */
/* Software is furnished to do so, subject to the following */
/* conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the */
/* Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */
/* */
/************************************************************************/
#ifndef VIGRA_SPLINEIMAGEVIEW_HXX
#define VIGRA_SPLINEIMAGEVIEW_HXX
#include "vigra/mathutil.hxx"
#include "vigra/recursiveconvolution.hxx"
#include "vigra/splines.hxx"
#include "vigra/array_vector.hxx"
#include "vigra/basicimage.hxx"
#include "vigra/copyimage.hxx"
#include "vigra/tinyvector.hxx"
#include "vigra/fixedpoint.hxx"
#include "vigra/multi_array.hxx"
namespace vigra {
/********************************************************/
/* */
/* SplineImageView */
/* */
/********************************************************/
/** \brief Create a continuous view onto a discrete image using splines.
This class is very useful if image values or derivatives at arbitrary
real-valued coordinates are needed. Access at such coordinates is implemented by
interpolating the given discrete image values with a spline of the
specified ORDER. Continuous derivatives are available up to
degree ORDER-1. If the requested coordinates are near the image border,
reflective boundary conditions are applied. In principle, this class can also be used
for image resizing, but here the functions from the resize... family are
more efficient.
The SplineImageView template is explicitly specialized to make it as efficient as possible.
In particular, unnecessary copying of the image is avoided when the iterators passed
in the constructor originate from a \ref vigra::BasicImage. In addition, these specializations
provide function unchecked(...) that do not perform bounds checking. If the original image
is not a variant of \ref vigra::BasicImage, one can customize the internal representation by
using \ref vigra::SplineImageview0 or \ref vigra::SplineImageview1.
Usage:
\#include "vigra/splineimageview.hxx"
Namespace: vigra
\code
BImage img(w,h);
... // fill img
// construct spline view for quadratic interpolation
SplineImageView<2, double> spi2(img);
double x = ..., y = ...;
double v2 = spi2(x, y);
// construct spline view for linear interpolation
SplineImageView<1, UInt32> spi1(img);
UInt32 v1 = spi1(x, y);
FixedPoint<16, 15> fx(...), fy(...);
UInt32 vf = spi1.unchecked(fx, fy);
\endcode
*/
template
class SplineImageView
{
typedef typename NumericTraits::RealPromote InternalValue;
public:
/** The view's value type (return type of access and derivative functions).
*/
typedef VALUETYPE value_type;
/** The view's size type.
*/
typedef Size2D size_type;
/** The view's difference type.
*/
typedef TinyVector difference_type;
/** The order of the spline used.
*/
enum StaticOrder { order = ORDER };
/** The type of the internal image holding the spline coefficients.
*/
typedef BasicImage InternalImage;
private:
typedef typename InternalImage::traverser InternalTraverser;
typedef typename InternalTraverser::row_iterator InternalRowIterator;
typedef typename InternalTraverser::column_iterator InternalColumnIterator;
typedef BSpline Spline;
enum { ksize_ = ORDER + 1, kcenter_ = ORDER / 2 };
public:
/** Construct SplineImageView for the given image.
If skipPrefiltering = true (default: false), the recursive
prefilter of the cardinal spline function is not applied, resulting
in an approximating (smoothing) rather than interpolating spline. This is
especially useful if customized prefilters are to be applied.
*/
template
SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool skipPrefiltering = false)
: w_(iend.x - is.x), h_(iend.y - is.y), w1_(w_-1), h1_(h_-1),
x0_(kcenter_), x1_(w_ - kcenter_ - 2), y0_(kcenter_), y1_(h_ - kcenter_ - 2),
image_(w_, h_),
x_(-1.0), y_(-1.0),
u_(-1.0), v_(-1.0)
{
copyImage(srcIterRange(is, iend, sa), destImage(image_));
if(!skipPrefiltering)
init();
}
/** Construct SplineImageView for the given image.
If skipPrefiltering = true (default: false), the recursive
prefilter of the cardinal spline function is not applied, resulting
in an approximating (smoothing) rather than interpolating spline. This is
especially useful if customized prefilters are to be applied.
*/
template
SplineImageView(triple s, bool skipPrefiltering = false)
: w_(s.second.x - s.first.x), h_(s.second.y - s.first.y), w1_(w_-1), h1_(h_-1),
x0_(kcenter_), x1_(w_ - kcenter_ - 2), y0_(kcenter_), y1_(h_ - kcenter_ - 2),
image_(w_, h_),
x_(-1.0), y_(-1.0),
u_(-1.0), v_(-1.0)
{
copyImage(srcIterRange(s.first, s.second, s.third), destImage(image_));
if(!skipPrefiltering)
init();
}
/** Access interpolated function at real-valued coordinate (x, y).
If (x, y) is near the image border or outside the image, the value
is calculated with reflective boundary conditions. An exception is thrown if the
coordinate is outside the first reflection.
*/
value_type operator()(double x, double y) const;
/** Access derivative of order (dx, dy) at real-valued coordinate (x, y).
If (x, y) is near the image border or outside the image, the value
is calculated with reflective boundary conditions. An exception is thrown if the
coordinate is outside the first reflection.
*/
value_type operator()(double x, double y, unsigned int dx, unsigned int dy) const;
/** Access 1st derivative in x-direction at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 1, 0).
*/
value_type dx(double x, double y) const
{ return operator()(x, y, 1, 0); }
/** Access 1st derivative in y-direction at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 0, 1).
*/
value_type dy(double x, double y) const
{ return operator()(x, y, 0, 1); }
/** Access 2nd derivative in x-direction at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 2, 0).
*/
value_type dxx(double x, double y) const
{ return operator()(x, y, 2, 0); }
/** Access mixed 2nd derivative at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 1, 1).
*/
value_type dxy(double x, double y) const
{ return operator()(x, y, 1, 1); }
/** Access 2nd derivative in y-direction at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 0, 2).
*/
value_type dyy(double x, double y) const
{ return operator()(x, y, 0, 2); }
/** Access 3rd derivative in x-direction at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 3, 0).
*/
value_type dx3(double x, double y) const
{ return operator()(x, y, 3, 0); }
/** Access 3rd derivative in y-direction at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 0, 3).
*/
value_type dy3(double x, double y) const
{ return operator()(x, y, 0, 3); }
/** Access mixed 3rd derivative dxxy at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 2, 1).
*/
value_type dxxy(double x, double y) const
{ return operator()(x, y, 2, 1); }
/** Access mixed 3rd derivative dxyy at real-valued coordinate (x, y).
Equivalent to splineView(x, y, 1, 2).
*/
value_type dxyy(double x, double y) const
{ return operator()(x, y, 1, 2); }
/** Access interpolated function at real-valued coordinate d.
Equivalent to splineView(d[0], d[1]).
*/
value_type operator()(difference_type const & d) const
{ return operator()(d[0], d[1]); }
/** Access derivative of order (dx, dy) at real-valued coordinate d.
Equivalent to splineView(d[0], d[1], dx, dy).
*/
value_type operator()(difference_type const & d, unsigned int dx, unsigned int dy) const
{ return operator()(d[0], d[1], dx, dy); }
/** Access 1st derivative in x-direction at real-valued coordinate d.
Equivalent to splineView.dx(d[0], d[1]).
*/
value_type dx(difference_type const & d) const
{ return dx(d[0], d[1]); }
/** Access 1st derivative in y-direction at real-valued coordinate d.
Equivalent to splineView.dy(d[0], d[1]).
*/
value_type dy(difference_type const & d) const
{ return dy(d[0], d[1]); }
/** Access 2nd derivative in x-direction at real-valued coordinate d.
Equivalent to splineView.dxx(d[0], d[1]).
*/
value_type dxx(difference_type const & d) const
{ return dxx(d[0], d[1]); }
/** Access mixed 2nd derivative at real-valued coordinate d.
Equivalent to splineView.dxy(d[0], d[1]).
*/
value_type dxy(difference_type const & d) const
{ return dxy(d[0], d[1]); }
/** Access 2nd derivative in y-direction at real-valued coordinate d.
Equivalent to splineView.dyy(d[0], d[1]).
*/
value_type dyy(difference_type const & d) const
{ return dyy(d[0], d[1]); }
/** Access 3rd derivative in x-direction at real-valued coordinate d.
Equivalent to splineView.dx3(d[0], d[1]).
*/
value_type dx3(difference_type const & d) const
{ return dx3(d[0], d[1]); }
/** Access 3rd derivative in y-direction at real-valued coordinate d.
Equivalent to splineView.dy3(d[0], d[1]).
*/
value_type dy3(difference_type const & d) const
{ return dy3(d[0], d[1]); }
/** Access mixed 3rd derivative dxxy at real-valued coordinate d.
Equivalent to splineView.dxxy(d[0], d[1]).
*/
value_type dxxy(difference_type const & d) const
{ return dxxy(d[0], d[1]); }
/** Access mixed 3rd derivative dxyy at real-valued coordinate d.
Equivalent to splineView.dxyy(d[0], d[1]).
*/
value_type dxyy(difference_type const & d) const
{ return dxyy(d[0], d[1]); }
/** Access gradient squared magnitude at real-valued coordinate (x, y).
*/
value_type g2(double x, double y) const;
/** Access 1st derivative in x-direction of gradient squared magnitude
at real-valued coordinate (x, y).
*/
value_type g2x(double x, double y) const;
/** Access 1st derivative in y-direction of gradient squared magnitude
at real-valued coordinate (x, y).
*/
value_type g2y(double x, double y) const;
/** Access 2nd derivative in x-direction of gradient squared magnitude
at real-valued coordinate (x, y).
*/
value_type g2xx(double x, double y) const;
/** Access mixed 2nd derivative of gradient squared magnitude
at real-valued coordinate (x, y).
*/
value_type g2xy(double x, double y) const;
/** Access 2nd derivative in y-direction of gradient squared magnitude
at real-valued coordinate (x, y).
*/
value_type g2yy(double x, double y) const;
/** Access gradient squared magnitude at real-valued coordinate d.
*/
value_type g2(difference_type const & d) const
{ return g2(d[0], d[1]); }
/** Access 1st derivative in x-direction of gradient squared magnitude
at real-valued coordinate d.
*/
value_type g2x(difference_type const & d) const
{ return g2x(d[0], d[1]); }
/** Access 1st derivative in y-direction of gradient squared magnitude
at real-valued coordinate d.
*/
value_type g2y(difference_type const & d) const
{ return g2y(d[0], d[1]); }
/** Access 2nd derivative in x-direction of gradient squared magnitude
at real-valued coordinate d.
*/
value_type g2xx(difference_type const & d) const
{ return g2xx(d[0], d[1]); }
/** Access mixed 2nd derivative of gradient squared magnitude
at real-valued coordinate d.
*/
value_type g2xy(difference_type const & d) const
{ return g2xy(d[0], d[1]); }
/** Access 2nd derivative in y-direction of gradient squared magnitude
at real-valued coordinate d.
*/
value_type g2yy(difference_type const & d) const
{ return g2yy(d[0], d[1]); }
/** The width of the image.
0 <= x <= width()-1 is required for all access functions.
*/
unsigned int width() const
{ return w_; }
/** The height of the image.
0 <= y <= height()-1 is required for all access functions.
*/
unsigned int height() const
{ return h_; }
/** The size of the image.
0 <= x <= size().x-1 and 0 <= y <= size().y-1
are required for all access functions.
*/
size_type size() const
{ return size_type(w_, h_); }
/** The internal image holding the spline coefficients.
*/
InternalImage const & image() const
{
return image_;
}
/** Get the array of polynomial coefficients for the facet containing
the point (x, y). The array res will be resized to
dimension (ORDER+1)x(ORDER+1). From these coefficients, the
value of the interpolated function can be calculated by the following
algorithm
\code
SplineImageView view(...);
double x = ..., y = ...;
double dx, dy;
// calculate the local facet coordinates of x and y
if(ORDER % 2)
{
// odd order => facet coordinates between 0 and 1
dx = x - floor(x);
dy = y - floor(y);
}
else
{
// even order => facet coordinates between -0.5 and 0.5
dx = x - floor(x + 0.5);
dy = y - floor(y + 0.5);
}
BasicImage coefficients;
view.coefficientArray(x, y, coefficients);
float f_x_y = 0.0;
for(int ny = 0; ny < ORDER + 1; ++ny)
for(int nx = 0; nx < ORDER + 1; ++nx)
f_x_y += pow(dx, nx) * pow(dy, ny) * coefficients(nx, ny);
assert(abs(f_x_y - view(x, y)) < 1e-6);
\endcode
*/
template
void coefficientArray(double x, double y, Array & res) const;
/** Check if x is in the original image range.
Equivalent to 0 <= x <= width()-1.
*/
bool isInsideX(double x) const
{
return x >= 0.0 && x <= width()-1.0;
}
/** Check if y is in the original image range.
Equivalent to 0 <= y <= height()-1.
*/
bool isInsideY(double y) const
{
return y >= 0.0 && y <= height()-1.0;
}
/** Check if x and y are in the original image range.
Equivalent to 0 <= x <= width()-1 and 0 <= y <= height()-1.
*/
bool isInside(double x, double y) const
{
return isInsideX(x) && isInsideY(y);
}
/** Check if x and y are in the valid range. Points outside the original image range are computed
by reflcective boundary conditions, but only within the first reflection.
Equivalent to -width() + ORDER/2 + 2 < x < 2*width() - ORDER/2 - 2 and
-height() + ORDER/2 + 2 < y < 2*height() - ORDER/2 - 2.
*/
bool isValid(double x, double y) const
{
return x < w1_ + x1_ && x > -x1_ && y < h1_ + y1_ && y > -y1_;
}
/** Check whether the points (x0, y0) and (x1, y1) are in
the same spline facet. For odd order splines, facets span the range
(floor(x), floor(x)+1) x (floor(y), floor(y)+1) (i.e. we have
integer facet borders), whereas even order splines have facet between
half integer values
(floor(x)-0.5, floor(x)+0.5) x (floor(y)-0.5, floor(y)+0.5).
*/
bool sameFacet(double x0, double y0, double x1, double y1) const
{
x0 = VIGRA_CSTD::floor((ORDER % 2) ? x0 : x0 + 0.5);
y0 = VIGRA_CSTD::floor((ORDER % 2) ? y0 : y0 + 0.5);
x1 = VIGRA_CSTD::floor((ORDER % 2) ? x1 : x1 + 0.5);
y1 = VIGRA_CSTD::floor((ORDER % 2) ? y1 : y1 + 0.5);
return x0 == x1 && y0 == y1;
}
protected:
void init();
void calculateIndices(double x, double y) const;
void coefficients(double t, double * const & c) const;
void derivCoefficients(double t, unsigned int d, double * const & c) const;
value_type convolve() const;
unsigned int w_, h_;
int w1_, h1_;
double x0_, x1_, y0_, y1_;
InternalImage image_;
Spline k_;
mutable double x_, y_, u_, v_, kx_[ksize_], ky_[ksize_];
mutable int ix_[ksize_], iy_[ksize_];
};
template
void SplineImageView::init()
{
ArrayVector const & b = k_.prefilterCoefficients();
for(unsigned int i=0; i
struct SplineImageViewUnrollLoop1
{
template
static void exec(int c0, Array c)
{
SplineImageViewUnrollLoop1::exec(c0, c);
c[i] = c0 + i;
}
};
template <>
struct SplineImageViewUnrollLoop1<0>
{
template
static void exec(int c0, Array c)
{
c[0] = c0;
}
};
template
struct SplineImageViewUnrollLoop2
{
template
static ValueType
exec(Array1 k, RowIterator r, Array2 x)
{
return k[i] * r[x[i]] + SplineImageViewUnrollLoop2::exec(k, r, x);
}
};
template
struct SplineImageViewUnrollLoop2<0, ValueType>
{
template
static ValueType
exec(Array1 k, RowIterator r, Array2 x)
{
return k[0] * r[x[0]];
}
};
} // namespace detail
template
void
SplineImageView::calculateIndices(double x, double y) const
{
if(x == x_ && y == y_)
return; // still in cache
if(x > x0_ && x < x1_ && y > y0_ && y < y1_)
{
detail::SplineImageViewUnrollLoop1::exec(
(ORDER % 2) ? int(x - kcenter_) : int(x + 0.5 - kcenter_), ix_);
detail::SplineImageViewUnrollLoop1::exec(
(ORDER % 2) ? int(y - kcenter_) : int(y + 0.5 - kcenter_), iy_);
u_ = x - ix_[kcenter_];
v_ = y - iy_[kcenter_];
}
else
{
vigra_precondition(isValid(x,y),
"SplineImageView::calculateIndices(): coordinates out of range.");
int xCenter = (ORDER % 2) ?
(int)VIGRA_CSTD::floor(x) :
(int)VIGRA_CSTD::floor(x + 0.5);
int yCenter = (ORDER % 2) ?
(int)VIGRA_CSTD::floor(y) :
(int)VIGRA_CSTD::floor(y + 0.5);
if(x >= x1_)
{
for(int i = 0; i < ksize_; ++i)
ix_[i] = w1_ - vigra::abs(w1_ - xCenter - (i - kcenter_));
}
else
{
for(int i = 0; i < ksize_; ++i)
ix_[i] = vigra::abs(xCenter - (kcenter_ - i));
}
if(y >= y1_)
{
for(int i = 0; i < ksize_; ++i)
iy_[i] = h1_ - vigra::abs(h1_ - yCenter - (i - kcenter_));
}
else
{
for(int i = 0; i < ksize_; ++i)
iy_[i] = vigra::abs(yCenter - (kcenter_ - i));
}
u_ = x - xCenter;
v_ = y - yCenter;
}
x_ = x;
y_ = y;
}
template
void SplineImageView::coefficients(double t, double * const & c) const
{
t += kcenter_;
for(int i = 0; i
void SplineImageView::derivCoefficients(double t,
unsigned int d, double * const & c) const
{
t += kcenter_;
for(int i = 0; i
VALUETYPE SplineImageView::convolve() const
{
InternalValue sum;
sum = ky_[0]*detail::SplineImageViewUnrollLoop2::exec(kx_, image_.rowBegin(iy_[0]), ix_);
for(int j=1; j::exec(kx_, image_.rowBegin(iy_[j]), ix_);
}
return NumericTraits::fromRealPromote(sum);
}
template
template
void
SplineImageView::coefficientArray(double x, double y, Array & res) const
{
typename Spline::WeightMatrix & weights = Spline::weights();
InternalValue tmp[ksize_][ksize_];
calculateIndices(x, y);
for(int j=0; j
VALUETYPE SplineImageView::operator()(double x, double y) const
{
calculateIndices(x, y);
coefficients(u_, kx_);
coefficients(v_, ky_);
return convolve();
}
template
VALUETYPE SplineImageView::operator()(double x, double y,
unsigned int dx, unsigned int dy) const
{
calculateIndices(x, y);
derivCoefficients(u_, dx, kx_);
derivCoefficients(v_, dy, ky_);
return convolve();
}
template
VALUETYPE SplineImageView::g2(double x, double y) const
{
return sq(dx(x,y)) + sq(dy(x,y));
}
template
VALUETYPE SplineImageView::g2x(double x, double y) const
{
return 2.0*(dx(x,y) * dxx(x,y) + dy(x,y) * dxy(x,y));
}
template
VALUETYPE SplineImageView::g2y(double x, double y) const
{
return 2.0*(dx(x,y) * dxy(x,y) + dy(x,y) * dyy(x,y));
}
template
VALUETYPE SplineImageView::g2xx(double x, double y) const
{
return 2.0*(sq(dxx(x,y)) + dx(x,y) * dx3(x,y) + sq(dxy(x,y)) + dy(x,y) * dxxy(x,y));
}
template
VALUETYPE SplineImageView::g2yy(double x, double y) const
{
return 2.0*(sq(dxy(x,y)) + dx(x,y) * dxyy(x,y) + sq(dyy(x,y)) + dy(x,y) * dy3(x,y));
}
template
VALUETYPE SplineImageView::g2xy(double x, double y) const
{
return 2.0*(dx(x,y) * dxxy(x,y) + dy(x,y) * dxyy(x,y) + dxy(x,y) * (dxx(x,y) + dyy(x,y)));
}
/********************************************************/
/* */
/* SplineImageView0 */
/* */
/********************************************************/
template
class SplineImageView0Base
{
typedef typename INTERNAL_INDEXER::value_type InternalValue;
public:
typedef VALUETYPE value_type;
typedef Size2D size_type;
typedef TinyVector difference_type;
enum StaticOrder { order = 0 };
public:
SplineImageView0Base(unsigned int w, unsigned int h)
: w_(w), h_(h)
{}
SplineImageView0Base(int w, int h, INTERNAL_INDEXER i)
: w_(w), h_(h), internalIndexer_(i)
{}
template
value_type unchecked(FixedPoint x,
FixedPoint y) const
{
return internalIndexer_(round(x), round(y));
}
template
value_type unchecked(FixedPoint x,
FixedPoint y,
unsigned int dx, unsigned int dy) const
{
if((dx != 0) || (dy != 0))
return NumericTraits::zero();
return unchecked(x, y);
}
value_type unchecked(double x, double y) const
{
return internalIndexer_((int)(x + 0.5), (int)(y + 0.5));
}
value_type unchecked(double x, double y, unsigned int dx, unsigned int dy) const
{
if((dx != 0) || (dy != 0))
return NumericTraits::zero();
return unchecked(x, y);
}
value_type operator()(double x, double y) const
{
int ix, iy;
if(x < 0.0)
{
ix = (int)(-x + 0.5);
vigra_precondition(ix <= (int)w_ - 1,
"SplineImageView::operator(): coordinates out of range.");
}
else
{
ix = (int)(x + 0.5);
if(ix >= (int)w_)
{
ix = 2*w_-2-ix;
vigra_precondition(ix >= 0,
"SplineImageView::operator(): coordinates out of range.");
}
}
if(y < 0.0)
{
iy = (int)(-y + 0.5);
vigra_precondition(iy <= (int)h_ - 1,
"SplineImageView::operator(): coordinates out of range.");
}
else
{
iy = (int)(y + 0.5);
if(iy >= (int)h_)
{
iy = 2*h_-2-iy;
vigra_precondition(iy >= 0,
"SplineImageView::operator(): coordinates out of range.");
}
}
return internalIndexer_(ix, iy);
}
value_type operator()(double x, double y, unsigned int dx, unsigned int dy) const
{
if((dx != 0) || (dy != 0))
return NumericTraits::zero();
return operator()(x, y);
}
value_type dx(double x, double y) const
{ return NumericTraits::zero(); }
value_type dy(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxx(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxy(double x, double y) const
{ return NumericTraits::zero(); }
value_type dyy(double x, double y) const
{ return NumericTraits::zero(); }
value_type dx3(double x, double y) const
{ return NumericTraits::zero(); }
value_type dy3(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxxy(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxyy(double x, double y) const
{ return NumericTraits::zero(); }
value_type operator()(difference_type const & d) const
{ return operator()(d[0], d[1]); }
value_type operator()(difference_type const & d, unsigned int dx, unsigned int dy) const
{ return operator()(d[0], d[1], dx, dy); }
value_type dx(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxx(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dyy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dx3(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dy3(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxxy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxyy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2x(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2y(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2xx(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2xy(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2yy(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2x(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2y(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2xx(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2xy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2yy(difference_type const & d) const
{ return NumericTraits::zero(); }
unsigned int width() const
{ return w_; }
unsigned int height() const
{ return h_; }
size_type size() const
{ return size_type(w_, h_); }
template
void coefficientArray(double x, double y, Array & res) const
{
res.resize(1, 1);
res(0, 0) = operator()(x,y);
}
bool isInsideX(double x) const
{
return x >= 0.0 && x <= width() - 1.0;
}
bool isInsideY(double y) const
{
return y >= 0.0 && y <= height() - 1.0;
}
bool isInside(double x, double y) const
{
return isInsideX(x) && isInsideY(y);
}
bool isValid(double x, double y) const
{
return x < 2.0*w_-2.0 && x > -w_+1.0 && y < 2.0*h_-2.0 && y > -h_+1.0;
}
bool sameFacet(double x0, double y0, double x1, double y1) const
{
x0 = VIGRA_CSTD::floor(x0 + 0.5);
y0 = VIGRA_CSTD::floor(y0 + 0.5);
x1 = VIGRA_CSTD::floor(x1 + 0.5);
y1 = VIGRA_CSTD::floor(y1 + 0.5);
return x0 == x1 && y0 == y1;
}
protected:
unsigned int w_, h_;
INTERNAL_INDEXER internalIndexer_;
};
/** \brief Create an image view for nearest-neighbor interpolation.
This class behaves like \ref vigra::SplineImageView<0, ...>, but one can pass
an additional template argument that determined the internal representation of the image.
If this is equal to the argument type passed in the constructor, the image is not copied.
By default, this works for \ref vigra::BasicImage, \ref vigra::BasicImageView,
\ref vigra::MultiArray<2, ...>, and \ref vigra::MultiArrayView<2, ...>.
*/
template ::const_traverser>
class SplineImageView0
: public SplineImageView0Base
{
typedef SplineImageView0Base Base;
public:
typedef typename Base::value_type value_type;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order };
typedef BasicImage InternalImage;
protected:
typedef typename IteratorTraits::mutable_iterator InternalTraverser;
typedef typename IteratorTraits::DefaultAccessor InternalAccessor;
typedef typename IteratorTraits::const_iterator InternalConstTraverser;
typedef typename IteratorTraits::DefaultAccessor InternalConstAccessor;
public:
/* when traverser and accessor types passed to the constructor are the same as the corresponding
internal types, we need not copy the image (speed up)
*/
SplineImageView0(InternalTraverser is, InternalTraverser iend, InternalAccessor sa)
: Base(iend.x - is.x, iend.y - is.y, is)
{}
SplineImageView0(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
{}
SplineImageView0(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor sa)
: Base(iend.x - is.x, iend.y - is.y, is)
{}
SplineImageView0(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
{}
template
SplineImageView0(MultiArrayView<2, T, SU> const & i)
: Base(i.shape(0), i.shape(1)),
image_(i.shape(0), i.shape(1))
{
for(unsigned int y=0; yheight(); ++y)
for(unsigned int x=0; xwidth(); ++x)
image_(x,y) = detail::RequiresExplicitCast::cast(i(x,y));
this->internalIndexer_ = image_.upperLeft();
}
template
SplineImageView0(SrcIterator is, SrcIterator iend, SrcAccessor sa)
: Base(iend.x - is.x, iend.y - is.y),
image_(iend - is)
{
copyImage(srcIterRange(is, iend, sa), destImage(image_));
this->internalIndexer_ = image_.upperLeft();
}
template
SplineImageView0(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y),
image_(s.second - s.first)
{
copyImage(s, destImage(image_));
this->internalIndexer_ = image_.upperLeft();
}
InternalImage const & image() const
{ return image_; }
protected:
InternalImage image_;
};
template
class SplineImageView0 >
: public SplineImageView0Base >
{
typedef SplineImageView0Base > Base;
public:
typedef typename Base::value_type value_type;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order };
typedef BasicImage InternalImage;
protected:
typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexer;
public:
/* when traverser and accessor types passed to the constructor are the same as the corresponding
internal types, we need not copy the image (speed up)
*/
SplineImageView0(InternalIndexer const & i)
: Base(i.shape(0), i.shape(1), i)
{}
template
SplineImageView0(MultiArrayView<2, T, SU> const & i)
: Base(i.shape(0), i.shape(1)),
image_(i.shape(0), i.shape(1))
{
for(unsigned int y=0; yheight(); ++y)
for(unsigned int x=0; xwidth(); ++x)
image_(x,y) = detail::RequiresExplicitCast::cast(i(x,y));
this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
image_.data());
}
template
SplineImageView0(SrcIterator is, SrcIterator iend, SrcAccessor sa)
: Base(iend.x - is.x, iend.y - is.y),
image_(iend-is)
{
copyImage(srcIterRange(is, iend, sa), destImage(image_));
this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
image_.data());
}
template
SplineImageView0(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y),
image_(s.second - s.first)
{
copyImage(s, destImage(image_));
this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
image_.data());
}
InternalImage const & image() const
{ return image_; }
protected:
InternalImage image_;
};
template
class SplineImageView<0, VALUETYPE>
: public SplineImageView0
{
typedef SplineImageView0 Base;
public:
typedef typename Base::value_type value_type;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order };
typedef typename Base::InternalImage InternalImage;
protected:
typedef typename Base::InternalTraverser InternalTraverser;
typedef typename Base::InternalAccessor InternalAccessor;
typedef typename Base::InternalConstTraverser InternalConstTraverser;
typedef typename Base::InternalConstAccessor InternalConstAccessor;
public:
/* when traverser and accessor types passed to the constructor are the same as the corresponding
internal types, we need not copy the image (speed up)
*/
SplineImageView(InternalTraverser is, InternalTraverser iend, InternalAccessor sa, bool /* unused */ = false)
: Base(is, iend, sa)
{}
SplineImageView(triple s, bool /* unused */ = false)
: Base(s)
{}
SplineImageView(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor sa, bool /* unused */ = false)
: Base(is, iend, sa)
{}
SplineImageView(triple s, bool /* unused */ = false)
: Base(s)
{}
template
SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool /* unused */ = false)
: Base(is, iend, sa)
{
copyImage(srcIterRange(is, iend, sa), destImage(this->image_));
}
template
SplineImageView(triple s, bool /* unused */ = false)
: Base(s)
{
copyImage(s, destImage(this->image_));
}
};
/********************************************************/
/* */
/* SplineImageView1 */
/* */
/********************************************************/
template
class SplineImageView1Base
{
typedef typename INTERNAL_INDEXER::value_type InternalValue;
public:
typedef VALUETYPE value_type;
typedef Size2D size_type;
typedef TinyVector difference_type;
enum StaticOrder { order = 1 };
public:
SplineImageView1Base(unsigned int w, unsigned int h)
: w_(w), h_(h)
{}
SplineImageView1Base(int w, int h, INTERNAL_INDEXER i)
: w_(w), h_(h), internalIndexer_(i)
{}
template
value_type unchecked(FixedPoint x,
FixedPoint y) const
{
int ix = floor(x);
FixedPoint<0, FractionalBits1> tx = frac(x - FixedPoint(ix));
FixedPoint<0, FractionalBits1> dtx = dual_frac(tx);
if(ix == (int)w_ - 1)
{
--ix;
tx.value = FixedPoint<0, FractionalBits1>::ONE;
dtx.value = 0;
}
int iy = floor(y);
FixedPoint<0, FractionalBits2> ty = frac(y - FixedPoint(iy));
FixedPoint<0, FractionalBits2> dty = dual_frac(ty);
if(iy == (int)h_ - 1)
{
--iy;
ty.value = FixedPoint<0, FractionalBits2>::ONE;
dty.value = 0;
}
return fixed_point_cast(
dty*(dtx*fixedPoint(internalIndexer_(ix,iy)) +
tx*fixedPoint(internalIndexer_(ix+1,iy))) +
ty *(dtx*fixedPoint(internalIndexer_(ix,iy+1)) +
tx*fixedPoint(internalIndexer_(ix+1,iy+1))));
}
template
value_type unchecked(FixedPoint x,
FixedPoint y,
unsigned int dx, unsigned int dy) const
{
int ix = floor(x);
FixedPoint<0, FractionalBits1> tx = frac(x - FixedPoint(ix));
FixedPoint<0, FractionalBits1> dtx = dual_frac(tx);
if(ix == (int)w_ - 1)
{
--ix;
tx.value = FixedPoint<0, FractionalBits1>::ONE;
dtx.value = 0;
}
int iy = floor(y);
FixedPoint<0, FractionalBits2> ty = frac(y - FixedPoint(iy));
FixedPoint<0, FractionalBits2> dty = dual_frac(ty);
if(iy == (int)h_ - 1)
{
--iy;
ty.value = FixedPoint<0, FractionalBits2>::ONE;
dty.value = 0;
}
switch(dx)
{
case 0:
switch(dy)
{
case 0:
return fixed_point_cast(
dty*(dtx*fixedPoint(internalIndexer_(ix,iy)) +
tx*fixedPoint(internalIndexer_(ix+1,iy))) +
ty *(dtx*fixedPoint(internalIndexer_(ix,iy+1)) +
tx*fixedPoint(internalIndexer_(ix+1,iy+1))));
case 1:
return fixed_point_cast(
(dtx*fixedPoint(internalIndexer_(ix,iy+1)) + tx*fixedPoint(internalIndexer_(ix+1,iy+1))) -
(dtx*fixedPoint(internalIndexer_(ix,iy)) + tx*fixedPoint(internalIndexer_(ix+1,iy))));
default:
return NumericTraits::zero();
}
case 1:
switch(dy)
{
case 0:
return fixed_point_cast(
dty*(fixedPoint(internalIndexer_(ix+1,iy)) - fixedPoint(internalIndexer_(ix,iy))) +
ty *(fixedPoint(internalIndexer_(ix+1,iy+1)) - fixedPoint(internalIndexer_(ix,iy+1))));
case 1:
return detail::RequiresExplicitCast::cast(
(internalIndexer_(ix+1,iy+1) - internalIndexer_(ix,iy+1)) -
(internalIndexer_(ix+1,iy) - internalIndexer_(ix,iy)));
default:
return NumericTraits::zero();
}
default:
return NumericTraits::zero();
}
}
value_type unchecked(double x, double y) const
{
int ix = (int)std::floor(x);
if(ix == (int)w_ - 1)
--ix;
double tx = x - ix;
int iy = (int)std::floor(y);
if(iy == (int)h_ - 1)
--iy;
double ty = y - iy;
return NumericTraits::fromRealPromote(
(1.0-ty)*((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)) +
ty *((1.0-tx)*internalIndexer_(ix,iy+1) + tx*internalIndexer_(ix+1,iy+1)));
}
value_type unchecked(double x, double y, unsigned int dx, unsigned int dy) const
{
int ix = (int)std::floor(x);
if(ix == (int)w_ - 1)
--ix;
double tx = x - ix;
int iy = (int)std::floor(y);
if(iy == (int)h_ - 1)
--iy;
double ty = y - iy;
switch(dx)
{
case 0:
switch(dy)
{
case 0:
return NumericTraits::fromRealPromote(
(1.0-ty)*((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)) +
ty *((1.0-tx)*internalIndexer_(ix,iy+1) + tx*internalIndexer_(ix+1,iy+1)));
case 1:
return NumericTraits::fromRealPromote(
((1.0-tx)*internalIndexer_(ix,iy+1) + tx*internalIndexer_(ix+1,iy+1)) -
((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)));
default:
return NumericTraits::zero();
}
case 1:
switch(dy)
{
case 0:
return NumericTraits::fromRealPromote(
(1.0-ty)*(internalIndexer_(ix+1,iy) - internalIndexer_(ix,iy)) +
ty *(internalIndexer_(ix+1,iy+1) - internalIndexer_(ix,iy+1)));
case 1:
return detail::RequiresExplicitCast::cast(
(internalIndexer_(ix+1,iy+1) - internalIndexer_(ix,iy+1)) -
(internalIndexer_(ix+1,iy) - internalIndexer_(ix,iy)));
default:
return NumericTraits::zero();
}
default:
return NumericTraits::zero();
}
}
value_type operator()(double x, double y) const
{
return operator()(x, y, 0, 0);
}
value_type operator()(double x, double y, unsigned int dx, unsigned int dy) const
{
value_type mul = NumericTraits::one();
if(x < 0.0)
{
x = -x;
vigra_precondition(x <= w_ - 1.0,
"SplineImageView::operator(): coordinates out of range.");
if(dx % 2)
mul = -mul;
}
else if(x > w_ - 1.0)
{
x = 2.0*w_-2.0-x;
vigra_precondition(x >= 0.0,
"SplineImageView::operator(): coordinates out of range.");
if(dx % 2)
mul = -mul;
}
if(y < 0.0)
{
y = -y;
vigra_precondition(y <= h_ - 1.0,
"SplineImageView::operator(): coordinates out of range.");
if(dy % 2)
mul = -mul;
}
else if(y > h_ - 1.0)
{
y = 2.0*h_-2.0-y;
vigra_precondition(y >= 0.0,
"SplineImageView::operator(): coordinates out of range.");
if(dy % 2)
mul = -mul;
}
return mul*unchecked(x, y, dx, dy);
}
value_type dx(double x, double y) const
{ return operator()(x, y, 1, 0); }
value_type dy(double x, double y) const
{ return operator()(x, y, 0, 1); }
value_type dxx(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxy(double x, double y) const
{ return operator()(x, y, 1, 1); }
value_type dyy(double x, double y) const
{ return NumericTraits::zero(); }
value_type dx3(double x, double y) const
{ return NumericTraits::zero(); }
value_type dy3(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxxy(double x, double y) const
{ return NumericTraits::zero(); }
value_type dxyy(double x, double y) const
{ return NumericTraits::zero(); }
value_type operator()(difference_type const & d) const
{ return operator()(d[0], d[1]); }
value_type operator()(difference_type const & d, unsigned int dx, unsigned int dy) const
{ return operator()(d[0], d[1], dx, dy); }
value_type dx(difference_type const & d) const
{ return operator()(d[0], d[1], 1, 0); }
value_type dy(difference_type const & d) const
{ return operator()(d[0], d[1], 0, 1); }
value_type dxx(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxy(difference_type const & d) const
{ return operator()(d[0], d[1], 1, 1); }
value_type dyy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dx3(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dy3(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxxy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type dxyy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2(double x, double y) const
{ return sq(dx(x,y)) + sq(dy(x,y)); }
value_type g2x(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2y(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2xx(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2xy(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2yy(double x, double y) const
{ return NumericTraits::zero(); }
value_type g2(difference_type const & d) const
{ return g2(d[0], d[1]); }
value_type g2x(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2y(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2xx(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2xy(difference_type const & d) const
{ return NumericTraits::zero(); }
value_type g2yy(difference_type const & d) const
{ return NumericTraits::zero(); }
unsigned int width() const
{ return w_; }
unsigned int height() const
{ return h_; }
size_type size() const
{ return size_type(w_, h_); }
template
void coefficientArray(double x, double y, Array & res) const;
void calculateIndices(double x, double y, int & ix, int & iy, int & ix1, int & iy1) const;
bool isInsideX(double x) const
{
return x >= 0.0 && x <= width() - 1.0;
}
bool isInsideY(double y) const
{
return y >= 0.0 && y <= height() - 1.0;
}
bool isInside(double x, double y) const
{
return isInsideX(x) && isInsideY(y);
}
bool isValid(double x, double y) const
{
return x < 2.0*w_-2.0 && x > 1.0-w_ && y < 2.0*h_-2.0 && y > 1.0-h_;
}
bool sameFacet(double x0, double y0, double x1, double y1) const
{
x0 = VIGRA_CSTD::floor(x0);
y0 = VIGRA_CSTD::floor(y0);
x1 = VIGRA_CSTD::floor(x1);
y1 = VIGRA_CSTD::floor(y1);
return x0 == x1 && y0 == y1;
}
protected:
unsigned int w_, h_;
INTERNAL_INDEXER internalIndexer_;
};
template
template
void SplineImageView1Base::coefficientArray(double x, double y, Array & res) const
{
int ix, iy, ix1, iy1;
calculateIndices(x, y, ix, iy, ix1, iy1);
res.resize(2, 2);
res(0,0) = internalIndexer_(ix,iy);
res(1,0) = internalIndexer_(ix1,iy) - internalIndexer_(ix,iy);
res(0,1) = internalIndexer_(ix,iy1) - internalIndexer_(ix,iy);
res(1,1) = internalIndexer_(ix,iy) - internalIndexer_(ix1,iy) -
internalIndexer_(ix,iy1) + internalIndexer_(ix1,iy1);
}
template
void SplineImageView1Base::calculateIndices(double x, double y, int & ix, int & iy, int & ix1, int & iy1) const
{
if(x < 0.0)
{
x = -x;
vigra_precondition(x <= w_ - 1.0,
"SplineImageView::calculateIndices(): coordinates out of range.");
ix = (int)VIGRA_CSTD::ceil(x);
ix1 = ix - 1;
}
else if(x >= w_ - 1.0)
{
x = 2.0*w_-2.0-x;
vigra_precondition(x > 0.0,
"SplineImageView::calculateIndices(): coordinates out of range.");
ix = (int)VIGRA_CSTD::ceil(x);
ix1 = ix - 1;
}
else
{
ix = (int)VIGRA_CSTD::floor(x);
ix1 = ix + 1;
}
if(y < 0.0)
{
y = -y;
vigra_precondition(y <= h_ - 1.0,
"SplineImageView::calculateIndices(): coordinates out of range.");
iy = (int)VIGRA_CSTD::ceil(y);
iy1 = iy - 1;
}
else if(y >= h_ - 1.0)
{
y = 2.0*h_-2.0-y;
vigra_precondition(y > 0.0,
"SplineImageView::calculateIndices(): coordinates out of range.");
iy = (int)VIGRA_CSTD::ceil(y);
iy1 = iy - 1;
}
else
{
iy = (int)VIGRA_CSTD::floor(y);
iy1 = iy + 1;
}
}
/** \brief Create an image view for bi-linear interpolation.
This class behaves like \ref vigra::SplineImageView<1, ...>, but one can pass
an additional template argument that determined the internal representation of the image.
If this is equal to the argument type passed in the constructor, the image is not copied.
By default, this works for \ref vigra::BasicImage, \ref vigra::BasicImageView,
\ref vigra::MultiArray<2, ...>, and \ref vigra::MultiArrayView<2, ...>.
In addition to the function provided by \ref vigra::SplineImageView, there are functions
unchecked(x,y) and unchecked(x,y, xorder, yorder) which improve speed by
not applying bounds checking and reflective border treatment (isInside(x, y) must
be true), but otherwise behave identically to their checked counterparts.
In addition, x and y can have type \ref vigra::FixedPoint instead of
double.
*/
template ::const_traverser>
class SplineImageView1
: public SplineImageView1Base
{
typedef SplineImageView1Base Base;
public:
typedef typename Base::value_type value_type;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order };
typedef BasicImage InternalImage;
protected:
typedef typename IteratorTraits::mutable_iterator InternalTraverser;
typedef typename IteratorTraits::DefaultAccessor InternalAccessor;
typedef typename IteratorTraits::const_iterator InternalConstTraverser;
typedef typename IteratorTraits::DefaultAccessor InternalConstAccessor;
public:
/* when traverser and accessor types passed to the constructor are the same as the corresponding
internal types, we need not copy the image (speed up)
*/
SplineImageView1(InternalTraverser is, InternalTraverser iend, InternalAccessor sa)
: Base(iend.x - is.x, iend.y - is.y, is)
{}
SplineImageView1(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
{}
SplineImageView1(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor sa)
: Base(iend.x - is.x, iend.y - is.y, is)
{}
SplineImageView1(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
{}
template
SplineImageView1(MultiArrayView<2, T, SU> const & i)
: Base(i.shape(0), i.shape(1)),
image_(i.shape(0), i.shape(1))
{
for(unsigned int y=0; yheight(); ++y)
for(unsigned int x=0; xwidth(); ++x)
image_(x,y) = detail::RequiresExplicitCast::cast(i(x,y));
this->internalIndexer_ = image_.upperLeft();
}
template
SplineImageView1(SrcIterator is, SrcIterator iend, SrcAccessor sa)
: Base(iend.x - is.x, iend.y - is.y),
image_(iend - is)
{
copyImage(srcIterRange(is, iend, sa), destImage(image_));
this->internalIndexer_ = image_.upperLeft();
}
template
SplineImageView1(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y),
image_(s.second - s.first)
{
copyImage(s, destImage(image_));
this->internalIndexer_ = image_.upperLeft();
}
InternalImage const & image() const
{ return image_; }
protected:
InternalImage image_;
};
template
class SplineImageView1 >
: public SplineImageView1Base >
{
typedef SplineImageView1Base > Base;
public:
typedef typename Base::value_type value_type;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order };
typedef BasicImage InternalImage;
protected:
typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexer;
public:
/* when traverser and accessor types passed to the constructor are the same as the corresponding
internal types, we need not copy the image (speed up)
*/
SplineImageView1(InternalIndexer const & i)
: Base(i.shape(0), i.shape(1), i)
{}
template
SplineImageView1(MultiArrayView<2, T, SU> const & i)
: Base(i.shape(0), i.shape(1)),
image_(i.shape(0), i.shape(1))
{
for(unsigned int y=0; yheight(); ++y)
for(unsigned int x=0; xwidth(); ++x)
image_(x,y) = detail::RequiresExplicitCast::cast(i(x,y));
this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
image_.data());
}
template
SplineImageView1(SrcIterator is, SrcIterator iend, SrcAccessor sa)
: Base(iend.x - is.x, iend.y - is.y),
image_(iend-is)
{
copyImage(srcIterRange(is, iend, sa), destImage(image_));
this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
image_.data());
}
template
SplineImageView1(triple s)
: Base(s.second.x - s.first.x, s.second.y - s.first.y),
image_(s.second - s.first)
{
copyImage(s, destImage(image_));
this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
image_.data());
}
InternalImage const & image() const
{ return image_; }
protected:
InternalImage image_;
};
template
class SplineImageView<1, VALUETYPE>
: public SplineImageView1
{
typedef SplineImageView1 Base;
public:
typedef typename Base::value_type value_type;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order };
typedef typename Base::InternalImage InternalImage;
protected:
typedef typename Base::InternalTraverser InternalTraverser;
typedef typename Base::InternalAccessor InternalAccessor;
typedef typename Base::InternalConstTraverser InternalConstTraverser;
typedef typename Base::InternalConstAccessor InternalConstAccessor;
public:
/* when traverser and accessor types passed to the constructor are the same as the corresponding
internal types, we need not copy the image (speed up)
*/
SplineImageView(InternalTraverser is, InternalTraverser iend, InternalAccessor sa, bool /* unused */ = false)
: Base(is, iend, sa)
{}
SplineImageView(triple s, bool /* unused */ = false)
: Base(s)
{}
SplineImageView(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor sa, bool /* unused */ = false)
: Base(is, iend, sa)
{}
SplineImageView(triple s, bool /* unused */ = false)
: Base(s)
{}
template
SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool /* unused */ = false)
: Base(is, iend, sa)
{
copyImage(srcIterRange(is, iend, sa), destImage(this->image_));
}
template
SplineImageView(triple s, bool /* unused */ = false)
: Base(s)
{
copyImage(s, destImage(this->image_));
}
};
} // namespace vigra
#endif /* VIGRA_SPLINEIMAGEVIEW_HXX */