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_;
158 template <
class SrcIterator,
class SrcAccessor,
159 class DestIterator,
class DestAccessor>
161 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
162 DestIterator
id, DestIterator idend, DestAccessor ad)
164 int wold = iend - i1;
165 int wnew = idend - id;
173 double dx = (double)(wold - 1) / (wnew - 1);
175 for(;
id != idend; ++id, x += dx)
178 ad.set(as(i1, ix),
id);
274 template <
class SrcIterator,
class SrcAccessor,
275 class DestIterator,
class DestAccessor>
278 DestIterator
id, DestIterator idend, DestAccessor da)
280 int w = iend.x - is.x;
281 int h = iend.y - is.y;
283 int wnew = idend.x -
id.x;
284 int hnew = idend.y -
id.y;
286 vigra_precondition((w > 1) && (h > 1),
287 "resizeImageNoInterpolation(): "
288 "Source image too small.\n");
289 vigra_precondition((wnew > 1) && (hnew > 1),
290 "resizeImageNoInterpolation(): "
291 "Destination image too small.\n");
293 typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
294 typedef typename TmpImage::traverser TmpImageIterator;
296 TmpImage tmp(w, hnew);
298 TmpImageIterator yt = tmp.upperLeft();
300 for(
int x=0; x<w; ++x, ++is.x, ++yt.x)
302 typename SrcIterator::column_iterator c1 = is.columnIterator();
303 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
305 resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
308 yt = tmp.upperLeft();
310 for(
int y=0; y < hnew; ++y, ++yt.y, ++
id.y)
312 typename DestIterator::row_iterator rd =
id.rowIterator();
313 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
315 resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
319 template <
class SrcIterator,
class SrcAccessor,
320 class DestIterator,
class DestAccessor>
323 triple<DestIterator, DestIterator, DestAccessor> dest)
326 dest.first, dest.second, dest.third);
329 template <
class T1,
class S1,
333 MultiArrayView<2, T2, S2> dest)
336 destImageRange(dest));
345 template <
class SrcIterator,
class SrcAccessor,
346 class DestIterator,
class DestAccessor>
348 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
349 DestIterator
id, DestIterator idend, DestAccessor ad)
351 int wold = iend - i1;
352 int wnew = idend - id;
354 if((wold <= 1) || (wnew <= 1))
return;
357 NumericTraits<typename DestAccessor::value_type> DestTraits;
358 typedef typename DestTraits::RealPromote RealPromote;
360 ad.set(DestTraits::fromRealPromote(as(i1)),
id);
364 ad.set(DestTraits::fromRealPromote(as(iend)), idend);
366 double dx = (double)(wold - 1) / (wnew - 1);
369 for(;
id != idend; ++id, x += dx)
379 ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as(i1, 1))),
id);
489 template <
class SrcIterator,
class SrcAccessor,
490 class DestIterator,
class DestAccessor>
493 DestIterator
id, DestIterator idend, DestAccessor da)
495 int w = iend.x - is.x;
496 int h = iend.y - is.y;
498 int wnew = idend.x -
id.x;
499 int hnew = idend.y -
id.y;
501 vigra_precondition((w > 1) && (h > 1),
502 "resizeImageLinearInterpolation(): "
503 "Source image too small.\n");
504 vigra_precondition((wnew > 1) && (hnew > 1),
505 "resizeImageLinearInterpolation(): "
506 "Destination image too small.\n");
508 double const scale = 2.0;
510 typedef typename SrcAccessor::value_type SRCVT;
511 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
512 typedef BasicImage<TMPTYPE> TmpImage;
513 typedef typename TmpImage::traverser TmpImageIterator;
515 BasicImage<TMPTYPE> tmp(w, hnew);
516 BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
520 typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
521 typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
523 for(x=0; x<w; ++x, ++is.x, ++yt.x)
525 typename SrcIterator::column_iterator c1 = is.columnIterator();
526 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
531 lt, line.accessor(), (double)h/hnew/scale);
533 resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
534 ct, ct + hnew, tmp.accessor());
538 resizeLineLinearInterpolation(c1, c1 + h, sa,
539 ct, ct + hnew, tmp.accessor());
543 yt = tmp.upperLeft();
545 for(y=0; y < hnew; ++y, ++yt.y, ++
id.y)
547 typename DestIterator::row_iterator rd =
id.rowIterator();
548 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
553 lt, line.accessor(), (double)w/wnew/scale);
555 resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
560 resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
566 template <
class SrcIterator,
class SrcAccessor,
567 class DestIterator,
class DestAccessor>
570 triple<DestIterator, DestIterator, DestAccessor> dest)
573 dest.first, dest.second, dest.third);
576 template <
class T1,
class S1,
580 MultiArrayView<2, T2, S2> dest)
583 destImageRange(dest));
720 template <
class SrcIterator,
class SrcAccessor,
721 class DestIterator,
class DestAccessor,
725 SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
726 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
727 SPLINE
const & spline)
730 int width_old = src_iter_end.x - src_iter.x;
731 int height_old = src_iter_end.y - src_iter.y;
733 int width_new = dest_iter_end.x - dest_iter.x;
734 int height_new = dest_iter_end.y - dest_iter.y;
736 vigra_precondition((width_old > 1) && (height_old > 1),
737 "resizeImageSplineInterpolation(): "
738 "Source image too small.\n");
740 vigra_precondition((width_new > 1) && (height_new > 1),
741 "resizeImageSplineInterpolation(): "
742 "Destination image too small.\n");
744 Rational<int> xratio(width_new - 1, width_old - 1);
745 Rational<int> yratio(height_new - 1, height_old - 1);
746 Rational<int> offset(0);
747 resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
748 resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
749 int xperiod =
lcm(xratio.numerator(), xratio.denominator());
750 int yperiod =
lcm(yratio.numerator(), yratio.denominator());
752 double const scale = 2.0;
754 typedef typename SrcAccessor::value_type SRCVT;
755 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
756 typedef BasicImage<TMPTYPE> TmpImage;
757 typedef typename TmpImage::traverser TmpImageIterator;
759 BasicImage<TMPTYPE> tmp(width_old, height_new);
761 BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
762 typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
763 ArrayVector<double>
const & prefilterCoeffs = spline.prefilterCoefficients();
767 ArrayVector<Kernel1D<double> > kernels(yperiod);
768 createResamplingKernels(spline, ymapCoordinate, kernels);
770 typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
771 typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
773 for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
776 typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
777 typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
779 if(prefilterCoeffs.size() == 0)
781 if(height_new >= height_old)
784 c_tmp, c_tmp + height_new, tmp_acc,
785 kernels, ymapCoordinate);
790 line_tmp, line.accessor(), (double)height_old/height_new/scale);
792 c_tmp, c_tmp + height_new, tmp_acc,
793 kernels, ymapCoordinate);
799 line_tmp, line.accessor(),
800 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
801 for(
unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
804 line_tmp, line.accessor(),
805 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
807 if(height_new < height_old)
810 line_tmp, line.accessor(), (double)height_old/height_new/scale);
813 c_tmp, c_tmp + height_new, tmp_acc,
814 kernels, ymapCoordinate);
818 y_tmp = tmp.upperLeft();
820 kernels.resize(xperiod);
821 createResamplingKernels(spline, xmapCoordinate, kernels);
823 for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
825 typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
826 typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
828 if(prefilterCoeffs.size() == 0)
830 if(width_new >= width_old)
833 r_dest, r_dest + width_new, dest_acc,
834 kernels, xmapCoordinate);
839 line_tmp, line.accessor(), (double)width_old/width_new/scale);
841 r_dest, r_dest + width_new, dest_acc,
842 kernels, xmapCoordinate);
848 line_tmp, line.accessor(),
849 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
850 for(
unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
853 line_tmp, line.accessor(),
854 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
856 if(width_new < width_old)
859 line_tmp, line.accessor(), (double)width_old/width_new/scale);
862 r_dest, r_dest + width_new, dest_acc,
863 kernels, xmapCoordinate);
868 template <
class SrcIterator,
class SrcAccessor,
869 class DestIterator,
class DestAccessor>
872 DestIterator
id, DestIterator idend, DestAccessor da)
877 template <
class SrcIterator,
class SrcAccessor,
878 class DestIterator,
class DestAccessor,
882 triple<DestIterator, DestIterator, DestAccessor> dest,
883 SPLINE
const & spline)
886 dest.first, dest.second, dest.third, spline);
889 template <
class SrcIterator,
class SrcAccessor,
890 class DestIterator,
class DestAccessor>
893 triple<DestIterator, DestIterator, DestAccessor> dest)
896 dest.first, dest.second, dest.third);
899 template <
class T1,
class S1,
904 MultiArrayView<2, T2, S2> dest,
905 SPLINE
const & spline)
908 destImageRange(dest), spline);
911 template <
class T1,
class S1,
915 MultiArrayView<2, T2, S2> dest)
918 destImageRange(dest));
982 template <
class SrcIterator,
class SrcAccessor,
983 class DestIterator,
class DestAccessor>
986 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
989 CatmullRomSpline<double>());
992 template <
class SrcIterator,
class SrcAccessor,
993 class DestIterator,
class DestAccessor>
996 triple<DestIterator, DestIterator, DestAccessor> dest)
999 dest.first, dest.second, dest.third);
1002 template <
class T1,
class S1,
1006 MultiArrayView<2, T2, S2> dest)
1009 destImageRange(dest));
1074 template <
class SrcIterator,
class SrcAccessor,
1075 class DestIterator,
class DestAccessor>
1078 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
1081 CoscotFunction<double>());
1084 template <
class SrcIterator,
class SrcAccessor,
1085 class DestIterator,
class DestAccessor>
1088 triple<DestIterator, DestIterator, DestAccessor> dest)
1091 dest.first, dest.second, dest.third);
1094 template <
class T1,
class S1,
1098 MultiArrayView<2, T2, S2> dest)
1101 destImageRange(dest));
1108 #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...