37 #ifndef VIGRA_RESIZEIMAGE_HXX
38 #define VIGRA_RESIZEIMAGE_HXX
42 #include "numerictraits.hxx"
43 #include "stdimage.hxx"
44 #include "recursiveconvolution.hxx"
45 #include "separableconvolution.hxx"
46 #include "resampling_convolution.hxx"
47 #include "splines.hxx"
48 #include "multi_shape.hxx"
134 return prefilterCoefficients_;
144 ArrayVector<double> CoscotFunction<T>::prefilterCoefficients_;
170 template <
class SrcIterator,
class SrcAccessor,
171 class DestIterator,
class DestAccessor>
173 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
174 DestIterator
id, DestIterator idend, DestAccessor ad)
176 int wold = iend - i1;
177 int wnew = idend - id;
185 double dx = (double)(wold - 1) / (wnew - 1);
187 for(;
id != idend; ++id, x += dx)
190 ad.set(as(i1, ix),
id);
286 template <
class SrcIterator,
class SrcAccessor,
287 class DestIterator,
class DestAccessor>
290 DestIterator
id, DestIterator idend, DestAccessor da)
292 int w = iend.x - is.x;
293 int h = iend.y - is.y;
295 int wnew = idend.x -
id.x;
296 int hnew = idend.y -
id.y;
298 vigra_precondition((w > 1) && (h > 1),
299 "resizeImageNoInterpolation(): "
300 "Source image too small.\n");
301 vigra_precondition((wnew > 1) && (hnew > 1),
302 "resizeImageNoInterpolation(): "
303 "Destination image too small.\n");
305 typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
306 typedef typename TmpImage::traverser TmpImageIterator;
308 TmpImage tmp(w, hnew);
310 TmpImageIterator yt = tmp.upperLeft();
312 for(
int x=0; x<w; ++x, ++is.x, ++yt.x)
314 typename SrcIterator::column_iterator c1 = is.columnIterator();
315 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
317 resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
320 yt = tmp.upperLeft();
322 for(
int y=0; y < hnew; ++y, ++yt.y, ++
id.y)
324 typename DestIterator::row_iterator rd =
id.rowIterator();
325 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
327 resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
331 template <
class SrcIterator,
class SrcAccessor,
332 class DestIterator,
class DestAccessor>
335 triple<DestIterator, DestIterator, DestAccessor> dest)
338 dest.first, dest.second, dest.third);
341 template <
class T1,
class S1,
345 MultiArrayView<2, T2, S2> dest)
348 destImageRange(dest));
357 template <
class SrcIterator,
class SrcAccessor,
358 class DestIterator,
class DestAccessor>
360 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
361 DestIterator
id, DestIterator idend, DestAccessor ad)
363 int wold = iend - i1;
364 int wnew = idend - id;
366 if((wold <= 1) || (wnew <= 1))
return;
369 NumericTraits<typename DestAccessor::value_type> DestTraits;
370 typedef typename DestTraits::RealPromote RealPromote;
372 ad.set(DestTraits::fromRealPromote(as(i1)),
id);
376 ad.set(DestTraits::fromRealPromote(as(iend)), idend);
378 double dx = (double)(wold - 1) / (wnew - 1);
381 for(;
id != idend; ++id, x += dx)
391 ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as(i1, 1))),
id);
501 template <
class SrcIterator,
class SrcAccessor,
502 class DestIterator,
class DestAccessor>
505 DestIterator
id, DestIterator idend, DestAccessor da)
507 int w = iend.x - is.x;
508 int h = iend.y - is.y;
510 int wnew = idend.x -
id.x;
511 int hnew = idend.y -
id.y;
513 vigra_precondition((w > 1) && (h > 1),
514 "resizeImageLinearInterpolation(): "
515 "Source image too small.\n");
516 vigra_precondition((wnew > 1) && (hnew > 1),
517 "resizeImageLinearInterpolation(): "
518 "Destination image too small.\n");
520 double const scale = 2.0;
522 typedef typename SrcAccessor::value_type SRCVT;
523 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
524 typedef BasicImage<TMPTYPE> TmpImage;
525 typedef typename TmpImage::traverser TmpImageIterator;
527 BasicImage<TMPTYPE> tmp(w, hnew);
528 BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
532 typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
533 typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
535 for(x=0; x<w; ++x, ++is.x, ++yt.x)
537 typename SrcIterator::column_iterator c1 = is.columnIterator();
538 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
543 lt, line.accessor(), (double)h/hnew/scale);
545 resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
546 ct, ct + hnew, tmp.accessor());
550 resizeLineLinearInterpolation(c1, c1 + h, sa,
551 ct, ct + hnew, tmp.accessor());
555 yt = tmp.upperLeft();
557 for(y=0; y < hnew; ++y, ++yt.y, ++
id.y)
559 typename DestIterator::row_iterator rd =
id.rowIterator();
560 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
565 lt, line.accessor(), (double)w/wnew/scale);
567 resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
572 resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
578 template <
class SrcIterator,
class SrcAccessor,
579 class DestIterator,
class DestAccessor>
582 triple<DestIterator, DestIterator, DestAccessor> dest)
585 dest.first, dest.second, dest.third);
588 template <
class T1,
class S1,
592 MultiArrayView<2, T2, S2> dest)
595 destImageRange(dest));
732 template <
class SrcIterator,
class SrcAccessor,
733 class DestIterator,
class DestAccessor,
737 SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
738 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
739 SPLINE
const & spline)
742 int width_old = src_iter_end.x - src_iter.x;
743 int height_old = src_iter_end.y - src_iter.y;
745 int width_new = dest_iter_end.x - dest_iter.x;
746 int height_new = dest_iter_end.y - dest_iter.y;
748 vigra_precondition((width_old > 1) && (height_old > 1),
749 "resizeImageSplineInterpolation(): "
750 "Source image too small.\n");
752 vigra_precondition((width_new > 1) && (height_new > 1),
753 "resizeImageSplineInterpolation(): "
754 "Destination image too small.\n");
756 Rational<int> xratio(width_new - 1, width_old - 1);
757 Rational<int> yratio(height_new - 1, height_old - 1);
758 Rational<int> offset(0);
759 resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
760 resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
761 int xperiod =
lcm(xratio.numerator(), xratio.denominator());
762 int yperiod =
lcm(yratio.numerator(), yratio.denominator());
764 double const scale = 2.0;
766 typedef typename SrcAccessor::value_type SRCVT;
767 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
768 typedef BasicImage<TMPTYPE> TmpImage;
769 typedef typename TmpImage::traverser TmpImageIterator;
771 BasicImage<TMPTYPE> tmp(width_old, height_new);
773 BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
774 typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
775 ArrayVector<double>
const & prefilterCoeffs = spline.prefilterCoefficients();
779 ArrayVector<Kernel1D<double> > kernels(yperiod);
780 createResamplingKernels(spline, ymapCoordinate, kernels);
782 typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
783 typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
785 for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
788 typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
789 typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
791 if(prefilterCoeffs.size() == 0)
793 if(height_new >= height_old)
796 c_tmp, c_tmp + height_new, tmp_acc,
797 kernels, ymapCoordinate);
802 line_tmp, line.accessor(), (double)height_old/height_new/scale);
804 c_tmp, c_tmp + height_new, tmp_acc,
805 kernels, ymapCoordinate);
811 line_tmp, line.accessor(),
812 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
813 for(
unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
816 line_tmp, line.accessor(),
817 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
819 if(height_new < height_old)
822 line_tmp, line.accessor(), (double)height_old/height_new/scale);
825 c_tmp, c_tmp + height_new, tmp_acc,
826 kernels, ymapCoordinate);
830 y_tmp = tmp.upperLeft();
832 kernels.resize(xperiod);
833 createResamplingKernels(spline, xmapCoordinate, kernels);
835 for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
837 typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
838 typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
840 if(prefilterCoeffs.size() == 0)
842 if(width_new >= width_old)
845 r_dest, r_dest + width_new, dest_acc,
846 kernels, xmapCoordinate);
851 line_tmp, line.accessor(), (double)width_old/width_new/scale);
853 r_dest, r_dest + width_new, dest_acc,
854 kernels, xmapCoordinate);
860 line_tmp, line.accessor(),
861 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
862 for(
unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
865 line_tmp, line.accessor(),
866 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
868 if(width_new < width_old)
871 line_tmp, line.accessor(), (double)width_old/width_new/scale);
874 r_dest, r_dest + width_new, dest_acc,
875 kernels, xmapCoordinate);
880 template <
class SrcIterator,
class SrcAccessor,
881 class DestIterator,
class DestAccessor>
884 DestIterator
id, DestIterator idend, DestAccessor da)
889 template <
class SrcIterator,
class SrcAccessor,
890 class DestIterator,
class DestAccessor,
894 triple<DestIterator, DestIterator, DestAccessor> dest,
895 SPLINE
const & spline)
898 dest.first, dest.second, dest.third, spline);
901 template <
class SrcIterator,
class SrcAccessor,
902 class DestIterator,
class DestAccessor>
905 triple<DestIterator, DestIterator, DestAccessor> dest)
908 dest.first, dest.second, dest.third);
911 template <
class T1,
class S1,
916 MultiArrayView<2, T2, S2> dest,
917 SPLINE
const & spline)
920 destImageRange(dest), spline);
923 template <
class T1,
class S1,
927 MultiArrayView<2, T2, S2> dest)
930 destImageRange(dest));
994 template <
class SrcIterator,
class SrcAccessor,
995 class DestIterator,
class DestAccessor>
998 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
1001 CatmullRomSpline<double>());
1004 template <
class SrcIterator,
class SrcAccessor,
1005 class DestIterator,
class DestAccessor>
1008 triple<DestIterator, DestIterator, DestAccessor> dest)
1011 dest.first, dest.second, dest.third);
1014 template <
class T1,
class S1,
1018 MultiArrayView<2, T2, S2> dest)
1021 destImageRange(dest));
1086 template <
class SrcIterator,
class SrcAccessor,
1087 class DestIterator,
class DestAccessor>
1090 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
1093 CoscotFunction<double>());
1096 template <
class SrcIterator,
class SrcAccessor,
1097 class DestIterator,
class DestAccessor>
1100 triple<DestIterator, DestIterator, DestAccessor> dest)
1103 dest.first, dest.second, dest.third);
1106 template <
class T1,
class S1,
1110 MultiArrayView<2, T2, S2> dest)
1113 destImageRange(dest));
1120 #endif // VIGRA_RESIZEIMAGE_HXX
Definition: resizeimage.hxx:82
result_type operator()(argument_type x) const
Definition: resizeimage.hxx:103
linalg::TemporaryMatrix< T > sin(MultiArrayView< 2, T, C > const &v)
void recursiveSmoothLine(...)
Convolves the image with a 1-dimensional exponential filter.
double radius() const
Definition: resizeimage.hxx:121
unsigned int derivativeOrder() const
Definition: resizeimage.hxx:126
T argument_type
Definition: resizeimage.hxx:91
value_type operator[](value_type x) const
Definition: resizeimage.hxx:115
void recursiveFilterLine(...)
Performs a 1-dimensional recursive convolution of the source signal.
IntType lcm(IntType n, IntType m)
Definition: rational.hxx:122
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
T result_type
Definition: resizeimage.hxx:94
T value_type
Definition: resizeimage.hxx:88
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
ArrayVector< double > const & prefilterCoefficients() const
Definition: resizeimage.hxx:132
linalg::TemporaryMatrix< T > tan(MultiArrayView< 2, T, C > const &v)
linalg::TemporaryMatrix< T > cos(MultiArrayView< 2, T, C > const &v)
void resamplingConvolveLine(...)
Performs a 1-dimensional resampling convolution of the source signal using the given set of kernels...