core/vil1/vil1_convolve_simple.txx

Go to the documentation of this file.
00001 // This is core/vil1/vil1_convolve_simple.txx
00002 #ifndef vil1_convolve_simple_txx_
00003 #define vil1_convolve_simple_txx_
00004 //:
00005 // \file
00006 // \author fsm
00007 
00008 #include "vil1_convolve_simple.h"
00009 
00010 #include <vcl_cassert.h>
00011 #include <vcl_algorithm.h>
00012 #include <vcl_vector.h>
00013 
00014 #ifndef TRACE
00015 #define TRACE 0
00016 #endif
00017 #if TRACE
00018 #include <vcl_iostream.h>
00019 #endif
00020 
00021 //--------------------------------------------------------------------------------
00022 
00023 // fsm: With 2.7 the assembler complains that this symbol is defined
00024 // twice. Moreover, it *is* defined twice (both .weak), even if we don't
00025 // explicitly instantiate it. If explicitly instantiated, it is defined once
00026 // .global and once .weak. Presumably, the compiler incorrectly thinks it needs
00027 // to instantiate it twice just because it is called twice.
00028 // To get around this annoying bug without breaking up the source file, this
00029 // function must be called through a pointer-to-function on gcc 2.7.2, since
00030 // that seems to trick the compiler into emitting only one instantiation.
00031 template <class I1, class I2, class AC, class O>
00032 void vil1_convolve_simple(I1 const* const* input1, unsigned w1, unsigned h1,
00033                           I2 const* const* input2, unsigned w2, unsigned h2,
00034                           AC *,
00035                           O       * const* out)
00036 {
00037   //?? typedef typename vil1_ip_traits<O* const*>::pixel_type OutType;
00038 
00039 #if TRACE
00040   vcl_cerr << "w1 h1 = " << w1 << ' ' << h1 << vcl_endl;
00041   vcl_cerr << "w2 h2 = " << w2 << ' ' << h2 << vcl_endl;
00042 #endif
00043 
00044   // here we go : vrrrm.. vrrrm..
00045   for (int jo=0; jo<int(h1+h2)-1; ++jo) {
00046     for (int io=0; io<int(w1+w2)-1; ++io) {
00047       // initialize accumulator
00048       AC acc(0);
00049 
00050       // bounds.
00051       // The type unification complains there is no max(int, unsigned)
00052       // template. On gcc 2.95 we could use max<int> to disambiguate,
00053       // but SGI native doesn't accept that. Hence the explicit casts.
00054       // fsm
00055       int ibeg = vcl_max(int( 0), int(io-w2+1));
00056       int iend = vcl_min(int(w1), int(io+1));
00057       int jbeg = vcl_max(int( 0), int(jo-h2+1));
00058       int jend = vcl_min(int(h1), int(jo+1));
00059 
00060       // accumulate
00061       for (int j1=jbeg; j1<jend; ++j1) {
00062         for (int i1=ibeg; i1<iend; ++i1) {
00063           int i2 = io - i1;
00064           int j2 = jo - j1;
00065           acc += AC(input1[j1][i1]) * AC(input2[j2][i2]);
00066         }
00067       }
00068 
00069       // assign
00070       out[jo][io] = O/*utType*/(acc);
00071     }
00072   }
00073 }
00074 
00075 #define VIL1_CONVOLVE_SIMPLE_INSTANTIATE0(I1, I2, AC, O) \
00076 template void vil1_convolve_simple(I1 const * const *, unsigned, unsigned, \
00077                                    I2 const * const *, unsigned, unsigned, \
00078                                    AC *,  \
00079                                    O * const *)
00080 
00081 //----------------------------------------------------------------------
00082 
00083 #include <vil1/vil1_memory_image_of.h>
00084 
00085 template <class I1, class I2, class AC, class O>
00086 void vil1_convolve_simple(vil1_memory_image_of<I1> const &input1,    // input 1
00087                           int x1, int y1, unsigned w1, unsigned h1,
00088                           vil1_memory_image_of<I2> const &input2,    // input 2
00089                           int x2, int y2, unsigned w2, unsigned h2,
00090                           AC *,
00091                           vil1_memory_image_of<O>        &output,    // output
00092                           int xo, int yo)
00093 {
00094   // assert that the memory to be touched may be touched :
00095   assert( input1.in_range(x1, y1, w1, h1) );
00096   assert( input2.in_range(x2, y2, w2, h2) );
00097   assert( output.in_range(xo, yo, w1+w2-1, h1+h2-1) );
00098 
00099   //
00100   vcl_vector<I1 const *> in1(h1);
00101   for (unsigned k=0; k<h1; ++k)
00102     in1[k] = input1[y1+k] + x1;
00103 #if TRACE
00104   vcl_cerr << in1.size() << " rasters in in1\n";
00105 #endif
00106 
00107   //
00108   vcl_vector<I2 const *> in2(h2);
00109   for (unsigned k=0; k<h2; ++k)
00110     in2[k] = input2[y2+k] + x2;
00111 #if TRACE
00112   vcl_cerr << in2.size() << " rasters in in2\n";
00113 #endif
00114 
00115   //
00116   vcl_vector<O *> out(h1+h2-1);
00117   for (unsigned k=0; k<h1+h2-1; ++k)
00118     out[k] = output[yo+k] + xo;
00119 #if TRACE
00120   vcl_cerr << out.size() << " rasters in out\n";
00121 #endif
00122 
00123   // call the simpler routine (see comment above for explanation of hack).
00124   static void (*f)(I1 const * const *, unsigned, unsigned,
00125                    I2 const * const *, unsigned, unsigned,
00126                    AC *,
00127                    O        * const *) = 0;
00128   if (!f)
00129     f = vil1_convolve_simple;
00130   (*f)(const_cast<I1 const * const *>(/* xxx */&in1[0]), w1, h1,
00131        const_cast<I2 const * const *>(/* xxx */&in2[0]), w2, h2,
00132        (AC*)0,
00133        const_cast<O        * const *>(/* xxx */&out[0]));
00134 }
00135 
00136 #define VIL1_CONVOLVE_SIMPLE_INSTANTIATE1(I1, I2, AC, O) \
00137 template void vil1_convolve_simple(vil1_memory_image_of<I1 > const &, \
00138                                    int, int, unsigned, unsigned,      \
00139                                    vil1_memory_image_of<I2 > const &, \
00140                                    int, int, unsigned, unsigned,      \
00141                                    AC *, \
00142                                    vil1_memory_image_of<O >        &, \
00143                                    int, int)
00144 
00145 //----------------------------------------------------------------------
00146 
00147 //: $\displaystyle {\rm out}_{{\rm off}+k} = \sum_{i+j=k} a_{{\rm off}+i} b_{{\rm off}+j}$
00148 template <class I1, class I2, class AC, class O>
00149 void vil1_convolve_simple(vil1_memory_image_of<I1> const &in1,
00150                           vil1_memory_image_of<I2> const &in2,
00151                           AC *,
00152                           vil1_memory_image_of<O>        &out)
00153 {
00154   // see comment above for explanation of hack.
00155   static void (*f)(I1 const * const *, unsigned, unsigned,
00156                    I2 const * const *, unsigned, unsigned,
00157                    AC *,
00158                    O        * const *) = 0;
00159   if (!f)
00160     f = vil1_convolve_simple;
00161   (*f)(in1.row_array(), in1.width(), in1.height(),
00162        in2.row_array(), in2.width(), in2.height(),
00163        (AC*)0,
00164        out.row_array());
00165 }
00166 
00167 #define VIL1_CONVOLVE_SIMPLE_INSTANTIATE2(I1, I2, AC, O) \
00168 template void vil1_convolve_simple(vil1_memory_image_of<I1 > const &, \
00169                                    vil1_memory_image_of<I2 > const &, \
00170                                    AC *, \
00171                                    vil1_memory_image_of<O >        &)
00172 
00173 //--------------------------------------------------------------------------------
00174 
00175 //
00176 #define VIL1_CONVOLVE_SIMPLE_INSTANTIATE(I1, I2, AC, O) \
00177 VIL1_CONVOLVE_SIMPLE_INSTANTIATE0(I1, I2, AC, O); \
00178 VIL1_CONVOLVE_SIMPLE_INSTANTIATE1(I1, I2, AC, O); \
00179 VIL1_CONVOLVE_SIMPLE_INSTANTIATE2(I1, I2, AC, O)
00180 
00181 #endif // vil1_convolve_simple_txx_

Generated on Tue Oct 7 05:08:18 2008 for core/vil1 by  doxygen 1.5.1