contrib/tbl/vipl/filter/vipl_filter.txx
Go to the documentation of this file.
00001 // This is tbl/vipl/filter/vipl_filter.txx
00002 #ifndef vipl_filter_txx_
00003 #define vipl_filter_txx_
00004 //:
00005 // \file
00006 
00007 #include "vipl_filter.h"
00008 #include <vcl_iostream.h>
00009 #include <vcl_algorithm.h> // for vcl_max and vcl_min
00010 
00011 #ifdef VCL_VC
00012 #pragma warning( disable: 4390 )
00013 #endif
00014 
00015 #if !VCL_STATIC_CONST_INIT_INT_NO_DEFN
00016 template <class ImgIn,class ImgOut,class DataIn,class DataOut,int Arity,class PixelItr>
00017 const VIPL_FILTER_STATE vipl_filter<ImgIn,ImgOut,DataIn,DataOut,Arity,PixelItr>::Not_Ready VCL_STATIC_CONST_INIT_INT_DEFN( 0 );
00018 template <class ImgIn,class ImgOut,class DataIn,class DataOut,int Arity,class PixelItr>
00019 const VIPL_FILTER_STATE vipl_filter<ImgIn,ImgOut,DataIn,DataOut,Arity,PixelItr>::Ready VCL_STATIC_CONST_INIT_INT_DEFN( 1 );
00020 template <class ImgIn,class ImgOut,class DataIn,class DataOut,int Arity,class PixelItr>
00021 const VIPL_FILTER_STATE vipl_filter<ImgIn,ImgOut,DataIn,DataOut,Arity,PixelItr>::Unchanged VCL_STATIC_CONST_INIT_INT_DEFN( 2 );
00022 template <class ImgIn,class ImgOut,class DataIn,class DataOut,int Arity,class PixelItr>
00023 const VIPL_FILTER_STATE vipl_filter<ImgIn,ImgOut,DataIn,DataOut,Arity,PixelItr>::Filter_Owned VCL_STATIC_CONST_INIT_INT_DEFN( 4 );
00024 #endif
00025 
00026 //: A workhorse constructor for this abstract class.
00027 // If dst_image (by default) the output will be generated automatically when
00028 // filtering is about to proceed.
00029 // (Either way, the filter increments refcount when set and
00030 // decrements the refcount of the output when it is destroyed.) Some filters
00031 // support multiple inputs, if ninputs is >1 then this constructor expects
00032 // src_img to be the first element pointer to the input (i.e. src_img+1 is
00033 // the location of input image2). Note that the filter keeps pointers to the
00034 // input (properly refcounted).
00035 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int  Arity, class PixelItr>
00036   vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00037   ::vipl_filter( ImgIn const* src_img ,
00038                  ImgOut* dst_img ,
00039                  int ninputs,
00040                  int img_border ,
00041                  DataOut fill_val )
00042   : hsimage_border_size(img_border),
00043     hsdef_fill_value( fill_val ),
00044     hsinput_state(Ready),
00045     hsfilter_state(Not_Ready),
00046     hsoutput_state(Not_Ready),
00047     hsnuminputs(ninputs),
00048     hsinf(vcl_vector<inimagept>(hsnuminputs)),
00049     hsoutf(dst_img),
00050     hssrc_section (0),
00051     hsinsecp (0),
00052     hsdst_section (0),
00053     hssecp (0),
00054     hsinROA (NULL),
00055     hsROA (NULL),
00056     hsis_input_driven(false)
00057 {
00058 #if 0
00059   for (int j = numinputs()-1; j>=0; --j)
00060     ref_inf()[j] = 0;
00061 #endif
00062   if (dst_img) {
00063     if (UNCHANGED(output_state()))
00064       put_output_state(output_state() ^ Unchanged);
00065     if (FILTER_OWNED(output_state())) {
00066       put_output_state(output_state() ^ Filter_Owned);
00067 #if 0
00068       if (READY(output_state())) FILTER_IMPTR_DEC_REFCOUNT(ref_outf());
00069 #endif
00070     }
00071     if (NOT_READY(output_state()))
00072       put_output_state(output_state() | Ready);
00073 #if 0
00074     FILTER_IMPTR_INC_REFCOUNT(dst_img);
00075 #endif
00076   }
00077   for (int i=0; i< ninputs; i++) {
00078     ref_inf()[i] = src_img;
00079     if (src_img) src_img++; // if real, go to next one
00080 #if 0
00081     if (ref_inf()[i]) FILTER_IMPTR_INC_REFCOUNT(((ImgIn*)ref_inf()[i]));
00082 #endif
00083   }
00084 }
00085 
00086 //: A second workhorse constructor for this abstract class.
00087 // If dst_img is null (by default), the output will be generated automatically
00088 // when filtering is about to proceed. The filter decrements the refcount of the
00089 // output when it is destroyed. Some filters support multiple inputs, if
00090 // ninputs is >1 then this constructor uses non_consecutive input images (with
00091 // their address in a c_vector, i.e. *(src_img+1) is the location of input
00092 // image2). Note that the filter keeps pointers to the input (properly
00093 // refcounted).
00094 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00095   vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00096   ::vipl_filter( ImgIn const** src_img ,
00097                  ImgOut* dst_img ,
00098                  int ninputs,
00099                  int img_border ,
00100                  DataOut fill_val)
00101   : hsimage_border_size(img_border),
00102     hsdef_fill_value( fill_val ),
00103     hsinput_state(Ready),
00104     hsfilter_state(Not_Ready),
00105     hsoutput_state(Not_Ready),
00106     hsnuminputs(ninputs),
00107     hsinf(vcl_vector<inimagept>(hsnuminputs)),
00108     hsoutf(dst_img),
00109     hssrc_section (0),
00110     hsinsecp (0),
00111     hsdst_section (0),
00112     hssecp (0),
00113     hsinROA (NULL),
00114     hsROA (NULL),
00115     hsis_input_driven(false)
00116 {
00117 #if 0
00118   for (int j = numinputs()-1; j>=0; --j)
00119     ref_inf()[j] = 0;
00120 #endif
00121   if (dst_img) {
00122     if (UNCHANGED(output_state()))
00123       put_output_state(output_state() ^ Unchanged);
00124     if (FILTER_OWNED(output_state())) {
00125       put_output_state(output_state() ^ Filter_Owned);
00126 #if 0
00127       if (READY(output_state())) FILTER_IMPTR_DEC_REFCOUNT(ref_outf());
00128 #endif
00129     }
00130     if (NOT_READY(output_state()))
00131       put_output_state(output_state() | Ready);
00132 #if 0
00133     FILTER_IMPTR_INC_REFCOUNT(dst_img);
00134 #endif
00135   }
00136   for (int i=0; i< ninputs; i++, src_img++) {
00137     if (src_img == 0)
00138       vcl_cerr << "filter ctor passed vector will null src_img pointers, ignored them watch out.\n";
00139     else
00140       ref_inf()[i] = *src_img;
00141 #if 0
00142     if (ref_inf()[i]) FILTER_IMPTR_INC_REFCOUNT(((ImgIn*)ref_inf()[i]));
00143 #endif
00144   }
00145 }
00146 
00147 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00148   vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00149   ::~vipl_filter()
00150 {
00151 #ifdef DEBUG
00152   vcl_cout << "destructor for abstract class filter called " << this << vcl_endl;
00153 #endif
00154 #ifndef SMARTPTR
00155   if (ref_src_section()) FILTER_IMPTR_DEC_REFCOUNT(ref_src_section()); // dec_refcount or kill it
00156   if (ref_dst_section()) FILTER_IMPTR_DEC_REFCOUNT(ref_dst_section()); // dec_refcount or kill it
00157   if (ref_secp())        FILTER_IMPTR_DEC_REFCOUNT(ref_secp()); // dec_refcount or kill it
00158   if (ref_insecp())      FILTER_IMPTR_DEC_REFCOUNT(ref_insecp()); // dec_refcount or kill it
00159   if (ref_ROA())         FILTER_IMPTR_DEC_REFCOUNT(ref_ROA()); // dec_refcount or kill it
00160   if (ref_inROA())       FILTER_IMPTR_DEC_REFCOUNT(ref_inROA()); // dec_refcount or kill it
00161 #if 0
00162   for (int i=0; i< numinputs(); i++) {
00163     if (ref_inf()[i]) { // no longer needed with smart pointers
00164       FILTER_IMPTR_DEC_REFCOUNT(
00165 //    ((ImgIn*) (ref_inf()[i]))); //SGI CC doesn't like this...
00166       *((ImgIn**)(ref_inf())+i)); //FIXME, cast cause inf is const Im**
00167     }
00168   }
00169   //???  we did new (poor man's array) so we use delete????
00170   if (ref_inf()) {
00171     delete [] ref_inf();
00172     // free up new'd space
00173     ref_inf() = 0;
00174   }
00175   // delete the output and intermediate functions if they are filter-owned
00176 #if 0
00177     if (FILTER_OWNED(hsoutput_state) && hsoutf)
00178 #else
00179     if (ref_outf())
00180 #endif
00181     {
00182       FILTER_IMPTR_DEC_REFCOUNT(ref_outf());
00183     }
00184 #endif
00185 #endif
00186 }
00187 
00188 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00189   vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00190   ::vipl_filter()
00191   : hsimage_border_size(0),
00192     hsinput_state(Not_Ready),
00193     hsfilter_state(Not_Ready),
00194     hsoutput_state(Not_Ready),
00195     hsnuminputs(1),
00196     hsinf(vcl_vector<inimagept>(hsnuminputs)),
00197     hsoutf(0),
00198     hssrc_section(0),
00199     hsinsecp(0),
00200     hsdst_section(0),
00201     hssecp(0),
00202     hsinROA (NULL),
00203     hsROA (NULL),
00204     hsis_input_driven(false)
00205 {
00206 #if 0
00207   for (int i = 0; i < numinputs(); i++)
00208     ref_inf()[i] = 0;
00209 #endif
00210 }
00211 
00212 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00213   vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00214                          ::vipl_filter(vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr > const& t)
00215   : vipl_filter_abs (t),
00216     hsimage_border_size(t.hsimage_border_size),
00217     hsdef_fill_value(t.hsdef_fill_value),
00218     hsinput_state(t.hsinput_state),
00219     hsfilter_state(t.hsfilter_state),
00220     hsoutput_state(t.hsoutput_state),
00221     hsnuminputs(t.hsnuminputs),
00222     hsinf(vcl_vector<inimagept>(hsnuminputs)),
00223     hsoutf(0),
00224     hssrc_section(t.hssrc_section),
00225     hsinsecp(t.hsinsecp),
00226     hsdst_section(t.hsdst_section),
00227     hssecp(t.hssecp),
00228     hsinROA (t.hsinROA),
00229     hsROA (t.hsROA),
00230     hsis_input_driven(t.hsis_input_driven)
00231 // C++ low-level copy constructor
00232 {
00233   // you can fill special ``copy constructor'' stuff here.
00234   // All dynamic/soft attributes are copied. Thus your
00235   //code should not change any soft attributes (if you
00236   //want to change it here is should be hard because it
00237   //is always changed!) So don't change things without
00238   //knowing their form.
00239   for (int i = 0; i < numinputs(); i++) {
00240     ref_inf()[i] = t.inf()[i];
00241 #if 0
00242     if (ref_inf()[i]) FILTER_IMPTR_INC_REFCOUNT(((ImgIn*)ref_inf()[i]));
00243 #endif
00244   }
00245 #ifndef SMARTPTR
00246   if (ref_outf()) { FILTER_IMPTR_INC_REFCOUNT(ref_outf()); }
00247   if (ref_src_section()) { FILTER_IMPTR_INC_REFCOUNT(ref_src_section()); } // share so inc_refcount
00248   if (ref_dst_section()) { FILTER_IMPTR_INC_REFCOUNT(ref_dst_section()); } // share so inc_refcount
00249   if (ref_secp()) { FILTER_IMPTR_INC_REFCOUNT(ref_secp()); } // share so inc_refcount
00250   if (ref_insecp()) { FILTER_IMPTR_INC_REFCOUNT(ref_insecp()); } // share so inc_refcount
00251   if (ref_ROA()) { FILTER_IMPTR_INC_REFCOUNT(ref_ROA()); } // share so inc_refcount
00252   if (ref_inROA()) { FILTER_IMPTR_INC_REFCOUNT(ref_inROA()); } // share so inc_refcount
00253 #endif
00254   // FIXME should we do deep copy of filter-ownable parameters.???
00255   if (FILTER_OWNED(hsoutput_state))
00256     hsoutput_state ^= Filter_Owned;
00257 }
00258 
00259 //:
00260 // Is the current apply section intersected with the ROA an empty region, if
00261 // so we should not load it. If it's empty there is no guarantee that the
00262 // section_start and section_end will not overlap.
00263 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00264   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00265                    ::is_section_within_ROA(int axis) const
00266 {
00267   if (is_input_driven()) { // if we are input driven
00268     if (!inROA())
00269   // if we don't have an ROA we must be in it.
00270       return true;
00271     // should this consider insecp???????
00272     if (insecp()) { // ok have a valid section .
00273       for (int i =0; i < Arity; i++){
00274         if ((insecp()->curr_sec_start(axis) > inROA()->curr_sec_end(axis)) ||
00275             (insecp()->curr_sec_end(axis) < inROA()->curr_sec_start(axis)))
00276           return false;
00277       }
00278       return true;
00279   // if we make it this far, must be in
00280     }
00281   }
00282   else {
00283     // if we don't have an ROA we must be in it.
00284     if (!ROA())
00285       return true;
00286     // should this consider secp or insecp???????
00287     if (secp()) { // ok have a valid section .
00288       for (int i =0; i < Arity; i++) {
00289         if ((secp()->curr_sec_start(axis) > ROA()->curr_sec_end(axis)) ||
00290             (secp()->curr_sec_end(axis) < ROA()->curr_sec_start(axis)))
00291           return false;
00292       }
00293       return true;
00294   // if we make it this far, must be in
00295     }
00296   }
00297   // error if reaching this point:
00298   vcl_cerr << "Warning: called is_section_within_ROA but no valid sections defined. Returning 0\n";
00299   return 0;
00300 }
00301 
00302 //: What is the ``start coordinate'' for the current apply section.
00303 // This always leaves a border around the section. (E.g. if there is no ROA this
00304 // is actual section start + image_boarder_size;  remember section iteration
00305 // overlaps).  If the current section is outside the ROA, the section_start
00306 // and section_end may be equal.
00307 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00308   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00309                      ::start(int axis) const
00310 {
00311   if (is_input_driven()) return start_src(axis);
00312   else  return start_dst(axis);
00313 }
00314 
00315 //: What is the ``start'' coordinate for the current source apply section.
00316 // This always leaves a border around the section. (E.g. if there is no ROA this
00317 // is actual section start + image_boarder_size;  remember section iteration
00318 // overlaps).  If the current section is outside the ROA, the section_start
00319 // and section_end may be equal.
00320 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00321   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00322                      ::start_src(int axis) const
00323 {
00324   if (insecp()){ // ok have a valid section
00325     int ibs = image_border_size();
00326     int end = insecp()->curr_sec_end(axis);
00327     int st = insecp()->curr_sec_start(axis);
00328     if (st > end){ // swap hack in case people get it wrong....
00329       int temp = end; end = st; st = temp;
00330     }
00331     st += ibs;
00332     end -= ibs;
00333     if (inROA())
00334       st =vcl_min(end,vcl_max(st,inROA()->curr_sec_start(axis)+ibs));
00335 #ifdef DEBUG
00336     vcl_cerr << "i_ [" << axis << "] st=" << st << " ibs=" << ibs << vcl_endl;
00337 #endif
00338     return st;
00339   }
00340 
00341   // error if reaching this point:
00342   vcl_cerr << "Warning: called start_src but no valid sections defined. Returning 0\n";
00343   return 0;
00344 }
00345 
00346 
00347 //: What is the ``start'' coordinate for the current destination apply section.
00348 // This always leaves a border around the section. (E.g. if there is no ROA this
00349 // is actual section start + image_boarder_size;  remember section iteration
00350 // overlaps).  If the current section is outside the ROA, the section_start
00351 // and section_end may be equal.
00352 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00353   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00354                      ::start_dst(int axis) const
00355 {
00356   // should we consider secp or insecp????
00357   if (secp()){ // ok have a valid section
00358     int ibs = image_border_size();
00359     int end = secp()->curr_sec_end(axis);
00360     int st = secp()->curr_sec_start(axis);
00361     if (st > end){ // swap hack in case people get it wrong....
00362       int temp = end; end = st; st = temp;
00363     }
00364     st += ibs;
00365     end -= ibs;
00366     if (ROA())
00367       st = vcl_min(end,vcl_max(st,ROA()->curr_sec_start(axis)+ibs));
00368 #ifdef DEBUG
00369     vcl_cerr << "o_ [" << axis << "] st=" << st << " ibs=" << ibs << vcl_endl;
00370 #endif
00371     return st;
00372   }
00373 
00374   // error if reaching this point:
00375   vcl_cerr << "Warning: called start_dst but no valid sections defined. Returning 0\n";
00376   return 0;
00377 }
00378 
00379 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00380   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00381                      ::start(int axis, int /*other_axis_value*/) const
00382 { return start(axis); }
00383 
00384 //: What is the ``stopping'' coordinate for the current apply section.
00385 // This always leaves a border around the section. (E.g. if there is no ROA this
00386 // is actual section end - image_boarder_size;  remember section iteration
00387 // overlaps).  If the current section is outside the ROA, the section_start
00388 // and section_end may be equal.
00389 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00390   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00391                      ::stop(int axis) const
00392 {
00393   if (is_input_driven()) return stop_src(axis);
00394   else  return stop_dst(axis);
00395 }
00396 
00397 
00398 //: What is the ``stopping'' coordinate for the current apply section.
00399 // This always leaves a border around the section. (E.g. if there is no ROA this
00400 // is actual section end - image_boarder_size;  remember section iteration
00401 // overlaps).  If the current section is outside the ROA, the section_start
00402 // and section_end may be equal.
00403 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00404   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00405                      ::stop_src(int axis) const
00406 {
00407   if (insecp()){ // ok have a valid section
00408     int ibs = image_border_size();
00409     int end = insecp()->curr_sec_end(axis);
00410     int st = insecp()->curr_sec_start(axis);
00411     if (st > end){ // hack in case people get it wrong....
00412       end = st;
00413     }
00414     end -= ibs;
00415 #ifdef DEBUG
00416     vcl_cerr << "_i [" << axis << "] end=" << end << " ibs=" << ibs << vcl_endl;
00417 #endif
00418     return end;
00419   }
00420 
00421   // error if reaching this point:
00422   vcl_cerr << "Warning: called stop_src but no valid sections defined. Returning 0\n";
00423   return 0;
00424 }
00425 
00426 
00427 //: What is the ``stopping'' coordinate for the current apply section.
00428 // This always leaves a border around the section. (E.g. if there is no ROA this
00429 // is actual section end - image_boarder_size;  remember section iteration
00430 // overlaps).  If the current section is outside the ROA, the section_start
00431 // and section_end may be equal.
00432 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00433   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00434                      ::stop_dst(int axis) const
00435 {
00436   // should we consider secp or insecp????
00437   if (secp()){ // ok have a valid section
00438     int ibs = image_border_size();
00439     int end = secp()->curr_sec_end(axis);
00440     int st = secp()->curr_sec_start(axis);
00441     if (st > end){ // hack in case people get it wrong....
00442       end = st;
00443     }
00444     end -= ibs;
00445 #ifdef DEBUG
00446     vcl_cerr << "_o [" << axis << "] end=" << end << " ibs=" << ibs << vcl_endl;
00447 #endif
00448     return end;
00449   }
00450 
00451   // error if reaching this point:
00452   vcl_cerr << "Warning: called stop_dst but no valid sections defined. Returning 0\n";
00453   return 0;
00454 }
00455 
00456 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00457   int vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00458                      ::stop(int axis, int /*other_axis_value*/) const
00459 { return stop(axis); }
00460 
00461 // Put the given pointer into the array of input ``functions'' at the
00462 // provided index. Decrements old objects refcount, Inc's newobjects
00463 // refcount
00464 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00465   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00466                         ::put_in_data_ptr(ImgIn const* fpointer , int index)
00467 {
00468   if (UNCHANGED(input_state()) || NOT_READY(input_state()))
00469     ref_input_state() = Ready;
00470   if ( 0 <= index && index < numinputs()) {
00471 #if 0
00472     if (ref_inf()[index]) { // no longer needed for smart pointers
00473       // FILTER_IMPTR_DEC_REFCOUNT(((ImgIn*)ref_inf()[index])); //SGI CC doesn't like this...
00474       FILTER_IMPTR_DEC_REFCOUNT(*((ImgIn**)(ref_inf())+index)); // release old
00475     }
00476 #endif
00477     ref_inf()[index] = fpointer;
00478 #if 0
00479     if (fpointer) FILTER_IMPTR_INC_REFCOUNT(((ImgIn*)fpointer)); // mark new
00480 #endif
00481     return true;
00482   }
00483   // error if reaching this point:
00484   vcl_cerr << "Warning: index out of range in put_in_data_ptr, ignored\n";
00485   return false;
00486 }
00487 
00488 // Return a pointer to the input ``functions'' at the provided
00489 // index. Increments refcount before returning
00490 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00491   ImgIn const* vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00492                           ::in_data_ptr(int index)
00493 {
00494   if (index < 0 || index >= numinputs()) {
00495     vcl_cerr << "Warning: index " << index << " out of range, returning data at 0 instead\n";
00496     index = 0;
00497   }
00498   return inf()[index];
00499 }
00500 
00501 //: Return a ref to the input ``data object'' at the provided index.
00502 // (dereferences the internal pointer)
00503 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00504   const ImgIn& vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr>
00505                            ::in_data(int index) const
00506 {
00507   if (0 <= index && index < numinputs()) {
00508     if (inf()[index])
00509       return *inf()[index];
00510     else {
00511       vcl_cerr << "Warning: input pointer is null returning image at index 0\n";
00512       return *inf()[0];
00513     }
00514   }
00515   vcl_cerr << "Warning: out of range is null, a new val, it will leak\n";
00516   return *inf()[0];
00517 }
00518 
00519 //: Put the given pointer into output data at the given index location.
00520 // Decrements old putput refcount, increments newobjects refcount.
00521 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00522   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00523                         ::put_out_data_ptr(ImgOut* fpointer , int /*index*/)
00524 {
00525   if (UNCHANGED(output_state()))    put_output_state(output_state() ^ Unchanged);
00526   if (FILTER_OWNED(output_state())) put_output_state(output_state() ^ Filter_Owned);
00527 #if 0
00528   if (ref_outf())                   FILTER_IMPTR_DEC_REFCOUNT(ref_outf());
00529 #endif
00530   if (NOT_READY(output_state()))    put_output_state(output_state() | Ready);
00531 #if 0
00532   FILTER_IMPTR_INC_REFCOUNT(fpointer); // we will keep a pointer, inc it
00533 #endif
00534   put_outf(fpointer);
00535   return true;
00536 }
00537 
00538 //: Get ptr to specified output data item given index location.
00539 // Inc's refcount before returning ptr.
00540 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00541   ImgOut* vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00542                      ::out_data_ptr(int /*index*/)
00543 {
00544   if (READY(output_state()) || UNCHANGED(output_state()))
00545     put_output_state(output_state() ^ Unchanged);
00546   if (READY(output_state()) )
00547     return ref_outf();
00548   else {
00549     vcl_cerr << "Warning: Tried to reference a NOT READY output-data, returned 0\n";
00550     return 0;
00551   }
00552 }
00553 
00554 //: Get ref to specified output data item given index location.
00555 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00556    ImgOut& vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr>
00557                             ::out_data(int /*index*/) const
00558 {
00559   if (READY(output_state()) )
00560     return *outf();
00561   else {
00562     vcl_cerr << "Warning: Tried to reference a NOT READY output-returning old input, may coredump\n";
00563     return *outf();
00564   }
00565 }
00566 
00567 //: This function gets called for every iteration of the filtering operation, before the actual filtering routine.
00568 // Can be used for input normalization or such. Default op is noop.
00569 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00570   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00571                       ::preop()
00572 {
00573   return true;
00574 }
00575 
00576 //: This function gets called after every iteration of the actual filtering routine.
00577 // Can be used for post_processing normalization or cleaning up the edges. Default op is noop.
00578 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00579   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00580                       ::postop()
00581 {
00582   return true;
00583 }
00584 
00585 //: This is the method that implements the basic form for the filtering operation.
00586 // For each section, this method runs before section_applyop. Default at this
00587 // level is noop. (lower level class redefine it to ``fill'' the image borders).
00588 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00589   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00590                       ::section_preop()
00591 {
00592   return true;
00593 }
00594 
00595 //: For each section, this method runs after section_applyop.
00596 // Default is noop
00597 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00598   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00599                      ::section_postop()
00600 {
00601   return true;
00602 }
00603 
00604 //: This is the method that implements the filtering inside each section.
00605 // You must supply this function.
00606 // If a section is pointer safe, then this function is called to filter
00607 // it. Default is just to call the non-pointer section_applyop
00608 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00609   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00610                       ::ptr_based_section_applyop()
00611 {
00612   return section_applyop();
00613 }
00614 
00615 //:
00616 // Before this function can run to completion, all arguments must be set via
00617 // the respective ``put_*'' functions (or be supplied at
00618 // construction time). Particularly important is the filter input. The
00619 // programmer should take a look at the concrete child classes of filter to
00620 // see what additional parameters they need before the actual filter
00621 // operation can proceed.
00622 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00623   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00624                      ::filter()
00625 {
00626   bool proceed_anyway = false;
00627   if (NOT_READY(input_state())) {
00628     // first make sure that the filter is ready to proceed
00629     ref_filter_state() = Not_Ready;
00630     vcl_cerr << "Warning: filtering without valid input\n";
00631     return false;
00632   }
00633   else if (UNCHANGED(input_state())) {
00634     ref_filter_state() |= Unchanged;
00635   }
00636   else
00637     ref_filter_state() |= Ready;
00638   if (NOT_READY(output_state()) || (FILTER_OWNED(output_state()) &&
00639                                     CHANGED(input_state()))) {
00640     // be conservative - if input has changed, then may need to regen the
00641     // output since we can not compare respective sizes .
00642 #if 0
00643     if (outf()) FILTER_IMPTR_DEC_REFCOUNT(ref_outf());
00644 #endif
00645     vcl_cerr << "Warning: Input changed after output set.  Sizes may not match...\n";
00646   }
00647   if ((check_params_1(proceed_anyway) &&
00648       READY(filter_state()) && CHANGED(filter_state())) || proceed_anyway) {
00649     return applyop();
00650   }
00651   return proceed_anyway;
00652 }
00653 
00654 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00655   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00656                        ::is_ready() const
00657 {
00658   bool proceeding=false;
00659   return check_params_1(proceeding) && !proceeding;
00660 }
00661 
00662 //:
00663 // For those filters that only need one input and output set (after
00664 // construction), the following function allows one to treat the filter
00665 // object more like a function calling
00666 //     obj.process(inimg, outimg)
00667 // will set the input and output then call filter()
00668 // It does not require pointers but takes the address of its
00669 // inputs, set the fields in the filter
00670 // does the filter and un-sets the in/out fields in the filter.
00671 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00672 bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00673                      ::process( ImgIn const& inimg, ImgOut& outimg)
00674 {
00675   put_in_data_ptr(&inimg);
00676   put_out_data_ptr(&outimg);
00677   bool ret = filter(); // do the real work
00678   put_in_data_ptr(0);  // reset input
00679   put_out_data_ptr(0); // reset output
00680   return ret;
00681 }
00682 
00683 //: second process form passing imgs by ptr.
00684 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00685 bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00686                      ::process( ImgIn const* inimg, ImgOut* outimg)
00687 {
00688   put_in_data_ptr(inimg);
00689   put_out_data_ptr(outimg);
00690   bool ret = filter(); // do the real work
00691   put_in_data_ptr(0);  // reset input
00692   put_out_data_ptr(0); // reset output
00693   return ret;
00694 }
00695 
00696 //:
00697 // Called by method \p filter() and checks additional parameters required
00698 // before the filtering operation can proceed. Default is empty_func
00699 // returning true, but subclasses can define as then need.  check_parms_1
00700 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00701   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00702                         ::check_params_1( bool& proceed_on_warn) const
00703 {
00704   proceed_on_warn = true;
00705   // check input and output are OK.
00706   return !NOT_READY(output_state()) && !NOT_READY(input_state());
00707 }
00708 
00709 #ifdef USE_COMPOSE_WITH
00710 //:
00711 // Try to set the output of this filter to be the input of ``to'', and
00712 // if possible make the filtering more efficient than just sequential
00713 // calls. Currently unimplemented so far this function does
00714 // nothing. Arg should be a nonconst ref because composition may
00715 // change the filter!
00716 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr>
00717   bool vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr >
00718                       ::compose_with(vipl_filter_abs& to)
00719 {
00720   vcl_cerr << "Warning: called unimplemented method compose_with\n";
00721   return false;
00722 }
00723 #endif
00724 
00725 #endif // vipl_filter_txx_