00001
00024 #ifndef VIGRA_EXT_PYRAMID_H
00025 #define VIGRA_EXT_PYRAMID_H
00026
00027 #include <vigra/separableconvolution.hxx>
00028
00029 #include <hugin_utils/utils.h>
00030
00031
00032
00033 #include <vigra_ext/pyramid2.h>
00034
00035
00036 namespace vigra_ext {
00037
00038 template <class ImageIn, class Image>
00039 void reduceNTimes(ImageIn & in, Image & out, int n)
00040 {
00041 typedef typename Image::value_type vt;
00042 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType;
00043 if (n <= 0) {
00044 out = in;
00045 return;
00046 }
00047
00048 size_t w = in.width();
00049 size_t h = in.height();
00050
00051 w = (w + 1) >> 1;
00052 h = (h + 1) >> 1;
00053
00054 Image temp;
00055 Image * curr = &temp;
00056 Image * next = &out;
00057 if( (n % 2) == 1)
00058 {
00059
00060 curr = &out;
00061 next = &temp;
00062 }
00063 curr->resize(w,h);
00064 enblend::reduce<SKIPSMType>(false, srcImageRange(in), destImageRange(*curr));
00065 n--;
00066 w = (w + 1) >> 1;
00067 h = (h + 1) >> 1;
00068 for( ; n > 0 ; --n) {
00069 next->resize(w,h);
00070 enblend::reduce<SKIPSMType>(false, srcImageRange(*curr), destImageRange(*next));
00071 w = (w + 1) >> 1;
00072 h = (h + 1) >> 1;
00073 Image * t = curr;
00074 curr = next;
00075 next = t;
00076 }
00077 }
00078
00079 template <class Image, class ImageMask>
00080 void reduceNTimes(Image & in, ImageMask & inMask, Image & out, ImageMask & outMask, int n)
00081 {
00082 typedef typename Image::value_type vt;
00083 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType;
00084 typedef typename ImageMask::value_type mt;
00085
00086 typedef double SKIPSMAlphaType;
00087
00088 if (n <= 0) {
00089 out = in;
00090 outMask = inMask;
00091 return;
00092 }
00093
00094 size_t w = in.width();
00095 size_t h = in.height();
00096
00097 w = (w + 1) >> 1;
00098 h = (h + 1) >> 1;
00099
00100 Image temp;
00101 ImageMask tempMask;
00102 Image * curr = &temp;
00103 ImageMask * currMask = &tempMask;
00104 Image * next = &out;
00105 ImageMask * nextMask = &outMask;
00106 if( (n % 2) == 1)
00107 {
00108
00109 curr = &out;
00110 currMask = &outMask;
00111 next = &temp;
00112 nextMask = &tempMask;
00113 }
00114 curr->resize(w,h);
00115 currMask->resize(w,h);
00116 enblend::reduce<SKIPSMType, SKIPSMAlphaType>(false, srcImageRange(in), srcImage(inMask),
00117 destImageRange(*curr), destImageRange(*currMask));
00118 n--;
00119 w = (w + 1) >> 1;
00120 h = (h + 1) >> 1;
00121 for( ; n > 0 ; --n) {
00122 next->resize(w,h);
00123 nextMask->resize(w,h);
00124 enblend::reduce<SKIPSMType, SKIPSMAlphaType>(false, srcImageRange(*curr), srcImage(*currMask),
00125 destImageRange(*next), destImageRange(*nextMask));
00126 w = (w + 1) >> 1;
00127 h = (h + 1) >> 1;
00128 Image * t = curr;
00129 ImageMask * tm = currMask;
00130 curr = next;
00131 currMask = nextMask;
00132 next = t;
00133 nextMask = tm;
00134 }
00135 }
00136
00137 template <class ImageIn, class ImageOut>
00138 void reduceToNextLevel(ImageIn & in, ImageOut & out)
00139 {
00140 typedef typename ImageOut::value_type vt;
00141 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType;
00142
00143 size_t w = in.width();
00144 size_t h = in.height();
00145
00146 w = (w + 1) >> 1;
00147 h = (h + 1) >> 1;
00148 out.resize(w,h);
00149 enblend::reduce<SKIPSMType>(false, srcImageRange(in), destImageRange(out));
00150 }
00151
00152 template <class ImageIn, class ImageInMask, class ImageOut, class ImageOutMask>
00153 void reduceToNextLevel(ImageIn & in, ImageInMask & inMask, ImageOut & out, ImageOutMask & outMask)
00154 {
00155 typedef typename ImageOut::value_type vt;
00156 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType;
00157
00158 typedef double SKIPSMAlphaType;
00159
00160 size_t w = in.width();
00161 size_t h = in.height();
00162
00163 w = (w + 1) >> 1;
00164 h = (h + 1) >> 1;
00165 out.resize(w,h);
00166 enblend::reduce<SKIPSMType, SKIPSMAlphaType>(false, srcImageRange(in), srcImage(inMask),
00167 destImageRange(out), destImageRange(outMask));
00168 }
00169
00170
00171 static const double AA = 0.4;
00172 static const double W[] = {0.25 - AA / 2.0, 0.25, AA, 0.25, 0.25 - AA / 2.0};
00173
00178 template <class Image>
00179 void reduceToNextLevelOld(Image & in, Image & out)
00180 {
00181 DEBUG_TRACE("");
00182
00183 int width = in.width();
00184 int height = in.height();
00185
00186
00187 int newwidth = (width + 1) / 2;
00188 int newheight = (height + 1) / 2;
00189
00190
00191 out.resize(newwidth, newheight);
00192
00193
00194
00195 vigra::Kernel1D<double> filter;
00196 filter.initExplicitly(-2, 2) = W[0], W[1], W[2], W[3], W[4];
00197
00198 vigra::BasicImage<typename Image::value_type> tmpimage1(width, height);
00199 vigra::BasicImage<typename Image::value_type> tmpimage2(width, height);
00200
00201
00202 separableConvolveX(srcImageRange(in),
00203 destImage(tmpimage1), kernel1d(filter));
00204 separableConvolveY(srcImageRange(tmpimage1),
00205 destImage(tmpimage2), kernel1d(filter));
00206
00207
00208 resizeImageNoInterpolation(srcImageRange(tmpimage2), destImageRange(out));
00209
00210 }
00211
00212 }
00213
00214
00215 #endif // VIGRA_EXT_PYRAMID_H