• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

transform_line.hh

00001 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
00002 // (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 #ifndef MLN_ACCU_TRANSFORM_LINE_HH
00028 # define MLN_ACCU_TRANSFORM_LINE_HH
00029 
00042 
00043 # include <mln/core/concept/image.hh>
00044 # include <mln/core/concept/meta_accumulator.hh>
00045 # include <mln/extension/adjust.hh>
00046 
00047 
00048 namespace mln
00049 {
00050 
00051   namespace accu
00052   {
00053 
00054 
00055     template <typename A, typename I>
00056     mln_ch_value(I, mln_result(A))
00057     transform_line(const Accumulator<A>& a,
00058                    const Image<I>& input,
00059                    unsigned length, unsigned dir);
00060 
00061     template <typename A, typename I>
00062     mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00063     transform_line(const Meta_Accumulator<A>& a,
00064                    const Image<I>& input,
00065                    unsigned length, unsigned dir);
00066 
00067 
00068 
00069 # ifndef MLN_INCLUDE_ONLY
00070 
00071 
00072     // Tests.
00073 
00074 
00075     namespace internal
00076     {
00077 
00078       template <typename A, typename I>
00079       void
00080       transform_line_tests(const Accumulator<A>& a_, const Image<I>& input_)
00081       {
00082         A a = exact(a_);
00083         const I& input = exact(input_);
00084 
00085         mln_precondition(input.is_valid());
00086         mln_psite(I)* p;
00087         mln_precondition(sizeof(a.take(input(*p)), 0) == sizeof(int));
00088 
00089         (void) p;
00090         (void) a;
00091         (void) input;
00092       }
00093 
00094     } // end of namespace mln::accu::internal
00095 
00096 
00097 
00098     // Implementations.
00099 
00100 
00101     namespace impl
00102     {
00103 
00104       namespace generic
00105       {
00106 
00107         template <typename A, typename I>
00108         inline
00109         mln_ch_value(I, mln_result(A))
00110         transform_line(const Accumulator<A>& a_,
00111                        const Image<I>& input_,
00112                        unsigned length, unsigned dir)
00113         {
00114           trace::entering("accu::impl::transform_line");
00115 
00116           const I& input = exact(input_);
00117           A a = exact(a_);
00118 
00119           internal::transform_line_tests(a, input);
00120 
00121           extension::adjust(input, length / 2); // Safety.
00122 
00123           mln_ch_value(I, mln_result(A)) output;
00124           initialize(output, input);
00125 
00126           typedef mln_psite(I) P;
00127           const P
00128             pmin = input.domain().pmin(),
00129             pmax = input.domain().pmax();
00130           const def::coord
00131             pmax_dir = pmax[dir],
00132             pmin_dir = pmin[dir];
00133 
00134           P p = pmin, // Starting point.
00135             qt, qu;
00136           def::coord& p_dir  = p [dir];
00137           def::coord& qt_dir = qt[dir];
00138           def::coord& qu_dir = qu[dir];
00139 
00140           do
00141             {
00142 
00143               // Start the line.
00144               // ---------------
00145 
00146               qt = p;
00147               qt_dir = p_dir - length / 2;
00148               qu = qt;
00149               a.init();
00150 
00151               for (unsigned i = 0; i < length; ++i)
00152                 {
00153                   if (input.has(qt))
00154                     a.take(input(qt));
00155                   qt_dir++;
00156                 }
00157               if (input.has(p))
00158                 output(p) = a.to_result();
00159 
00160               // Browse the line.
00161               // ----------------
00162 
00163               while (p_dir < pmax_dir)
00164                 {
00165                   if (input.has(qt))
00166                     a.take(input(qt));
00167                   qt_dir++;
00168 
00169                   if (input.has(qu))
00170                     a.untake(input(qu));
00171                   qu_dir++;
00172 
00173                   ++p_dir;
00174                   if (input.has(p))
00175                     output(p) = a.to_result();
00176                 }
00177 
00178               // Go to the next line.
00179               // --------------------
00180 
00181               p_dir = pmin_dir;
00182 
00183               for (int c = P::dim - 1; c >= 0; --c)
00184                 {
00185                   if (c == int(dir))
00186                     continue;
00187                   if (p[c] != pmax[c])
00188                     {
00189                       ++p[c];
00190                       break;
00191                     }
00192                   p[c] = pmin[c];
00193                 }
00194 
00195             } while (p != pmin);
00196 
00197           trace::exiting("accu::impl::transform_line");
00198           return output;
00199         }
00200 
00201       } // end of namespace mln::accu::impl::generic
00202 
00203 
00204       template <typename A, typename I>
00205       inline
00206       mln_ch_value(I, mln_result(A))
00207       transform_line_fastest(const Accumulator<A>& a_,
00208                              const Image<I>& input_,
00209                              unsigned length, unsigned dir)
00210       {
00211         trace::entering("accu::impl::transform_line_fastest");
00212 
00213         const I& input = exact(input_);
00214         A a = exact(a_);
00215 
00216         internal::transform_line_tests(a, input);
00217 
00218         extension::adjust(input, length / 2); // Safety.
00219 
00220         mln_ch_value(I, mln_result(A)) output;
00221         initialize(output, input);
00222 
00223         typedef mln_psite(I) P;
00224         const P
00225           pmin = input.domain().pmin(),
00226           pmax = input.domain().pmax();
00227         const def::coord
00228           pmax_dir = pmax[dir],
00229           pmin_dir = pmin[dir];
00230 
00231         P p = pmin; // Starting point.
00232         def::coord& p_dir  = p[dir];
00233         
00234         // Step.
00235         mln_delta(P) dp(literal::zero);
00236         dp[dir] = 1;
00237         int step = input.delta_index(dp);
00238 
00239         do
00240           {
00241             // Start the line.
00242             // ---------------
00243 
00244             unsigned o_p = input.index_of_point(p);
00245             unsigned o_qt = o_p - (length / 2) * step;
00246             unsigned o_qu = o_qt;
00247             a.init();
00248 
00249             for (unsigned i = 0; i < length; ++i)
00250               // t o | x o o
00251               //    ...
00252               // o o | x o t
00253               {
00254                 a.take(input.element(o_qt));
00255                 o_qt += step;
00256               }
00257             output.element(o_p) = a.to_result();
00258 
00259             // Browse the line.
00260             // ----------------
00261 
00262             while (p_dir < pmax_dir)
00263               // u o | o x o t
00264               //               ...
00265               //                   u o o x | o t
00266               {
00267                 a.take(input.element(o_qt));
00268                 o_qt += step;
00269 
00270                 a.untake(input.element(o_qu));
00271                 o_qu += step;
00272 
00273                 ++p_dir;
00274                 o_p += step;
00275                 output.element(o_p) = a.to_result();
00276               }
00277 
00278             // Go to the next line.
00279             // --------------------
00280 
00281             p_dir = pmin_dir;
00282 
00283             for (int c = P::dim - 1; c >= 0; --c)
00284               {
00285                 if (c == int(dir))
00286                   continue;
00287                 if (p[c] != pmax[c])
00288                   {
00289                     ++p[c];
00290                     break;
00291                   }
00292                 p[c] = pmin[c];
00293               }
00294 
00295           } while (p != pmin);
00296         
00297         trace::exiting("accu::impl::transform_line_fastest");
00298         return output;
00299       }
00300 
00301       /*
00302 
00303       template <typename A, typename I>
00304       inline
00305       mln_ch_value(I, mln_result(A))
00306         transform_line_fastest_without_border(const Accumulator<A>& a_,
00307                                               const Image<I>& input_,
00308                                               unsigned length, unsigned dir)
00309       {
00310         trace::entering("accu::impl::transform_line_fastest_without_border");
00311 
00312         const I& input = exact(input_);
00313         A a = exact(a_);
00314 
00315         internal::transform_line_tests(a, input);
00316 
00317         mln_ch_value(I, mln_result(A)) output;
00318         initialize(output, input);
00319 
00320         typedef mln_psite(I) P;
00321         const P
00322           pmin = input.domain().pmin(),
00323           pmax = input.domain().pmax();
00324         const def::coord
00325           pmax_dir = pmax[dir] - length / 2,
00326           pmin_dir = pmin[dir];
00327 
00328         P p = pmin; // Starting point.
00329         def::coord& p_dir  = p [dir];
00330 
00331         // Step.
00332         mln_delta(P) dp(literal::zero);
00333         dp[dir] = 1;
00334         int step = input.delta_index(dp);
00335 
00336         do
00337           {
00338             // Start the line.
00339             // ---------------
00340 
00341             unsigned o_p = input.index_of_point(p);
00342             unsigned o_qt = o_p;
00343             unsigned o_qu = o_p;
00344             
00345             a.init();
00346 
00347             // Causal part.
00348             for (unsigned i = 0; i <= length / 2; ++i)
00349               // | t
00350               // | x t
00351               // | x o t
00352               {
00353                 a.take(input.element(o_qt));
00354                 o_qt += step;
00355               }
00356             output.element(o_p) = a.to_result();
00357 
00358             // Non-causal part.
00359             for (unsigned i = 0; i < length / 2; ++i)
00360               // | x o o     <- end of previous loop
00361               // | o x o t
00362               // | o o x o t
00363               {
00364                 a.take(input.element(o_qt));
00365                 o_qt += step;
00366                 
00367                 ++p_dir;
00368                 o_p += step;
00369                 output.element(o_p) = a.to_result();
00370               }
00371 
00372             // Browse the line.
00373             // ----------------
00374 
00375             while (p_dir < pmax_dir)
00376               // from .. o o x o o   ..
00377               // to   .. u o o x o t ..
00378               {
00379                 a.take(input.element(o_qt));
00380                 o_qt += step;
00381 
00382                 a.untake(input.element(o_qu));
00383                 o_qu += step;
00384 
00385                 ++p_dir;
00386                 o_p += step;
00387                 output.element(o_p) = a.to_result();
00388               }
00389 
00390             // Finalize.
00391             // ---------
00392 
00393             for (unsigned i = 0; i < length / 2; ++i)
00394               // o o x o o | <- end of previous loop
00395               // u o o x o |
00396               //   u o o x |
00397               {
00398                 a.untake(input.element(o_qu));
00399                 o_qu += step;
00400                 
00401                 o_p += step;
00402                 output.element(o_p) = a.to_result();
00403               }
00404 
00405             // Go to the next line.
00406             // --------------------
00407 
00408             p_dir = pmin_dir;
00409 
00410             for (int c = P::dim - 1; c >= 0; --c)
00411               {
00412                 if (c == int(dir))
00413                   continue;
00414                 if (p[c] != pmax[c])
00415                   {
00416                     ++p[c];
00417                     break;
00418                   }
00419                 p[c] = pmin[c];
00420               }
00421 
00422           } while (p != pmin);
00423         
00424         trace::exiting("accu::impl::transform_line_fastest_without_border");
00425         return output;
00426       }
00427 
00428       */
00429 
00430     } // end of namespace mln::accu::impl
00431 
00432 
00433 
00434 
00435     // Dispatch.
00436 
00437 
00438     namespace internal
00439     {
00440 
00441       template <typename A, typename I>
00442       inline
00443       mln_ch_value(I, mln_result(A))
00444       transform_line_dispatch(trait::image::speed::any,
00445                               trait::accumulator::when_pix::any,
00446                               const Accumulator<A>& a,
00447                               const Image<I>& input,
00448                               unsigned length, unsigned dir)
00449       {
00450         return impl::generic::transform_line(a,
00451                                              input,
00452                                              length, dir);
00453       }
00454 
00455       template <typename A, typename I>
00456       inline
00457       mln_ch_value(I, mln_result(A))
00458       transform_line_dispatch(trait::image::speed::fastest,
00459                               trait::accumulator::when_pix::use_none,
00460                               const Accumulator<A>& a,
00461                               const Image<I>& input,
00462                               unsigned length, unsigned dir)
00463       {
00464         return impl::transform_line_fastest(a,
00465                                             input,
00466                                             length, dir);
00467       }
00468 
00469       template <typename A, typename I>
00470       inline
00471       mln_ch_value(I, mln_result(A))
00472       transform_line_dispatch(trait::image::speed::fastest,
00473                               trait::accumulator::when_pix::use_v,
00474                               const Accumulator<A>& a,
00475                               const Image<I>& input,
00476                               unsigned length, unsigned dir)
00477       {
00478         return impl::transform_line_fastest(a,
00479                                             input,
00480                                             length, dir);
00481       }
00482 
00483       template <typename A, typename I>
00484       inline
00485       mln_ch_value(I, mln_result(A))
00486       transform_line_dispatch(const Accumulator<A>& a,
00487                               const Image<I>& input,
00488                               unsigned length, unsigned dir)
00489       {
00490         return transform_line_dispatch(mln_trait_image_speed(I)(),
00491                                        mln_trait_accumulator_when_pix(A)(),
00492                                        a, input, length, dir);
00493       }
00494 
00495     } // end of namespace mln::accu::internal
00496 
00497 
00498 
00499 
00500     // Facades.
00501 
00502 
00503     template <typename A, typename I>
00504     inline
00505     mln_ch_value(I, mln_result(A))
00506     transform_line(const Accumulator<A>& a,
00507                    const Image<I>& input,
00508                    unsigned length, unsigned dir)
00509     {
00510       trace::entering("accu::transform_line");
00511 
00512       internal::transform_line_tests(a, input);
00513 
00514       extension::adjust(input, length / 2); // Safety.
00515 
00516       mln_ch_value(I, mln_result(A)) output;
00517       output = internal::transform_line_dispatch(a, input, length, dir);
00518 
00519       trace::exiting("accu::transform_line");
00520       return output;
00521     }
00522 
00523 
00524     template <typename A, typename I>
00525     inline
00526     mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00527     transform_line(const Meta_Accumulator<A>& a,
00528                    const Image<I>& input,
00529                    unsigned length, unsigned dir)
00530     {
00531       trace::entering("accu::transform_line");
00532 
00533       typedef mln_accu_with(A, mln_value(I)) A_;
00534       A_ a_ = accu::unmeta(exact(a), mln_value(I)());
00535 
00536       internal::transform_line_tests(a_, input);
00537           
00538       mln_ch_value(I, mln_result(A_)) output;
00539       output = internal::transform_line_dispatch(a_, input, length, dir);
00540 
00541       trace::exiting("accu::transform_line");
00542       return output;
00543     }
00544 
00545 
00546 # endif // ! MLN_INCLUDE_ONLY
00547 
00548   } // end of namespace mln::accu
00549 
00550 } // end of namespace mln
00551 
00552 
00553 #endif // ! MLN_ACCU_TRANSFORM_LINE_HH

Generated on Tue Oct 4 2011 15:24:44 for Milena (Olena) by  doxygen 1.7.1