[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

splineimageview.hxx
1/************************************************************************/
2/* */
3/* Copyright 1998-2004 by Ullrich Koethe */
4/* */
5/* This file is part of the VIGRA computer vision library. */
6/* The VIGRA Website is */
7/* http://hci.iwr.uni-heidelberg.de/vigra/ */
8/* Please direct questions, bug reports, and contributions to */
9/* ullrich.koethe@iwr.uni-heidelberg.de or */
10/* vigra@informatik.uni-hamburg.de */
11/* */
12/* Permission is hereby granted, free of charge, to any person */
13/* obtaining a copy of this software and associated documentation */
14/* files (the "Software"), to deal in the Software without */
15/* restriction, including without limitation the rights to use, */
16/* copy, modify, merge, publish, distribute, sublicense, and/or */
17/* sell copies of the Software, and to permit persons to whom the */
18/* Software is furnished to do so, subject to the following */
19/* conditions: */
20/* */
21/* The above copyright notice and this permission notice shall be */
22/* included in all copies or substantial portions of the */
23/* Software. */
24/* */
25/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32/* OTHER DEALINGS IN THE SOFTWARE. */
33/* */
34/************************************************************************/
35
36#ifndef VIGRA_SPLINEIMAGEVIEW_HXX
37#define VIGRA_SPLINEIMAGEVIEW_HXX
38
39#include "mathutil.hxx"
40#include "recursiveconvolution.hxx"
41#include "splines.hxx"
42#include "array_vector.hxx"
43#include "basicimage.hxx"
44#include "copyimage.hxx"
45#include "tinyvector.hxx"
46#include "fixedpoint.hxx"
47#include "multi_array.hxx"
48
49 namespace vigra {
50
51/********************************************************/
52/* */
53/* SplineImageView */
54/* */
55/********************************************************/
56/** \brief Create a continuous view onto a discrete image using splines.
57
58 This class is very useful if image values or derivatives at arbitrary
59 real-valued coordinates are needed. Access at such coordinates is implemented by
60 interpolating the given discrete image values with a spline of the
61 specified <tt>ORDER</TT>. Continuous derivatives are available up to
62 degree <tt>ORDER-1</TT>. If the requested coordinates are near the image border,
63 reflective boundary conditions are applied. In principle, this class can also be used
64 for image resizing, but here the functions from the <tt>resize...</tt> family are
65 more efficient, since they exploit the regularity of the sampling grid.
66
67 The <tt>SplineImageView</tt> template is explicitly specialized to make it as efficient as possible.
68 In particular, unnecessary copying of the image is avoided when the iterators passed
69 in the constructor originate from a \ref vigra::BasicImage. In addition, these specializations
70 provide function <tt>unchecked(...)</tt> that do not perform bounds checking. If the original image
71 is not a variant of \ref vigra::BasicImage, one can customize the internal representation by
72 using \ref vigra::SplineImageView0 or \ref vigra::SplineImageView1.
73
74 <b>Usage:</b>
75
76 <b>\#include</b> <vigra/splineimageview.hxx><br>
77 Namespace: vigra
78
79 \code
80 BImage img(w,h);
81 ... // fill img
82
83 // construct spline view for quadratic interpolation
84 SplineImageView<2, double> spi2(srcImageRange(img));
85
86 double x = ..., y = ...;
87 double v2 = spi2(x, y);
88
89 // construct spline view for linear interpolation
90 SplineImageView<1, UInt32> spi1(srcImageRange(img));
91
92 UInt32 v1 = spi1(x, y);
93
94 FixedPoint<16, 15> fx(...), fy(...);
95 UInt32 vf = spi1.unchecked(fx, fy); // caller is sure that (fx, fy) are valid coordinates
96 \endcode
97*/
98 template <int ORDER, class VALUETYPE>
99 class SplineImageView
100{
101 typedef typename NumericTraits<VALUETYPE>::RealPromote InternalValue;
102
103 public:
104
105 /** The view's value type (return type of access and derivative functions).
106 */
107 typedef VALUETYPE value_type;
108
109 /** The view's squared norm type (return type of g2() etc.).
110 */
111 typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
112
113 /** The view's size type.
114 */
115 typedef Size2D size_type;
116
117 /** The view's difference type.
118 */
119 typedef TinyVector<double, 2> difference_type;
120
121 /** The order of the spline used.
122 */
123 constexpr static int order = ORDER;
124
125 /** The type of the internal image holding the spline coefficients.
126 */
127 typedef BasicImage<InternalValue> InternalImage;
128
129 private:
130 typedef typename InternalImage::traverser InternalTraverser;
131 typedef typename InternalTraverser::row_iterator InternalRowIterator;
132 typedef typename InternalTraverser::column_iterator InternalColumnIterator;
133 typedef BSpline<ORDER, double> Spline;
134
135 constexpr static int ksize_ = ORDER + 1;
136 constexpr static int kcenter_ = ORDER / 2;
137
138 public:
139
140 /** Construct SplineImageView for a 2D MultiArrayView.
141
142 If <tt>skipPrefiltering = true</tt> (default: <tt>false</tt>), the recursive
143 prefilter of the cardinal spline function is not applied, resulting
144 in an approximating (smoothing) rather than interpolating spline. This is
145 especially useful if customized prefilters are to be applied.
146 */
147 template <class U, class S>
148 SplineImageView(MultiArrayView<2, U, S> const & s, bool skipPrefiltering = false)
149 : w_(s.shape(0)), h_(s.shape(1)), w1_(w_-1), h1_(h_-1),
150 x0_(kcenter_), x1_(w_ - kcenter_ - 2), y0_(kcenter_), y1_(h_ - kcenter_ - 2),
151 image_(w_, h_),
152 x_(-1.0), y_(-1.0),
153 u_(-1.0), v_(-1.0)
154 {
155 copyImage(srcImageRange(s), destImage(image_));
156 if(!skipPrefiltering)
157 init();
158 }
159
160 /** Construct SplineImageView for an image given by \ref ImageIterators and \ref DataAccessors.
161
162 If <tt>skipPrefiltering = true</tt> (default: <tt>false</tt>), the recursive
163 prefilter of the cardinal spline function is not applied, resulting
164 in an approximating (smoothing) rather than interpolating spline. This is
165 especially useful if customized prefilters are to be applied.
166 */
167 template <class SrcIterator, class SrcAccessor>
168 SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool skipPrefiltering = false)
169 : w_(iend.x - is.x), h_(iend.y - is.y), w1_(w_-1), h1_(h_-1),
170 x0_(kcenter_), x1_(w_ - kcenter_ - 2), y0_(kcenter_), y1_(h_ - kcenter_ - 2),
171 image_(w_, h_),
172 x_(-1.0), y_(-1.0),
173 u_(-1.0), v_(-1.0)
174 {
175 copyImage(srcIterRange(is, iend, sa), destImage(image_));
176 if(!skipPrefiltering)
177 init();
178 }
179
180 /** Construct SplineImageView for an image given by \ref ArgumentObjectFactories.
181
182 If <tt>skipPrefiltering = true</tt> (default: <tt>false</tt>), the recursive
183 prefilter of the cardinal spline function is not applied, resulting
184 in an approximating (smoothing) rather than interpolating spline. This is
185 especially useful if customized prefilters are to be applied.
186 */
187 template <class SrcIterator, class SrcAccessor>
188 SplineImageView(triple<SrcIterator, SrcIterator, SrcAccessor> s, bool skipPrefiltering = false)
189 : w_(s.second.x - s.first.x), h_(s.second.y - s.first.y), w1_(w_-1), h1_(h_-1),
190 x0_(kcenter_), x1_(w_ - kcenter_ - 2), y0_(kcenter_), y1_(h_ - kcenter_ - 2),
191 image_(w_, h_),
192 x_(-1.0), y_(-1.0),
193 u_(-1.0), v_(-1.0)
194 {
195 copyImage(srcIterRange(s.first, s.second, s.third), destImage(image_));
196 if(!skipPrefiltering)
197 init();
198 }
199
200 /** Access interpolated function at real-valued coordinate <tt>(x, y)</tt>.
201 If <tt>(x, y)</tt> is near the image border or outside the image, the value
202 is calculated with reflective boundary conditions. An exception is thrown if the
203 coordinate is outside the first reflection.
204 */
205 value_type operator()(double x, double y) const;
206
207 /** Access derivative of order <tt>(dx, dy)</tt> at real-valued coordinate <tt>(x, y)</tt>.
208 If <tt>(x, y)</tt> is near the image border or outside the image, the value
209 is calculated with reflective boundary conditions. An exception is thrown if the
210 coordinate is outside the first reflection.
211 */
212 value_type operator()(double x, double y, unsigned int dx, unsigned int dy) const;
213
214 /** Access 1st derivative in x-direction at real-valued coordinate <tt>(x, y)</tt>.
215 Equivalent to <tt>splineView(x, y, 1, 0)</tt>.
216 */
217 value_type dx(double x, double y) const
218 { return operator()(x, y, 1, 0); }
219
220 /** Access 1st derivative in y-direction at real-valued coordinate <tt>(x, y)</tt>.
221 Equivalent to <tt>splineView(x, y, 0, 1)</tt>.
222 */
223 value_type dy(double x, double y) const
224 { return operator()(x, y, 0, 1); }
225
226 /** Access 2nd derivative in x-direction at real-valued coordinate <tt>(x, y)</tt>.
227 Equivalent to <tt>splineView(x, y, 2, 0)</tt>.
228 */
229 value_type dxx(double x, double y) const
230 { return operator()(x, y, 2, 0); }
231
232 /** Access mixed 2nd derivative at real-valued coordinate <tt>(x, y)</tt>.
233 Equivalent to <tt>splineView(x, y, 1, 1)</tt>.
234 */
235 value_type dxy(double x, double y) const
236 { return operator()(x, y, 1, 1); }
237
238 /** Access 2nd derivative in y-direction at real-valued coordinate <tt>(x, y)</tt>.
239 Equivalent to <tt>splineView(x, y, 0, 2)</tt>.
240 */
241 value_type dyy(double x, double y) const
242 { return operator()(x, y, 0, 2); }
243
244 /** Access 3rd derivative in x-direction at real-valued coordinate <tt>(x, y)</tt>.
245 Equivalent to <tt>splineView(x, y, 3, 0)</tt>.
246 */
247 value_type dx3(double x, double y) const
248 { return operator()(x, y, 3, 0); }
249
250 /** Access 3rd derivative in y-direction at real-valued coordinate <tt>(x, y)</tt>.
251 Equivalent to <tt>splineView(x, y, 0, 3)</tt>.
252 */
253 value_type dy3(double x, double y) const
254 { return operator()(x, y, 0, 3); }
255
256 /** Access mixed 3rd derivative dxxy at real-valued coordinate <tt>(x, y)</tt>.
257 Equivalent to <tt>splineView(x, y, 2, 1)</tt>.
258 */
259 value_type dxxy(double x, double y) const
260 { return operator()(x, y, 2, 1); }
261
262 /** Access mixed 3rd derivative dxyy at real-valued coordinate <tt>(x, y)</tt>.
263 Equivalent to <tt>splineView(x, y, 1, 2)</tt>.
264 */
265 value_type dxyy(double x, double y) const
266 { return operator()(x, y, 1, 2); }
267
268 /** Access interpolated function at real-valued coordinate <tt>d</tt>.
269 Equivalent to <tt>splineView(d[0], d[1])</tt>.
270 */
271 value_type operator()(difference_type const & d) const
272 { return operator()(d[0], d[1]); }
273
274 /** Access derivative of order <tt>(dx, dy)</tt> at real-valued coordinate <tt>d</tt>.
275 Equivalent to <tt>splineView(d[0], d[1], dx, dy)</tt>.
276 */
277 value_type operator()(difference_type const & d, unsigned int dx, unsigned int dy) const
278 { return operator()(d[0], d[1], dx, dy); }
279
280 /** Access 1st derivative in x-direction at real-valued coordinate <tt>d</tt>.
281 Equivalent to <tt>splineView.dx(d[0], d[1])</tt>.
282 */
283 value_type dx(difference_type const & d) const
284 { return dx(d[0], d[1]); }
285
286 /** Access 1st derivative in y-direction at real-valued coordinate <tt>d</tt>.
287 Equivalent to <tt>splineView.dy(d[0], d[1])</tt>.
288 */
289 value_type dy(difference_type const & d) const
290 { return dy(d[0], d[1]); }
291
292 /** Access 2nd derivative in x-direction at real-valued coordinate <tt>d</tt>.
293 Equivalent to <tt>splineView.dxx(d[0], d[1])</tt>.
294 */
295 value_type dxx(difference_type const & d) const
296 { return dxx(d[0], d[1]); }
297
298 /** Access mixed 2nd derivative at real-valued coordinate <tt>d</tt>.
299 Equivalent to <tt>splineView.dxy(d[0], d[1])</tt>.
300 */
301 value_type dxy(difference_type const & d) const
302 { return dxy(d[0], d[1]); }
303
304 /** Access 2nd derivative in y-direction at real-valued coordinate <tt>d</tt>.
305 Equivalent to <tt>splineView.dyy(d[0], d[1])</tt>.
306 */
307 value_type dyy(difference_type const & d) const
308 { return dyy(d[0], d[1]); }
309
310 /** Access 3rd derivative in x-direction at real-valued coordinate <tt>d</tt>.
311 Equivalent to <tt>splineView.dx3(d[0], d[1])</tt>.
312 */
313 value_type dx3(difference_type const & d) const
314 { return dx3(d[0], d[1]); }
315
316 /** Access 3rd derivative in y-direction at real-valued coordinate <tt>d</tt>.
317 Equivalent to <tt>splineView.dy3(d[0], d[1])</tt>.
318 */
319 value_type dy3(difference_type const & d) const
320 { return dy3(d[0], d[1]); }
321
322 /** Access mixed 3rd derivative dxxy at real-valued coordinate <tt>d</tt>.
323 Equivalent to <tt>splineView.dxxy(d[0], d[1])</tt>.
324 */
325 value_type dxxy(difference_type const & d) const
326 { return dxxy(d[0], d[1]); }
327
328 /** Access mixed 3rd derivative dxyy at real-valued coordinate <tt>d</tt>.
329 Equivalent to <tt>splineView.dxyy(d[0], d[1])</tt>.
330 */
331 value_type dxyy(difference_type const & d) const
332 { return dxyy(d[0], d[1]); }
333
334 /** Access gradient squared magnitude at real-valued coordinate <tt>(x, y)</tt>.
335 */
336 SquaredNormType g2(double x, double y) const;
337
338 /** Access 1st derivative in x-direction of gradient squared magnitude
339 at real-valued coordinate <tt>(x, y)</tt>.
340 */
341 SquaredNormType g2x(double x, double y) const;
342
343 /** Access 1st derivative in y-direction of gradient squared magnitude
344 at real-valued coordinate <tt>(x, y)</tt>.
345 */
346 SquaredNormType g2y(double x, double y) const;
347
348 /** Access 2nd derivative in x-direction of gradient squared magnitude
349 at real-valued coordinate <tt>(x, y)</tt>.
350 */
351 SquaredNormType g2xx(double x, double y) const;
352
353 /** Access mixed 2nd derivative of gradient squared magnitude
354 at real-valued coordinate <tt>(x, y)</tt>.
355 */
356 SquaredNormType g2xy(double x, double y) const;
357
358 /** Access 2nd derivative in y-direction of gradient squared magnitude
359 at real-valued coordinate <tt>(x, y)</tt>.
360 */
361 SquaredNormType g2yy(double x, double y) const;
362
363 /** Access gradient squared magnitude at real-valued coordinate <tt>d</tt>.
364 */
365 SquaredNormType g2(difference_type const & d) const
366 { return g2(d[0], d[1]); }
367
368 /** Access 1st derivative in x-direction of gradient squared magnitude
369 at real-valued coordinate <tt>d</tt>.
370 */
371 SquaredNormType g2x(difference_type const & d) const
372 { return g2x(d[0], d[1]); }
373
374 /** Access 1st derivative in y-direction of gradient squared magnitude
375 at real-valued coordinate <tt>d</tt>.
376 */
377 SquaredNormType g2y(difference_type const & d) const
378 { return g2y(d[0], d[1]); }
379
380 /** Access 2nd derivative in x-direction of gradient squared magnitude
381 at real-valued coordinate <tt>d</tt>.
382 */
383 SquaredNormType g2xx(difference_type const & d) const
384 { return g2xx(d[0], d[1]); }
385
386 /** Access mixed 2nd derivative of gradient squared magnitude
387 at real-valued coordinate <tt>d</tt>.
388 */
389 SquaredNormType g2xy(difference_type const & d) const
390 { return g2xy(d[0], d[1]); }
391
392 /** Access 2nd derivative in y-direction of gradient squared magnitude
393 at real-valued coordinate <tt>d</tt>.
394 */
395 SquaredNormType g2yy(difference_type const & d) const
396 { return g2yy(d[0], d[1]); }
397
398 /** The width of the image.
399 <tt>0 <= x <= width()-1</tt> is required for all access functions.
400 */
401 unsigned int width() const
402 { return w_; }
403
404 /** The height of the image.
405 <tt>0 <= y <= height()-1</tt> is required for all access functions.
406 */
407 unsigned int height() const
408 { return h_; }
409
410 /** The size of the image.
411 <tt>0 <= x <= size().x-1</tt> and <tt>0 <= y <= size().y-1</tt>
412 are required for all access functions.
413 */
414 size_type size() const
415 { return size_type(w_, h_); }
416
417 /** The shape of the image.
418 Same as size(), except for the return type.
419 */
420 TinyVector<unsigned int, 2> shape() const
421 { return TinyVector<unsigned int, 2>(w_, h_); }
422
423 /** The internal image holding the spline coefficients.
424 */
425 InternalImage const & image() const
426 {
427 return image_;
428 }
429
430 /** Get the array of polynomial coefficients for the facet containing
431 the point <tt>(x, y)</tt>. The array <tt>res</tt> must have
432 dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients, the
433 value of the interpolated function can be calculated by the following
434 algorithm
435
436 \code
437 SplineImageView<ORDER, float> view(...);
438 double x = ..., y = ...;
439 double dx, dy;
440
441 // calculate the local facet coordinates of x and y
442 if(ORDER % 2)
443 {
444 // odd order => facet coordinates between 0 and 1
445 dx = x - floor(x);
446 dy = y - floor(y);
447 }
448 else
449 {
450 // even order => facet coordinates between -0.5 and 0.5
451 dx = x - floor(x + 0.5);
452 dy = y - floor(y + 0.5);
453 }
454
455 BasicImage<float> coefficients;
456 view.coefficientArray(x, y, coefficients);
457
458 float f_x_y = 0.0;
459 for(int ny = 0; ny < ORDER + 1; ++ny)
460 for(int nx = 0; nx < ORDER + 1; ++nx)
461 f_x_y += pow(dx, nx) * pow(dy, ny) * coefficients(nx, ny);
462
463 assert(abs(f_x_y - view(x, y)) < 1e-6);
464 \endcode
465 */
466 template <class Array>
467 void coefficientArray(double x, double y, Array & res) const;
468
469 /** Check if x is in the original image range.
470 Equivalent to <tt>0 <= x <= width()-1</tt>.
471 */
472 bool isInsideX(double x) const
473 {
474 return x >= 0.0 && x <= width()-1.0;
475 }
476
477 /** Check if y is in the original image range.
478 Equivalent to <tt>0 <= y <= height()-1</tt>.
479 */
480 bool isInsideY(double y) const
481 {
482 return y >= 0.0 && y <= height()-1.0;
483 }
484
485 /** Check if x and y are in the original image range.
486 Equivalent to <tt>0 <= x <= width()-1</tt> and <tt>0 <= y <= height()-1</tt>.
487 */
488 bool isInside(double x, double y) const
489 {
490 return isInsideX(x) && isInsideY(y);
491 }
492
493 /** Check if x and y are in the valid range. Points outside the original image range are computed
494 by reflective boundary conditions, but only within the first reflection.
495 Equivalent to <tt>-width() + ORDER/2 + 2 < x < 2*width() - ORDER/2 - 2</tt> and
496 <tt>-height() + ORDER/2 + 2 < y < 2*height() - ORDER/2 - 2</tt>.
497 */
498 bool isValid(double x, double y) const
499 {
500 return x < w1_ + x1_ && x > -x1_ && y < h1_ + y1_ && y > -y1_;
501 }
502
503 /** Check whether the points <tt>(x0, y0)</tt> and <tt>(x1, y1)</tt> are in
504 the same spline facet. For odd order splines, facets span the range
505 <tt>(floor(x), floor(x)+1) x (floor(y), floor(y)+1)</tt> (i.e. we have
506 integer facet borders), whereas even order splines have facet between
507 half integer values
508 <tt>(floor(x)-0.5, floor(x)+0.5) x (floor(y)-0.5, floor(y)+0.5)</tt>.
509 */
510 bool sameFacet(double x0, double y0, double x1, double y1) const
511 {
512 x0 = VIGRA_CSTD::floor((ORDER % 2) ? x0 : x0 + 0.5);
513 y0 = VIGRA_CSTD::floor((ORDER % 2) ? y0 : y0 + 0.5);
514 x1 = VIGRA_CSTD::floor((ORDER % 2) ? x1 : x1 + 0.5);
515 y1 = VIGRA_CSTD::floor((ORDER % 2) ? y1 : y1 + 0.5);
516 return x0 == x1 && y0 == y1;
517 }
518
519 protected:
520
521 void init();
522 void calculateIndices(double x, double y) const;
523 void coefficients(double t, double * const & c) const;
524 void derivCoefficients(double t, unsigned int d, double * const & c) const;
525 value_type convolve() const;
526
527 unsigned int w_, h_;
528 int w1_, h1_;
529 double x0_, x1_, y0_, y1_;
530 InternalImage image_;
531 Spline k_;
532 mutable double x_, y_, u_, v_, kx_[ksize_], ky_[ksize_];
533 mutable int ix_[ksize_], iy_[ksize_];
534};
535
536 template <int ORDER, class VALUETYPE>
537 void SplineImageView<ORDER, VALUETYPE>::init()
538{
539 ArrayVector<double> const & b = k_.prefilterCoefficients();
540
541 for(unsigned int i=0; i<b.size(); ++i)
542 {
543 recursiveFilterX(srcImageRange(image_), destImage(image_), b[i], BORDER_TREATMENT_REFLECT);
544 recursiveFilterY(srcImageRange(image_), destImage(image_), b[i], BORDER_TREATMENT_REFLECT);
545 }
546}
547
548 namespace detail
549{
550
551 template <int i>
552 struct SplineImageViewUnrollLoop1
553{
554 template <class Array>
555 static void exec(int c0, Array c)
556 {
557 SplineImageViewUnrollLoop1<i-1>::exec(c0, c);
558 c[i] = c0 + i;
559 }
560};
561
562 template <>
563 struct SplineImageViewUnrollLoop1<0>
564{
565 template <class Array>
566 static void exec(int c0, Array c)
567 {
568 c[0] = c0;
569 }
570};
571
572 template <int i, class ValueType>
573 struct SplineImageViewUnrollLoop2
574{
575 template <class Array1, class RowIterator, class Array2>
576 static ValueType
577 exec(Array1 k, RowIterator r, Array2 x)
578 {
579 return ValueType(k[i] * r[x[i]]) + SplineImageViewUnrollLoop2<i-1, ValueType>::exec(k, r, x);
580 }
581};
582
583 template <class ValueType>
584 struct SplineImageViewUnrollLoop2<0, ValueType>
585{
586 template <class Array1, class RowIterator, class Array2>
587 static ValueType
588 exec(Array1 k, RowIterator r, Array2 x)
589 {
590 return ValueType(k[0] * r[x[0]]);
591 }
592};
593
594} // namespace detail
595
596 template <int ORDER, class VALUETYPE>
597 void
598SplineImageView<ORDER, VALUETYPE>::calculateIndices(double x, double y) const
599{
600 if(x == x_ && y == y_)
601 return; // still in cache
602
603 if(x > x0_ && x < x1_ && y > y0_ && y < y1_)
604 {
605 detail::SplineImageViewUnrollLoop1<ORDER>::exec(
606 (ORDER % 2) ? int(x - kcenter_) : int(x + 0.5 - kcenter_), ix_);
607 detail::SplineImageViewUnrollLoop1<ORDER>::exec(
608 (ORDER % 2) ? int(y - kcenter_) : int(y + 0.5 - kcenter_), iy_);
609
610 u_ = x - ix_[kcenter_];
611 v_ = y - iy_[kcenter_];
612 }
613 else
614 {
615 vigra_precondition(isValid(x,y),
616 "SplineImageView::calculateIndices(): coordinates out of range.");
617
618 int xCenter = (ORDER % 2) ?
619 (int)VIGRA_CSTD::floor(x) :
620 (int)VIGRA_CSTD::floor(x + 0.5);
621 int yCenter = (ORDER % 2) ?
622 (int)VIGRA_CSTD::floor(y) :
623 (int)VIGRA_CSTD::floor(y + 0.5);
624
625 if(x >= x1_)
626 {
627 for(int i = 0; i < ksize_; ++i)
628 ix_[i] = w1_ - vigra::abs(w1_ - xCenter - (i - kcenter_));
629 }
630 else
631 {
632 for(int i = 0; i < ksize_; ++i)
633 ix_[i] = vigra::abs(xCenter - (kcenter_ - i));
634 }
635 if(y >= y1_)
636 {
637 for(int i = 0; i < ksize_; ++i)
638 iy_[i] = h1_ - vigra::abs(h1_ - yCenter - (i - kcenter_));
639 }
640 else
641 {
642 for(int i = 0; i < ksize_; ++i)
643 iy_[i] = vigra::abs(yCenter - (kcenter_ - i));
644 }
645 u_ = x - xCenter;
646 v_ = y - yCenter;
647 }
648 x_ = x;
649 y_ = y;
650}
651
652 template <int ORDER, class VALUETYPE>
653 void SplineImageView<ORDER, VALUETYPE>::coefficients(double t, double * const & c) const
654{
655 t += kcenter_;
656 for(int i = 0; i<ksize_; ++i)
657 c[i] = k_(t-i);
658}
659
660 template <int ORDER, class VALUETYPE>
661 void SplineImageView<ORDER, VALUETYPE>::derivCoefficients(double t,
662 unsigned int d, double * const & c) const
663{
664 t += kcenter_;
665 for(int i = 0; i<ksize_; ++i)
666 c[i] = k_(t-i, d);
667}
668
669 template <int ORDER, class VALUETYPE>
670VALUETYPE SplineImageView<ORDER, VALUETYPE>::convolve() const
671{
672 typedef typename NumericTraits<VALUETYPE>::RealPromote RealPromote;
673 RealPromote sum;
674 sum = RealPromote(
675 ky_[0]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::exec(kx_, image_.rowBegin(iy_[0]), ix_));
676
677 for(int j=1; j<ksize_; ++j)
678 {
679 sum += RealPromote(
680 ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::exec(kx_, image_.rowBegin(iy_[j]), ix_));
681 }
682 return detail::RequiresExplicitCast<VALUETYPE>::cast(sum);
683}
684
685 template <int ORDER, class VALUETYPE>
686 template <class Array>
687 void
688 SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Array & res) const
689{
690 typedef typename Array::value_type ResType;
691 typename Spline::WeightMatrix const & weights = Spline::weights();
692 ResType tmp[ksize_][ksize_];
693
694 calculateIndices(x, y);
695 for(int j=0; j<ksize_; ++j)
696 {
697 for(int i=0; i<ksize_; ++i)
698 {
699 tmp[i][j] = ResType();
700 for(int k=0; k<ksize_; ++k)
701 {
702 tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]);
703 }
704 }
705 }
706 for(int j=0; j<ksize_; ++j)
707 {
708 for(int i=0; i<ksize_; ++i)
709 {
710 res(i,j) = ResType();
711 for(int k=0; k<ksize_; ++k)
712 {
713 res(i,j) += weights[j][k]*tmp[i][k];
714 }
715 }
716 }
717}
718
719 template <int ORDER, class VALUETYPE>
720 VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y) const
721{
722 calculateIndices(x, y);
723 coefficients(u_, kx_);
724 coefficients(v_, ky_);
725 return convolve();
726}
727
728 template <int ORDER, class VALUETYPE>
729 VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y,
730 unsigned int dx, unsigned int dy) const
731{
732 calculateIndices(x, y);
733 derivCoefficients(u_, dx, kx_);
734 derivCoefficients(v_, dy, ky_);
735 return convolve();
736}
737
738 template <int ORDER, class VALUETYPE>
739 typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
740 SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const
741{
742 return squaredNorm(dx(x,y)) + squaredNorm(dy(x,y));
743}
744
745 template <int ORDER, class VALUETYPE>
746 typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
747 SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const
748{
749 return SquaredNormType(2.0)*(dot(dx(x,y), dxx(x,y)) + dot(dy(x,y), dxy(x,y)));
750}
751
752 template <int ORDER, class VALUETYPE>
753 typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
754 SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const
755{
756 return SquaredNormType(2.0)*(dot(dx(x,y), dxy(x,y)) + dot(dy(x,y), dyy(x,y)));
757}
758
759 template <int ORDER, class VALUETYPE>
760 typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
761 SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const
762{
763 return SquaredNormType(2.0)*(squaredNorm(dxx(x,y)) + dot(dx(x,y), dx3(x,y)) +
764 squaredNorm(dxy(x,y)) + dot(dy(x,y), dxxy(x,y)));
765}
766
767 template <int ORDER, class VALUETYPE>
768 typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
769 SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const
770{
771 return SquaredNormType(2.0)*(squaredNorm(dxy(x,y)) + dot(dx(x,y), dxyy(x,y)) +
772 squaredNorm(dyy(x,y)) + dot(dy(x,y), dy3(x,y)));
773}
774
775 template <int ORDER, class VALUETYPE>
776 typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
777 SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const
778{
779 return SquaredNormType(2.0)*(dot(dx(x,y), dxxy(x,y)) + dot(dy(x,y), dxyy(x,y)) +
780 dot(dxy(x,y), dxx(x,y) + dyy(x,y)));
781}
782
783/********************************************************/
784/* */
785/* SplineImageView0 */
786/* */
787/********************************************************/
788 template <class VALUETYPE, class INTERNAL_INDEXER>
789 class SplineImageView0Base
790{
791 typedef typename INTERNAL_INDEXER::value_type InternalValue;
792 public:
793 typedef VALUETYPE value_type;
794 typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
795 typedef Size2D size_type;
796 typedef TinyVector<double, 2> difference_type;
797 enum StaticOrder { order = 0 };
798
799 public:
800
801 SplineImageView0Base(unsigned int w, unsigned int h)
802 : w_(w), h_(h)
803 {}
804
805 SplineImageView0Base(int w, int h, INTERNAL_INDEXER i)
806 : w_(w), h_(h), internalIndexer_(i)
807 {}
808
809 template <unsigned IntBits1, unsigned FractionalBits1,
810 unsigned IntBits2, unsigned FractionalBits2>
811 value_type unchecked(FixedPoint<IntBits1, FractionalBits1> x,
812 FixedPoint<IntBits2, FractionalBits2> y) const
813 {
814 return internalIndexer_(round(x), round(y));
815 }
816
817 template <unsigned IntBits1, unsigned FractionalBits1,
818 unsigned IntBits2, unsigned FractionalBits2>
819 value_type unchecked(FixedPoint<IntBits1, FractionalBits1> x,
820 FixedPoint<IntBits2, FractionalBits2> y,
821 unsigned int dx, unsigned int dy) const
822 {
823 if((dx != 0) || (dy != 0))
824 return NumericTraits<VALUETYPE>::zero();
825 return unchecked(x, y);
826 }
827
828 value_type unchecked(double x, double y) const
829 {
830 return internalIndexer_((int)(x + 0.5), (int)(y + 0.5));
831 }
832
833 value_type unchecked(double x, double y, unsigned int dx, unsigned int dy) const
834 {
835 if((dx != 0) || (dy != 0))
836 return NumericTraits<VALUETYPE>::zero();
837 return unchecked(x, y);
838 }
839
840 value_type operator()(double x, double y) const
841 {
842 int ix, iy;
843 if(x < 0.0)
844 {
845 ix = (int)(-x + 0.5);
846 vigra_precondition(ix <= (int)w_ - 1,
847 "SplineImageView::operator(): coordinates out of range.");
848 }
849 else
850 {
851 ix = (int)(x + 0.5);
852 if(ix >= (int)w_)
853 {
854 ix = 2*w_-2-ix;
855 vigra_precondition(ix >= 0,
856 "SplineImageView::operator(): coordinates out of range.");
857 }
858 }
859 if(y < 0.0)
860 {
861 iy = (int)(-y + 0.5);
862 vigra_precondition(iy <= (int)h_ - 1,
863 "SplineImageView::operator(): coordinates out of range.");
864 }
865 else
866 {
867 iy = (int)(y + 0.5);
868 if(iy >= (int)h_)
869 {
870 iy = 2*h_-2-iy;
871 vigra_precondition(iy >= 0,
872 "SplineImageView::operator(): coordinates out of range.");
873 }
874 }
875 return internalIndexer_(ix, iy);
876 }
877
878 value_type operator()(double x, double y, unsigned int dx, unsigned int dy) const
879 {
880 if((dx != 0) || (dy != 0))
881 return NumericTraits<VALUETYPE>::zero();
882 return operator()(x, y);
883 }
884
885 value_type dx(double /*x*/, double /*y*/) const
886 { return NumericTraits<VALUETYPE>::zero(); }
887
888 value_type dy(double /*x*/, double /*y*/) const
889 { return NumericTraits<VALUETYPE>::zero(); }
890
891 value_type dxx(double /*x*/, double /*y*/) const
892 { return NumericTraits<VALUETYPE>::zero(); }
893
894 value_type dxy(double /*x*/, double /*y*/) const
895 { return NumericTraits<VALUETYPE>::zero(); }
896
897 value_type dyy(double /*x*/, double /*y*/) const
898 { return NumericTraits<VALUETYPE>::zero(); }
899
900 value_type dx3(double /*x*/, double /*y*/) const
901 { return NumericTraits<VALUETYPE>::zero(); }
902
903 value_type dy3(double /*x*/, double /*y*/) const
904 { return NumericTraits<VALUETYPE>::zero(); }
905
906 value_type dxxy(double /*x*/, double /*y*/) const
907 { return NumericTraits<VALUETYPE>::zero(); }
908
909 value_type dxyy(double /*x*/, double /*y*/) const
910 { return NumericTraits<VALUETYPE>::zero(); }
911
912 value_type operator()(difference_type const & d) const
913 { return operator()(d[0], d[1]); }
914
915 value_type operator()(difference_type const & d, unsigned int dx, unsigned int dy) const
916 { return operator()(d[0], d[1], dx, dy); }
917
918 value_type dx(difference_type const & /*d*/) const
919 { return NumericTraits<VALUETYPE>::zero(); }
920
921 value_type dy(difference_type const & /*d*/) const
922 { return NumericTraits<VALUETYPE>::zero(); }
923
924 value_type dxx(difference_type const & /*d*/) const
925 { return NumericTraits<VALUETYPE>::zero(); }
926
927 value_type dxy(difference_type const & /*d*/) const
928 { return NumericTraits<VALUETYPE>::zero(); }
929
930 value_type dyy(difference_type const & /*d*/) const
931 { return NumericTraits<VALUETYPE>::zero(); }
932
933 value_type dx3(difference_type const & /*d*/) const
934 { return NumericTraits<VALUETYPE>::zero(); }
935
936 value_type dy3(difference_type const & /*d*/) const
937 { return NumericTraits<VALUETYPE>::zero(); }
938
939 value_type dxxy(difference_type const & /*d*/) const
940 { return NumericTraits<VALUETYPE>::zero(); }
941
942 value_type dxyy(difference_type const & /*d*/) const
943 { return NumericTraits<VALUETYPE>::zero(); }
944
945 SquaredNormType g2(double /*x*/, double /*y*/) const
946 { return NumericTraits<SquaredNormType>::zero(); }
947
948 SquaredNormType g2x(double /*x*/, double /*y*/) const
949 { return NumericTraits<SquaredNormType>::zero(); }
950
951 SquaredNormType g2y(double /*x*/, double /*y*/) const
952 { return NumericTraits<SquaredNormType>::zero(); }
953
954 SquaredNormType g2xx(double /*x*/, double /*y*/) const
955 { return NumericTraits<SquaredNormType>::zero(); }
956
957 SquaredNormType g2xy(double /*x*/, double /*y*/) const
958 { return NumericTraits<SquaredNormType>::zero(); }
959
960 SquaredNormType g2yy(double /*x*/, double /*y*/) const
961 { return NumericTraits<SquaredNormType>::zero(); }
962
963 SquaredNormType g2(difference_type const & /*d*/) const
964 { return NumericTraits<SquaredNormType>::zero(); }
965
966 SquaredNormType g2x(difference_type const & /*d*/) const
967 { return NumericTraits<SquaredNormType>::zero(); }
968
969 SquaredNormType g2y(difference_type const & /*d*/) const
970 { return NumericTraits<SquaredNormType>::zero(); }
971
972 SquaredNormType g2xx(difference_type const & /*d*/) const
973 { return NumericTraits<SquaredNormType>::zero(); }
974
975 SquaredNormType g2xy(difference_type const & /*d*/) const
976 { return NumericTraits<SquaredNormType>::zero(); }
977
978 SquaredNormType g2yy(difference_type const & /*d*/) const
979 { return NumericTraits<SquaredNormType>::zero(); }
980
981 unsigned int width() const
982 { return w_; }
983
984 unsigned int height() const
985 { return h_; }
986
987 size_type size() const
988 { return size_type(w_, h_); }
989
990 TinyVector<unsigned int, 2> shape() const
991 { return TinyVector<unsigned int, 2>(w_, h_); }
992
993 template <class Array>
994 void coefficientArray(double x, double y, Array & res) const
995 {
996 res(0, 0) = operator()(x,y);
997 }
998
999 bool isInsideX(double x) const
1000 {
1001 return x >= 0.0 && x <= width() - 1.0;
1002 }
1003
1004 bool isInsideY(double y) const
1005 {
1006 return y >= 0.0 && y <= height() - 1.0;
1007 }
1008
1009 bool isInside(double x, double y) const
1010 {
1011 return isInsideX(x) && isInsideY(y);
1012 }
1013
1014 bool isValid(double x, double y) const
1015 {
1016 return x < 2.0*w_-2.0 && x > 1.0-w_ && y < 2.0*h_-2.0 && y > 1.0-h_;
1017 }
1018
1019 bool sameFacet(double x0, double y0, double x1, double y1) const
1020 {
1021 x0 = VIGRA_CSTD::floor(x0 + 0.5);
1022 y0 = VIGRA_CSTD::floor(y0 + 0.5);
1023 x1 = VIGRA_CSTD::floor(x1 + 0.5);
1024 y1 = VIGRA_CSTD::floor(y1 + 0.5);
1025 return x0 == x1 && y0 == y1;
1026 }
1027
1028 protected:
1029 unsigned int w_, h_;
1030 INTERNAL_INDEXER internalIndexer_;
1031};
1032
1033/** \brief Create an image view for nearest-neighbor interpolation.
1034
1035 This class behaves like \ref vigra::SplineImageView&lt;0, ...&gt;, but one can pass
1036 an additional template argument that determined the internal representation of the image.
1037 If this is equal to the argument type passed in the constructor, the image is not copied.
1038 By default, this works for \ref vigra::BasicImage, \ref vigra::BasicImageView,
1039 \ref vigra::MultiArray&lt;2, ...&gt;, and \ref vigra::MultiArrayView&lt;2, ...&gt;.
1040
1041*/
1042template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<VALUETYPE>::const_traverser>
1043 class SplineImageView0
1044: public SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER>
1045{
1046 typedef SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> Base;
1047 public:
1048 typedef typename Base::value_type value_type;
1049 typedef typename Base::SquaredNormType SquaredNormType;
1050 typedef typename Base::size_type size_type;
1051 typedef typename Base::difference_type difference_type;
1052 enum StaticOrder { order = Base::order };
1053 typedef BasicImage<VALUETYPE> InternalImage;
1054
1055 protected:
1056 typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator InternalTraverser;
1057 typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor InternalAccessor;
1058 typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator InternalConstTraverser;
1059 typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccessor InternalConstAccessor;
1060
1061 public:
1062
1063 /* when traverser and accessor types passed to the constructor are the same as the corresponding
1064 internal types, we need not copy the image (speed up)
1065 */
1066 SplineImageView0(InternalTraverser is, InternalTraverser iend, InternalAccessor /*sa*/)
1067 : Base(iend.x - is.x, iend.y - is.y, is)
1068 {}
1069
1070 SplineImageView0(triple<InternalTraverser, InternalTraverser, InternalAccessor> s)
1071 : Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
1072 {}
1073
1074 SplineImageView0(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor /*sa*/)
1075 : Base(iend.x - is.x, iend.y - is.y, is)
1076 {}
1077
1078 SplineImageView0(triple<InternalConstTraverser, InternalConstTraverser, InternalConstAccessor> s)
1079 : Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
1080 {}
1081
1082 template<class T, class SU>
1083 SplineImageView0(MultiArrayView<2, T, SU> const & i)
1084 : Base(i.shape(0), i.shape(1)),
1085 image_(i.shape(0), i.shape(1))
1086 {
1087 for(unsigned int y=0; y<this->height(); ++y)
1088 for(unsigned int x=0; x<this->width(); ++x)
1089 image_(x,y) = detail::RequiresExplicitCast<VALUETYPE>::cast(i(x,y));
1090 this->internalIndexer_ = image_.upperLeft();
1091 }
1092
1093 template <class SrcIterator, class SrcAccessor>
1094 SplineImageView0(SrcIterator is, SrcIterator iend, SrcAccessor sa)
1095 : Base(iend.x - is.x, iend.y - is.y),
1096 image_(iend - is)
1097 {
1098 copyImage(srcIterRange(is, iend, sa), destImage(image_));
1099 this->internalIndexer_ = image_.upperLeft();
1100 }
1101
1102 template <class SrcIterator, class SrcAccessor>
1103 SplineImageView0(triple<SrcIterator, SrcIterator, SrcAccessor> s)
1104 : Base(s.second.x - s.first.x, s.second.y - s.first.y),
1105 image_(s.second - s.first)
1106 {
1107 copyImage(s, destImage(image_));
1108 this->internalIndexer_ = image_.upperLeft();
1109 }
1110
1111 InternalImage const & image() const
1112 { return image_; }
1113
1114 protected:
1115 InternalImage image_;
1116};
1117
1118 template <class VALUETYPE, class StridedOrUnstrided>
1119 class SplineImageView0<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUnstrided> >
1120: public SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUnstrided> >
1121{
1122 typedef SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUnstrided> > Base;
1123 public:
1124 typedef typename Base::value_type value_type;
1125 typedef typename Base::SquaredNormType SquaredNormType;
1126 typedef typename Base::size_type size_type;
1127 typedef typename Base::difference_type difference_type;
1128 enum StaticOrder { order = Base::order };
1129 typedef BasicImage<VALUETYPE> InternalImage;
1130
1131 protected:
1132 typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexer;
1133
1134 public:
1135
1136 /* when traverser and accessor types passed to the constructor are the same as the corresponding
1137 internal types, we need not copy the image (speed up)
1138 */
1139 SplineImageView0(InternalIndexer const & i)
1140 : Base(i.shape(0), i.shape(1), i)
1141 {}
1142
1143 template<class T, class SU>
1144 SplineImageView0(MultiArrayView<2, T, SU> const & i)
1145 : Base(i.shape(0), i.shape(1)),
1146 image_(i.shape(0), i.shape(1))
1147 {
1148 for(unsigned int y=0; y<this->height(); ++y)
1149 for(unsigned int x=0; x<this->width(); ++x)
1150 image_(x,y) = detail::RequiresExplicitCast<VALUETYPE>::cast(i(x,y));
1151 this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
1152 image_.data());
1153 }
1154
1155 template <class SrcIterator, class SrcAccessor>
1156 SplineImageView0(SrcIterator is, SrcIterator iend, SrcAccessor sa)
1157 : Base(iend.x - is.x, iend.y - is.y),
1158 image_(iend-is)
1159 {
1160 copyImage(srcIterRange(is, iend, sa), destImage(image_));
1161 this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
1162 image_.data());
1163 }
1164
1165 template <class SrcIterator, class SrcAccessor>
1166 SplineImageView0(triple<SrcIterator, SrcIterator, SrcAccessor> s)
1167 : Base(s.second.x - s.first.x, s.second.y - s.first.y),
1168 image_(s.second - s.first)
1169 {
1170 copyImage(s, destImage(image_));
1171 this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
1172 image_.data());
1173 }
1174
1175 InternalImage const & image() const
1176 { return image_; }
1177
1178 protected:
1179 InternalImage image_;
1180};
1181
1182 template <class VALUETYPE>
1183 class SplineImageView<0, VALUETYPE>
1184: public SplineImageView0<VALUETYPE>
1185{
1186 typedef SplineImageView0<VALUETYPE> Base;
1187 public:
1188 typedef typename Base::value_type value_type;
1189 typedef typename Base::SquaredNormType SquaredNormType;
1190 typedef typename Base::size_type size_type;
1191 typedef typename Base::difference_type difference_type;
1192 enum StaticOrder { order = Base::order };
1193 typedef typename Base::InternalImage InternalImage;
1194
1195 protected:
1196 typedef typename Base::InternalTraverser InternalTraverser;
1197 typedef typename Base::InternalAccessor InternalAccessor;
1198 typedef typename Base::InternalConstTraverser InternalConstTraverser;
1199 typedef typename Base::InternalConstAccessor InternalConstAccessor;
1200
1201 public:
1202
1203 /* when traverser and accessor types passed to the constructor are the same as the corresponding
1204 internal types, we need not copy the image (speed up)
1205 */
1206 SplineImageView(InternalTraverser is, InternalTraverser iend, InternalAccessor sa, bool /* unused */ = false)
1207 : Base(is, iend, sa)
1208 {}
1209
1210 SplineImageView(triple<InternalTraverser, InternalTraverser, InternalAccessor> s, bool /* unused */ = false)
1211 : Base(s)
1212 {}
1213
1214 SplineImageView(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor sa, bool /* unused */ = false)
1215 : Base(is, iend, sa)
1216 {}
1217
1218 SplineImageView(triple<InternalConstTraverser, InternalConstTraverser, InternalConstAccessor> s, bool /* unused */ = false)
1219 : Base(s)
1220 {}
1221
1222 template <class SrcIterator, class SrcAccessor>
1223 SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool /* unused */ = false)
1224 : Base(is, iend, sa)
1225 {
1226 copyImage(srcIterRange(is, iend, sa), destImage(this->image_));
1227 }
1228
1229 template <class SrcIterator, class SrcAccessor>
1230 SplineImageView(triple<SrcIterator, SrcIterator, SrcAccessor> s, bool /* unused */ = false)
1231 : Base(s)
1232 {
1233 copyImage(s, destImage(this->image_));
1234 }
1235};
1236
1237/********************************************************/
1238/* */
1239/* SplineImageView1 */
1240/* */
1241/********************************************************/
1242 template <class VALUETYPE, class INTERNAL_INDEXER>
1243 class SplineImageView1Base
1244{
1245 typedef typename INTERNAL_INDEXER::value_type InternalValue;
1246 public:
1247 typedef VALUETYPE value_type;
1248 typedef Size2D size_type;
1249 typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
1250 typedef TinyVector<double, 2> difference_type;
1251 enum StaticOrder { order = 1 };
1252
1253 public:
1254
1255 SplineImageView1Base(unsigned int w, unsigned int h)
1256 : w_(w), h_(h)
1257 {}
1258
1259 SplineImageView1Base(int w, int h, INTERNAL_INDEXER i)
1260 : w_(w), h_(h), internalIndexer_(i)
1261 {}
1262
1263 template <unsigned IntBits1, unsigned FractionalBits1,
1264 unsigned IntBits2, unsigned FractionalBits2>
1265 value_type unchecked(FixedPoint<IntBits1, FractionalBits1> x,
1266 FixedPoint<IntBits2, FractionalBits2> y) const
1267 {
1268 int ix = floor(x);
1269 FixedPoint<0, FractionalBits1> tx = frac(x - FixedPoint<IntBits1, FractionalBits1>(ix));
1270 FixedPoint<0, FractionalBits1> dtx = dual_frac(tx);
1271 if(ix == (int)w_ - 1)
1272 {
1273 --ix;
1274 tx.value = FixedPoint<0, FractionalBits1>::ONE;
1275 dtx.value = 0;
1276 }
1277 int iy = floor(y);
1278 FixedPoint<0, FractionalBits2> ty = frac(y - FixedPoint<IntBits2, FractionalBits2>(iy));
1279 FixedPoint<0, FractionalBits2> dty = dual_frac(ty);
1280 if(iy == (int)h_ - 1)
1281 {
1282 --iy;
1283 ty.value = FixedPoint<0, FractionalBits2>::ONE;
1284 dty.value = 0;
1285 }
1286 return fixed_point_cast<value_type>(
1287 dty*(dtx*fixedPoint(internalIndexer_(ix,iy)) +
1288 tx*fixedPoint(internalIndexer_(ix+1,iy))) +
1289 ty *(dtx*fixedPoint(internalIndexer_(ix,iy+1)) +
1290 tx*fixedPoint(internalIndexer_(ix+1,iy+1))));
1291 }
1292
1293 template <unsigned IntBits1, unsigned FractionalBits1,
1294 unsigned IntBits2, unsigned FractionalBits2>
1295 value_type unchecked(FixedPoint<IntBits1, FractionalBits1> x,
1296 FixedPoint<IntBits2, FractionalBits2> y,
1297 unsigned int dx, unsigned int dy) const
1298 {
1299 int ix = floor(x);
1300 FixedPoint<0, FractionalBits1> tx = frac(x - FixedPoint<IntBits1, FractionalBits1>(ix));
1301 FixedPoint<0, FractionalBits1> dtx = dual_frac(tx);
1302 if(ix == (int)w_ - 1)
1303 {
1304 --ix;
1305 tx.value = FixedPoint<0, FractionalBits1>::ONE;
1306 dtx.value = 0;
1307 }
1308 int iy = floor(y);
1309 FixedPoint<0, FractionalBits2> ty = frac(y - FixedPoint<IntBits2, FractionalBits2>(iy));
1310 FixedPoint<0, FractionalBits2> dty = dual_frac(ty);
1311 if(iy == (int)h_ - 1)
1312 {
1313 --iy;
1314 ty.value = FixedPoint<0, FractionalBits2>::ONE;
1315 dty.value = 0;
1316 }
1317 switch(dx)
1318 {
1319 case 0:
1320 switch(dy)
1321 {
1322 case 0:
1323 return fixed_point_cast<value_type>(
1324 dty*(dtx*fixedPoint(internalIndexer_(ix,iy)) +
1325 tx*fixedPoint(internalIndexer_(ix+1,iy))) +
1326 ty *(dtx*fixedPoint(internalIndexer_(ix,iy+1)) +
1327 tx*fixedPoint(internalIndexer_(ix+1,iy+1))));
1328 case 1:
1329 return fixed_point_cast<value_type>(
1330 (dtx*fixedPoint(internalIndexer_(ix,iy+1)) + tx*fixedPoint(internalIndexer_(ix+1,iy+1))) -
1331 (dtx*fixedPoint(internalIndexer_(ix,iy)) + tx*fixedPoint(internalIndexer_(ix+1,iy))));
1332 default:
1333 return NumericTraits<VALUETYPE>::zero();
1334 }
1335 case 1:
1336 switch(dy)
1337 {
1338 case 0:
1339 return fixed_point_cast<value_type>(
1340 dty*(fixedPoint(internalIndexer_(ix+1,iy)) - fixedPoint(internalIndexer_(ix,iy))) +
1341 ty *(fixedPoint(internalIndexer_(ix+1,iy+1)) - fixedPoint(internalIndexer_(ix,iy+1))));
1342 case 1:
1343 return detail::RequiresExplicitCast<value_type>::cast(
1344 (internalIndexer_(ix+1,iy+1) - internalIndexer_(ix,iy+1)) -
1345 (internalIndexer_(ix+1,iy) - internalIndexer_(ix,iy)));
1346 default:
1347 return NumericTraits<VALUETYPE>::zero();
1348 }
1349 default:
1350 return NumericTraits<VALUETYPE>::zero();
1351 }
1352 }
1353
1354 value_type unchecked(double x, double y) const
1355 {
1356 int ix = (int)std::floor(x);
1357 if(ix == (int)w_ - 1)
1358 --ix;
1359 double tx = x - ix;
1360 int iy = (int)std::floor(y);
1361 if(iy == (int)h_ - 1)
1362 --iy;
1363 double ty = y - iy;
1364 return NumericTraits<value_type>::fromRealPromote(
1365 (1.0-ty)*((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)) +
1366 ty *((1.0-tx)*internalIndexer_(ix,iy+1) + tx*internalIndexer_(ix+1,iy+1)));
1367 }
1368
1369 value_type unchecked(double x, double y, unsigned int dx, unsigned int dy) const
1370 {
1371 int ix = (int)std::floor(x);
1372 if(ix == (int)w_ - 1)
1373 --ix;
1374 double tx = x - ix;
1375 int iy = (int)std::floor(y);
1376 if(iy == (int)h_ - 1)
1377 --iy;
1378 double ty = y - iy;
1379 switch(dx)
1380 {
1381 case 0:
1382 switch(dy)
1383 {
1384 case 0:
1385 return detail::RequiresExplicitCast<value_type>::cast(
1386 (1.0-ty)*((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)) +
1387 ty *((1.0-tx)*internalIndexer_(ix,iy+1) + tx*internalIndexer_(ix+1,iy+1)));
1388 case 1:
1389 return detail::RequiresExplicitCast<value_type>::cast(
1390 ((1.0-tx)*internalIndexer_(ix,iy+1) + tx*internalIndexer_(ix+1,iy+1)) -
1391 ((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)));
1392 default:
1393 return NumericTraits<VALUETYPE>::zero();
1394 }
1395 case 1:
1396 switch(dy)
1397 {
1398 case 0:
1399 return detail::RequiresExplicitCast<value_type>::cast(
1400 (1.0-ty)*(internalIndexer_(ix+1,iy) - internalIndexer_(ix,iy)) +
1401 ty *(internalIndexer_(ix+1,iy+1) - internalIndexer_(ix,iy+1)));
1402 case 1:
1403 return detail::RequiresExplicitCast<value_type>::cast(
1404 (internalIndexer_(ix+1,iy+1) - internalIndexer_(ix,iy+1)) -
1405 (internalIndexer_(ix+1,iy) - internalIndexer_(ix,iy)));
1406 default:
1407 return NumericTraits<VALUETYPE>::zero();
1408 }
1409 default:
1410 return NumericTraits<VALUETYPE>::zero();
1411 }
1412 }
1413
1414 value_type operator()(double x, double y) const
1415 {
1416 return operator()(x, y, 0, 0);
1417 }
1418
1419 value_type operator()(double x, double y, unsigned int dx, unsigned int dy) const
1420 {
1421 value_type mul = NumericTraits<value_type>::one();
1422 if(x < 0.0)
1423 {
1424 x = -x;
1425 vigra_precondition(x <= w_ - 1.0,
1426 "SplineImageView::operator(): coordinates out of range.");
1427 if(dx % 2)
1428 mul = -mul;
1429 }
1430 else if(x > w_ - 1.0)
1431 {
1432 x = 2.0*w_-2.0-x;
1433 vigra_precondition(x >= 0.0,
1434 "SplineImageView::operator(): coordinates out of range.");
1435 if(dx % 2)
1436 mul = -mul;
1437 }
1438 if(y < 0.0)
1439 {
1440 y = -y;
1441 vigra_precondition(y <= h_ - 1.0,
1442 "SplineImageView::operator(): coordinates out of range.");
1443 if(dy % 2)
1444 mul = -mul;
1445 }
1446 else if(y > h_ - 1.0)
1447 {
1448 y = 2.0*h_-2.0-y;
1449 vigra_precondition(y >= 0.0,
1450 "SplineImageView::operator(): coordinates out of range.");
1451 if(dy % 2)
1452 mul = -mul;
1453 }
1454 return mul*unchecked(x, y, dx, dy);
1455 }
1456
1457 value_type dx(double x, double y) const
1458 { return operator()(x, y, 1, 0); }
1459
1460 value_type dy(double x, double y) const
1461 { return operator()(x, y, 0, 1); }
1462
1463 value_type dxx(double /*x*/, double /*y*/) const
1464 { return NumericTraits<VALUETYPE>::zero(); }
1465
1466 value_type dxy(double x, double y) const
1467 { return operator()(x, y, 1, 1); }
1468
1469 value_type dyy(double /*x*/, double /*y*/) const
1470 { return NumericTraits<VALUETYPE>::zero(); }
1471
1472 value_type dx3(double /*x*/, double /*y*/) const
1473 { return NumericTraits<VALUETYPE>::zero(); }
1474
1475 value_type dy3(double /*x*/, double /*y*/) const
1476 { return NumericTraits<VALUETYPE>::zero(); }
1477
1478 value_type dxxy(double /*x*/, double /*y*/) const
1479 { return NumericTraits<VALUETYPE>::zero(); }
1480
1481 value_type dxyy(double /*x*/, double /*y*/) const
1482 { return NumericTraits<VALUETYPE>::zero(); }
1483
1484 value_type operator()(difference_type const & d) const
1485 { return operator()(d[0], d[1]); }
1486
1487 value_type operator()(difference_type const & d, unsigned int dx, unsigned int dy) const
1488 { return operator()(d[0], d[1], dx, dy); }
1489
1490 value_type dx(difference_type const & d) const
1491 { return operator()(d[0], d[1], 1, 0); }
1492
1493 value_type dy(difference_type const & d) const
1494 { return operator()(d[0], d[1], 0, 1); }
1495
1496 value_type dxx(difference_type const & /*d*/) const
1497 { return NumericTraits<VALUETYPE>::zero(); }
1498
1499 value_type dxy(difference_type const & d) const
1500 { return operator()(d[0], d[1], 1, 1); }
1501
1502 value_type dyy(difference_type const & /*d*/) const
1503 { return NumericTraits<VALUETYPE>::zero(); }
1504
1505 value_type dx3(difference_type const & /*d*/) const
1506 { return NumericTraits<VALUETYPE>::zero(); }
1507
1508 value_type dy3(difference_type const & /*d*/) const
1509 { return NumericTraits<VALUETYPE>::zero(); }
1510
1511 value_type dxxy(difference_type const & /*d*/) const
1512 { return NumericTraits<VALUETYPE>::zero(); }
1513
1514 value_type dxyy(difference_type const & /*d*/) const
1515 { return NumericTraits<VALUETYPE>::zero(); }
1516
1517 SquaredNormType g2(double x, double y) const
1518 { return squaredNorm(dx(x,y)) + squaredNorm(dy(x,y)); }
1519
1520 SquaredNormType g2x(double /*x*/, double /*y*/) const
1521 { return NumericTraits<SquaredNormType>::zero(); }
1522
1523 SquaredNormType g2y(double /*x*/, double /*y*/) const
1524 { return NumericTraits<SquaredNormType>::zero(); }
1525
1526 SquaredNormType g2xx(double /*x*/, double /*y*/) const
1527 { return NumericTraits<SquaredNormType>::zero(); }
1528
1529 SquaredNormType g2xy(double /*x*/, double /*y*/) const
1530 { return NumericTraits<SquaredNormType>::zero(); }
1531
1532 SquaredNormType g2yy(double /*x*/, double /*y*/) const
1533 { return NumericTraits<SquaredNormType>::zero(); }
1534
1535 SquaredNormType g2(difference_type const & d) const
1536 { return g2(d[0], d[1]); }
1537
1538 SquaredNormType g2x(difference_type const & /*d*/) const
1539 { return NumericTraits<SquaredNormType>::zero(); }
1540
1541 SquaredNormType g2y(difference_type const & /*d*/) const
1542 { return NumericTraits<SquaredNormType>::zero(); }
1543
1544 SquaredNormType g2xx(difference_type const & /*d*/) const
1545 { return NumericTraits<SquaredNormType>::zero(); }
1546
1547 SquaredNormType g2xy(difference_type const & /*d*/) const
1548 { return NumericTraits<SquaredNormType>::zero(); }
1549
1550 SquaredNormType g2yy(difference_type const & /*d*/) const
1551 { return NumericTraits<SquaredNormType>::zero(); }
1552
1553 unsigned int width() const
1554 { return w_; }
1555
1556 unsigned int height() const
1557 { return h_; }
1558
1559 size_type size() const
1560 { return size_type(w_, h_); }
1561
1562 TinyVector<unsigned int, 2> shape() const
1563 { return TinyVector<unsigned int, 2>(w_, h_); }
1564
1565 template <class Array>
1566 void coefficientArray(double x, double y, Array & res) const;
1567
1568 void calculateIndices(double x, double y, int & ix, int & iy, int & ix1, int & iy1) const;
1569
1570 bool isInsideX(double x) const
1571 {
1572 return x >= 0.0 && x <= width() - 1.0;
1573 }
1574
1575 bool isInsideY(double y) const
1576 {
1577 return y >= 0.0 && y <= height() - 1.0;
1578 }
1579
1580 bool isInside(double x, double y) const
1581 {
1582 return isInsideX(x) && isInsideY(y);
1583 }
1584
1585 bool isValid(double x, double y) const
1586 {
1587 return x < 2.0*w_-2.0 && x > 1.0-w_ && y < 2.0*h_-2.0 && y > 1.0-h_;
1588 }
1589
1590 bool sameFacet(double x0, double y0, double x1, double y1) const
1591 {
1592 x0 = VIGRA_CSTD::floor(x0);
1593 y0 = VIGRA_CSTD::floor(y0);
1594 x1 = VIGRA_CSTD::floor(x1);
1595 y1 = VIGRA_CSTD::floor(y1);
1596 return x0 == x1 && y0 == y1;
1597 }
1598
1599 protected:
1600 unsigned int w_, h_;
1601 INTERNAL_INDEXER internalIndexer_;
1602};
1603
1604 template <class VALUETYPE, class INTERNAL_INDEXER>
1605 template <class Array>
1606 void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::coefficientArray(double x, double y, Array & res) const
1607{
1608 int ix, iy, ix1, iy1;
1609 calculateIndices(x, y, ix, iy, ix1, iy1);
1610 res(0,0) = internalIndexer_(ix,iy);
1611 res(1,0) = internalIndexer_(ix1,iy) - internalIndexer_(ix,iy);
1612 res(0,1) = internalIndexer_(ix,iy1) - internalIndexer_(ix,iy);
1613 res(1,1) = internalIndexer_(ix,iy) - internalIndexer_(ix1,iy) -
1614 internalIndexer_(ix,iy1) + internalIndexer_(ix1,iy1);
1615}
1616
1617 template <class VALUETYPE, class INTERNAL_INDEXER>
1618 void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::calculateIndices(double x, double y, int & ix, int & iy, int & ix1, int & iy1) const
1619{
1620 if(x < 0.0)
1621 {
1622 x = -x;
1623 vigra_precondition(x <= w_ - 1.0,
1624 "SplineImageView::calculateIndices(): coordinates out of range.");
1625 ix = (int)VIGRA_CSTD::ceil(x);
1626 ix1 = ix - 1;
1627 }
1628 else if(x >= w_ - 1.0)
1629 {
1630 x = 2.0*w_-2.0-x;
1631 vigra_precondition(x > 0.0,
1632 "SplineImageView::calculateIndices(): coordinates out of range.");
1633 ix = (int)VIGRA_CSTD::ceil(x);
1634 ix1 = ix - 1;
1635 }
1636 else
1637 {
1638 ix = (int)VIGRA_CSTD::floor(x);
1639 ix1 = ix + 1;
1640 }
1641 if(y < 0.0)
1642 {
1643 y = -y;
1644 vigra_precondition(y <= h_ - 1.0,
1645 "SplineImageView::calculateIndices(): coordinates out of range.");
1646 iy = (int)VIGRA_CSTD::ceil(y);
1647 iy1 = iy - 1;
1648 }
1649 else if(y >= h_ - 1.0)
1650 {
1651 y = 2.0*h_-2.0-y;
1652 vigra_precondition(y > 0.0,
1653 "SplineImageView::calculateIndices(): coordinates out of range.");
1654 iy = (int)VIGRA_CSTD::ceil(y);
1655 iy1 = iy - 1;
1656 }
1657 else
1658 {
1659 iy = (int)VIGRA_CSTD::floor(y);
1660 iy1 = iy + 1;
1661 }
1662}
1663
1664/** \brief Create an image view for bi-linear interpolation.
1665
1666 This class behaves like \ref vigra::SplineImageView&lt;1, ...&gt;, but one can pass
1667 an additional template argument that determined the internal representation of the image.
1668 If this is equal to the argument type passed in the constructor, the image is not copied.
1669 By default, this works for \ref vigra::BasicImage, \ref vigra::BasicImageView,
1670 \ref vigra::MultiArray&lt;2, ...&gt;, and \ref vigra::MultiArrayView&lt;2, ...&gt;.
1671
1672 In addition to the function provided by \ref vigra::SplineImageView, there are functions
1673 <tt>unchecked(x,y)</tt> and <tt>unchecked(x,y, xorder, yorder)</tt> which improve speed by
1674 not applying bounds checking and reflective border treatment (<tt>isInside(x, y)</tt> must
1675 be <tt>true</tt>), but otherwise behave identically to their checked counterparts.
1676 In addition, <tt>x</tt> and <tt>y</tt> can have type \ref vigra::FixedPoint instead of
1677 <tt>double</tt>.
1678*/
1679template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<VALUETYPE>::const_traverser>
1680 class SplineImageView1
1681: public SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER>
1682{
1683 typedef SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> Base;
1684 public:
1685 typedef typename Base::value_type value_type;
1686 typedef typename Base::SquaredNormType SquaredNormType;
1687 typedef typename Base::size_type size_type;
1688 typedef typename Base::difference_type difference_type;
1689 enum StaticOrder { order = Base::order };
1690 typedef BasicImage<VALUETYPE> InternalImage;
1691
1692 protected:
1693 typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator InternalTraverser;
1694 typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor InternalAccessor;
1695 typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator InternalConstTraverser;
1696 typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccessor InternalConstAccessor;
1697
1698 public:
1699
1700 /* when traverser and accessor types passed to the constructor are the same as the corresponding
1701 internal types, we need not copy the image (speed up)
1702 */
1703 SplineImageView1(InternalTraverser is, InternalTraverser iend, InternalAccessor /*sa*/)
1704 : Base(iend.x - is.x, iend.y - is.y, is)
1705 {}
1706
1707 SplineImageView1(triple<InternalTraverser, InternalTraverser, InternalAccessor> s)
1708 : Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
1709 {}
1710
1711 SplineImageView1(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor /*sa*/)
1712 : Base(iend.x - is.x, iend.y - is.y, is)
1713 {}
1714
1715 SplineImageView1(triple<InternalConstTraverser, InternalConstTraverser, InternalConstAccessor> s)
1716 : Base(s.second.x - s.first.x, s.second.y - s.first.y, s.first)
1717 {}
1718
1719 template<class T, class SU>
1720 SplineImageView1(MultiArrayView<2, T, SU> const & i)
1721 : Base(i.shape(0), i.shape(1)),
1722 image_(i.shape(0), i.shape(1))
1723 {
1724 for(unsigned int y=0; y<this->height(); ++y)
1725 for(unsigned int x=0; x<this->width(); ++x)
1726 image_(x,y) = detail::RequiresExplicitCast<VALUETYPE>::cast(i(x,y));
1727 this->internalIndexer_ = image_.upperLeft();
1728 }
1729
1730 template <class SrcIterator, class SrcAccessor>
1731 SplineImageView1(SrcIterator is, SrcIterator iend, SrcAccessor sa)
1732 : Base(iend.x - is.x, iend.y - is.y),
1733 image_(iend - is)
1734 {
1735 copyImage(srcIterRange(is, iend, sa), destImage(image_));
1736 this->internalIndexer_ = image_.upperLeft();
1737 }
1738
1739 template <class SrcIterator, class SrcAccessor>
1740 SplineImageView1(triple<SrcIterator, SrcIterator, SrcAccessor> s)
1741 : Base(s.second.x - s.first.x, s.second.y - s.first.y),
1742 image_(s.second - s.first)
1743 {
1744 copyImage(s, destImage(image_));
1745 this->internalIndexer_ = image_.upperLeft();
1746 }
1747
1748 InternalImage const & image() const
1749 { return image_; }
1750
1751 protected:
1752 InternalImage image_;
1753};
1754
1755 template <class VALUETYPE, class StridedOrUnstrided>
1756 class SplineImageView1<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUnstrided> >
1757: public SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUnstrided> >
1758{
1759 typedef SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUnstrided> > Base;
1760 public:
1761 typedef typename Base::value_type value_type;
1762 typedef typename Base::SquaredNormType SquaredNormType;
1763 typedef typename Base::size_type size_type;
1764 typedef typename Base::difference_type difference_type;
1765 enum StaticOrder { order = Base::order };
1766 typedef BasicImage<VALUETYPE> InternalImage;
1767
1768 protected:
1769 typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexer;
1770
1771 public:
1772
1773 /* when traverser and accessor types passed to the constructor are the same as the corresponding
1774 internal types, we need not copy the image (speed up)
1775 */
1776 SplineImageView1(InternalIndexer const & i)
1777 : Base(i.shape(0), i.shape(1), i)
1778 {}
1779
1780 template<class T, class SU>
1781 SplineImageView1(MultiArrayView<2, T, SU> const & i)
1782 : Base(i.shape(0), i.shape(1)),
1783 image_(i.shape(0), i.shape(1))
1784 {
1785 copyImage(srcImageRange(i), destImage(image_));
1786 // for(unsigned int y=0; y<this->height(); ++y)
1787 // for(unsigned int x=0; x<this->width(); ++x)
1788 // image_(x,y) = detail::RequiresExplicitCast<VALUETYPE>::cast(i(x,y));
1789 this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
1790 image_.data());
1791 }
1792
1793 template <class SrcIterator, class SrcAccessor>
1794 SplineImageView1(SrcIterator is, SrcIterator iend, SrcAccessor sa)
1795 : Base(iend.x - is.x, iend.y - is.y),
1796 image_(iend-is)
1797 {
1798 copyImage(srcIterRange(is, iend, sa), destImage(image_));
1799 this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
1800 image_.data());
1801 }
1802
1803 template <class SrcIterator, class SrcAccessor>
1804 SplineImageView1(triple<SrcIterator, SrcIterator, SrcAccessor> s)
1805 : Base(s.second.x - s.first.x, s.second.y - s.first.y),
1806 image_(s.second - s.first)
1807 {
1808 copyImage(s, destImage(image_));
1809 this->internalIndexer_ = InternalIndexer(typename InternalIndexer::difference_type(this->width(), this->height()),
1810 image_.data());
1811 }
1812
1813 InternalImage const & image() const
1814 { return image_; }
1815
1816 protected:
1817 InternalImage image_;
1818};
1819
1820 template <class VALUETYPE>
1821 class SplineImageView<1, VALUETYPE>
1822: public SplineImageView1<VALUETYPE>
1823{
1824 typedef SplineImageView1<VALUETYPE> Base;
1825 public:
1826 typedef typename Base::value_type value_type;
1827 typedef typename Base::SquaredNormType SquaredNormType;
1828 typedef typename Base::size_type size_type;
1829 typedef typename Base::difference_type difference_type;
1830 enum StaticOrder { order = Base::order };
1831 typedef typename Base::InternalImage InternalImage;
1832
1833 protected:
1834 typedef typename Base::InternalTraverser InternalTraverser;
1835 typedef typename Base::InternalAccessor InternalAccessor;
1836 typedef typename Base::InternalConstTraverser InternalConstTraverser;
1837 typedef typename Base::InternalConstAccessor InternalConstAccessor;
1838
1839 public:
1840
1841 /* when traverser and accessor types passed to the constructor are the same as the corresponding
1842 internal types, we need not copy the image (speed up)
1843 */
1844 SplineImageView(InternalTraverser is, InternalTraverser iend, InternalAccessor sa, bool /* unused */ = false)
1845 : Base(is, iend, sa)
1846 {}
1847
1848 SplineImageView(triple<InternalTraverser, InternalTraverser, InternalAccessor> s, bool /* unused */ = false)
1849 : Base(s)
1850 {}
1851
1852 SplineImageView(InternalConstTraverser is, InternalConstTraverser iend, InternalConstAccessor sa, bool /* unused */ = false)
1853 : Base(is, iend, sa)
1854 {}
1855
1856 SplineImageView(triple<InternalConstTraverser, InternalConstTraverser, InternalConstAccessor> s, bool /* unused */ = false)
1857 : Base(s)
1858 {}
1859
1860 template <class SrcIterator, class SrcAccessor>
1861 SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool /* unused */ = false)
1862 : Base(is, iend, sa)
1863 {
1864 copyImage(srcIterRange(is, iend, sa), destImage(this->image_));
1865 }
1866
1867 template <class SrcIterator, class SrcAccessor>
1868 SplineImageView(triple<SrcIterator, SrcIterator, SrcAccessor> s, bool /* unused */ = false)
1869 : Base(s)
1870 {
1871 copyImage(s, destImage(this->image_));
1872 }
1873
1874 template<class T, class SU>
1875 SplineImageView(MultiArrayView<2, T, SU> const & i, bool /* unused */ = false)
1876 : Base(i)
1877 {}
1878};
1879
1880} // namespace vigra
1881
1882
1883#endif /* VIGRA_SPLINEIMAGEVIEW_HXX */
vigra::BSpline< ORDER, double >
vigra::BasicImage< InternalValue >
vigra::BasicImage::data
const_pointer data() const
Definition basicimage.hxx:1059
vigra::BasicImage::upperLeft
traverser upperLeft()
Definition basicimage.hxx:925
vigra::MultiArrayView
Base class for, and view to, vigra::MultiArray.
Definition multi_array.hxx:705
vigra::RGBValue
Class for a single RGB value.
Definition rgbvalue.hxx:128
vigra::RGBValue::RGBValue
RGBValue()
Definition rgbvalue.hxx:209
vigra::RGBValue::value_type
Base::value_type value_type
Definition rgbvalue.hxx:141
vigra::RGBValue::SquaredNormType
Base::SquaredNormType SquaredNormType
Definition rgbvalue.hxx:150
vigra::Size2D
Two dimensional size object.
Definition diff2d.hxx:483
vigra::SplineImageView0
Create an image view for nearest-neighbor interpolation.
Definition splineimageview.hxx:1045
vigra::SplineImageView1
Create an image view for bi-linear interpolation.
Definition splineimageview.hxx:1682
vigra::SplineImageView
Create a continuous view onto a discrete image using splines.
Definition splineimageview.hxx:100
vigra::SplineImageView::dy3
value_type dy3(double x, double y) const
Definition splineimageview.hxx:253
vigra::SplineImageView::dx
value_type dx(double x, double y) const
Definition splineimageview.hxx:217
vigra::SplineImageView::dyy
value_type dyy(difference_type const &d) const
Definition splineimageview.hxx:307
vigra::SplineImageView::g2
SquaredNormType g2(double x, double y) const
Definition splineimageview.hxx:740
vigra::SplineImageView::operator()
value_type operator()(difference_type const &d, unsigned int dx, unsigned int dy) const
Definition splineimageview.hxx:277
vigra::SplineImageView::isInside
bool isInside(double x, double y) const
Definition splineimageview.hxx:488
vigra::SplineImageView::isInsideY
bool isInsideY(double y) const
Definition splineimageview.hxx:480
vigra::SplineImageView::g2y
SquaredNormType g2y(double x, double y) const
Definition splineimageview.hxx:754
vigra::SplineImageView::SplineImageView
SplineImageView(triple< SrcIterator, SrcIterator, SrcAccessor > s, bool skipPrefiltering=false)
Definition splineimageview.hxx:188
vigra::SplineImageView::dy3
value_type dy3(difference_type const &d) const
Definition splineimageview.hxx:319
vigra::SplineImageView::g2xx
SquaredNormType g2xx(double x, double y) const
Definition splineimageview.hxx:761
vigra::SplineImageView::g2xx
SquaredNormType g2xx(difference_type const &d) const
Definition splineimageview.hxx:383
vigra::SplineImageView::g2xy
SquaredNormType g2xy(double x, double y) const
Definition splineimageview.hxx:777
vigra::SplineImageView::dxx
value_type dxx(double x, double y) const
Definition splineimageview.hxx:229
vigra::SplineImageView::operator()
value_type operator()(double x, double y) const
Definition splineimageview.hxx:720
vigra::SplineImageView::operator()
value_type operator()(difference_type const &d) const
Definition splineimageview.hxx:271
vigra::SplineImageView::isInsideX
bool isInsideX(double x) const
Definition splineimageview.hxx:472
vigra::SplineImageView::InternalImage
BasicImage< InternalValue > InternalImage
Definition splineimageview.hxx:127
vigra::SplineImageView::dxy
value_type dxy(double x, double y) const
Definition splineimageview.hxx:235
vigra::SplineImageView::g2y
SquaredNormType g2y(difference_type const &d) const
Definition splineimageview.hxx:377
vigra::SplineImageView::size
size_type size() const
Definition splineimageview.hxx:414
vigra::SplineImageView::dx3
value_type dx3(double x, double y) const
Definition splineimageview.hxx:247
vigra::SplineImageView::SquaredNormType
NormTraits< VALUETYPE >::SquaredNormType SquaredNormType
Definition splineimageview.hxx:111
vigra::SplineImageView::shape
TinyVector< unsigned int, 2 > shape() const
Definition splineimageview.hxx:420
vigra::SplineImageView::g2yy
SquaredNormType g2yy(double x, double y) const
Definition splineimageview.hxx:769
vigra::SplineImageView::size_type
Size2D size_type
Definition splineimageview.hxx:115
vigra::SplineImageView::isValid
bool isValid(double x, double y) const
Definition splineimageview.hxx:498
vigra::SplineImageView::dy
value_type dy(double x, double y) const
Definition splineimageview.hxx:223
vigra::SplineImageView::width
unsigned int width() const
Definition splineimageview.hxx:401
vigra::SplineImageView::g2
SquaredNormType g2(difference_type const &d) const
Definition splineimageview.hxx:365
vigra::SplineImageView::dxxy
value_type dxxy(difference_type const &d) const
Definition splineimageview.hxx:325
vigra::SplineImageView::image
InternalImage const & image() const
Definition splineimageview.hxx:425
vigra::SplineImageView::g2xy
SquaredNormType g2xy(difference_type const &d) const
Definition splineimageview.hxx:389
vigra::SplineImageView::sameFacet
bool sameFacet(double x0, double y0, double x1, double y1) const
Definition splineimageview.hxx:510
vigra::SplineImageView::dyy
value_type dyy(double x, double y) const
Definition splineimageview.hxx:241
vigra::SplineImageView::g2x
SquaredNormType g2x(difference_type const &d) const
Definition splineimageview.hxx:371
vigra::SplineImageView::dxx
value_type dxx(difference_type const &d) const
Definition splineimageview.hxx:295
vigra::SplineImageView::dxyy
value_type dxyy(difference_type const &d) const
Definition splineimageview.hxx:331
vigra::SplineImageView::dxyy
value_type dxyy(double x, double y) const
Definition splineimageview.hxx:265
vigra::SplineImageView::order
static constexpr int order
Definition splineimageview.hxx:123
vigra::SplineImageView::value_type
VALUETYPE value_type
Definition splineimageview.hxx:107
vigra::SplineImageView::g2yy
SquaredNormType g2yy(difference_type const &d) const
Definition splineimageview.hxx:395
vigra::SplineImageView::height
unsigned int height() const
Definition splineimageview.hxx:407
vigra::SplineImageView::coefficientArray
void coefficientArray(double x, double y, Array &res) const
Definition splineimageview.hxx:688
vigra::SplineImageView::dx
value_type dx(difference_type const &d) const
Definition splineimageview.hxx:283
vigra::SplineImageView::difference_type
TinyVector< double, 2 > difference_type
Definition splineimageview.hxx:119
vigra::SplineImageView::dxy
value_type dxy(difference_type const &d) const
Definition splineimageview.hxx:301
vigra::SplineImageView::dy
value_type dy(difference_type const &d) const
Definition splineimageview.hxx:289
vigra::SplineImageView::SplineImageView
SplineImageView(MultiArrayView< 2, U, S > const &s, bool skipPrefiltering=false)
Definition splineimageview.hxx:148
vigra::SplineImageView::dx3
value_type dx3(difference_type const &d) const
Definition splineimageview.hxx:313
vigra::SplineImageView::SplineImageView
SplineImageView(SrcIterator is, SrcIterator iend, SrcAccessor sa, bool skipPrefiltering=false)
Definition splineimageview.hxx:168
vigra::SplineImageView::dxxy
value_type dxxy(double x, double y) const
Definition splineimageview.hxx:259
vigra::SplineImageView::g2x
SquaredNormType g2x(double x, double y) const
Definition splineimageview.hxx:747
vigra::TinyVector< double, 2 >
vigra
vigra::floor
int floor(FixedPoint< IntBits, FracBits > v)
rounding down.
Definition fixedpoint.hxx:667
vigra::dual_frac
FixedPoint< 0, FracBits > dual_frac(FixedPoint< IntBits, FracBits > v)
dual fractional part: 1 - frac(v).
Definition fixedpoint.hxx:658
vigra::round
int round(FixedPoint< IntBits, FracBits > v)
rounding to the nearest integer.
Definition fixedpoint.hxx:683
vigra::mul
void mul(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
multiplication with enforced result type.
Definition fixedpoint.hxx:605
vigra::recursiveFilterY
void recursiveFilterY(...)
Performs 1 dimensional recursive filtering (1st and 2nd order) in y direction.
vigra::sum
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition tinyvector.hxx:2073
vigra::recursiveFilterX
void recursiveFilterX(...)
Performs 1 dimensional recursive filtering (1st and 2nd order) in x direction.
vigra::squaredNorm
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition fftw3.hxx:1044
vigra::frac
FixedPoint< 0, FracBits > frac(FixedPoint< IntBits, FracBits > v)
fractional part.
Definition fixedpoint.hxx:650
vigra::copyImage
void copyImage(...)
Copy source image into destination image.
vigra::IteratorTraits
Export associated information for each image iterator.
Definition iteratortraits.hxx:110

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.12.2