[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/basicgeometry.hxx

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    The VIGRA Website is                                              */
00008 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00009 /*    Please direct questions, bug reports, and contributions to        */
00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00011 /*        vigra@informatik.uni-hamburg.de                               */
00012 /*                                                                      */
00013 /*    Permission is hereby granted, free of charge, to any person       */
00014 /*    obtaining a copy of this software and associated documentation    */
00015 /*    files (the "Software"), to deal in the Software without           */
00016 /*    restriction, including without limitation the rights to use,      */
00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00018 /*    sell copies of the Software, and to permit persons to whom the    */
00019 /*    Software is furnished to do so, subject to the following          */
00020 /*    conditions:                                                       */
00021 /*                                                                      */
00022 /*    The above copyright notice and this permission notice shall be    */
00023 /*    included in all copies or substantial portions of the             */
00024 /*    Software.                                                         */
00025 /*                                                                      */
00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00034 /*                                                                      */
00035 /************************************************************************/
00036  
00037 #ifndef VIGRA_BASICGEOMETRY_HXX
00038 #define VIGRA_BASICGEOMETRY_HXX
00039 
00040 #include "error.hxx"
00041 #include "stdimage.hxx"
00042 #include "copyimage.hxx"
00043 #include <cmath>
00044 
00045 namespace vigra {
00046 
00047 /** \addtogroup GeometricTransformations Geometric Transformations
00048 */
00049 //@{
00050 
00051 /********************************************************/
00052 /*                                                      */
00053 /*                      rotateImage                     */
00054 /*                                                      */
00055 /********************************************************/
00056 
00057 /** \brief Rotate image by a multiple of 90 degrees.
00058 
00059     This algorithm just copies the pixels in the appropriate new order. It expects the 
00060     destination image to have the correct shape for the desired rotation.
00061     
00062     <b> Declarations:</b>
00063     
00064     pass arguments explicitly:
00065     \code
00066     namespace vigra {
00067         template <class SrcIterator, class SrcAccessor,
00068                   class DestIterator, class DestAccessor>
00069         void 
00070         rotateImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00071                     DestIterator id, DestAccessor ad, int rotation);
00072     }
00073     \endcode
00074     
00075     use argument objects in conjunction with \ref ArgumentObjectFactories :
00076     \code
00077     namespace vigra {
00078         template <class SrcImageIterator, class SrcAccessor,
00079               class DestImageIterator, class DestAccessor>
00080         inline void 
00081         rotateImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00082                     pair<DestImageIterator, DestAccessor> dest, int rotation);
00083     }
00084     \endcode
00085     
00086     <b> Usage:</b>
00087     
00088         <b>\#include</b> <<a href="basicgeometry_8hxx-source.html">vigra/basicgeometry.hxx</a>><br>
00089         Namespace: vigra
00090     
00091     \code
00092     Image dest(src.height(), src.width()); // note that width and height are exchanged
00093     
00094     vigra::rotateImage(srcImageRange(src), destImage(dest), 90);
00095     
00096     \endcode
00097 
00098     <b> Required Interface:</b>
00099     
00100     \code
00101     SrcImageIterator src_upperleft, src_lowerright;
00102     DestImageIterator dest_upperleft;
00103     
00104     SrcAccessor src_accessor;
00105     
00106     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00107 
00108     \endcode
00109     
00110     <b> Preconditions:</b>
00111     
00112     \code
00113     src_lowerright.x - src_upperleft.x > 1
00114     src_lowerright.y - src_upperleft.y > 1
00115     \endcode
00116     
00117 */
00118 doxygen_overloaded_function(template <...> void rotateImage)
00119 
00120 template <class SrcIterator, class SrcAccessor, 
00121           class DestIterator, class DestAccessor>
00122 void rotateImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00123                            DestIterator id, DestAccessor ad, int rotation)
00124 {
00125     int x, y;
00126     int ws = end.x - is.x;
00127     int hs = end.y - is.y;
00128 
00129     vigra_precondition(rotation % 90 == 0, 
00130                 "rotateImage(): "
00131                 "This function rotates images only about multiples of 90 degree");
00132 
00133     rotation = rotation%360; 
00134     if (rotation < 0)
00135         rotation += 360;
00136     
00137     switch(rotation)
00138     {
00139         case 0:
00140             copyImage(is, end, as, id, ad);
00141             break;
00142         case 90: 
00143             is.x += (ws-1);
00144             for(x=0; x != ws; x++, is.x--, id.y++)
00145             {
00146                 typename SrcIterator::column_iterator cs = is.columnIterator();
00147                 typename DestIterator::row_iterator rd = id.rowIterator();
00148                 for(y=0; y != hs; y++, cs++, rd++)
00149                 {
00150                     ad.set(as(cs), rd);
00151                 }
00152         
00153             }
00154             break;
00155 
00156         case 180:
00157             end.x--;
00158             end.y--;
00159             for(x=0; x != ws; x++, end.x--, id.x++)
00160             {
00161                 typename SrcIterator::column_iterator cs = end.columnIterator();
00162                 typename DestIterator::column_iterator cd = id.columnIterator();
00163                 for(y=0; y != hs; y++, cs--, cd++)
00164                 {
00165                     ad.set(as(cs), cd);
00166                 }
00167         
00168             }
00169             break;
00170 
00171         case 270:  
00172             is.y += (hs-1);
00173             for(x=0; x != ws; x++, is.x++, id.y++)
00174             {
00175                 typename SrcIterator::column_iterator cs = is.columnIterator();
00176                 typename DestIterator::row_iterator rd = id.rowIterator();
00177                 for(y=0; y != hs; y++, cs--, rd++)
00178                 {
00179                     ad.set(as(cs), rd);
00180                 }
00181         
00182             }
00183             break;
00184         default: //not needful, because of the exception handig in if-statement 
00185             vigra_fail("internal error"); 
00186     }
00187 }
00188 
00189 template <class SrcImageIterator, class SrcAccessor,
00190           class DestImageIterator, class DestAccessor>
00191 inline void 
00192 rotateImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00193               pair<DestImageIterator, DestAccessor> dest, int rotation)
00194 {
00195     rotateImage(src.first, src.second, src.third, dest.first, dest.second, rotation);
00196 }
00197 
00198 /********************************************************/
00199 /*                                                      */
00200 /*                     reflectImage                     */
00201 /*                                                      */
00202 /********************************************************/
00203 
00204 enum Reflect{horizontal = 1, vertical = 2};
00205 
00206 /** \brief Reflect image horizontally or vertically.
00207 
00208     The reflection direction refers to the reflection axis, i.e.
00209     horizontal reflection turns the image upside down, vertical reflection
00210     changes left for right. The directions are selected by the enum values
00211     <tt>vigra::horizontal</tt> and <tt>vigra::vertical</tt>. The two directions 
00212     can also be "or"ed together to perform both reflections simultaneously 
00213     (see example below) -- this is the same as a 180 degree rotation. 
00214     
00215     <b> Declarations:</b>
00216     
00217     pass arguments explicitly:
00218     \code
00219     namespace vigra {
00220         template <class SrcIterator, class SrcAccessor,
00221                   class DestIterator, class DestAccessor>
00222         void 
00223         reflectImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00224                      DestIterator id, DestAccessor ad, Reflect axis);
00225     }
00226     \endcode
00227     
00228     use argument objects in conjunction with \ref ArgumentObjectFactories :
00229     \code
00230     namespace vigra {
00231         template <class SrcImageIterator, class SrcAccessor,
00232               class DestImageIterator, class DestAccessor>
00233         inline void 
00234         reflectImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00235                      pair<DestImageIterator, DestAccessor> dest, Reflect axis);
00236     }
00237     \endcode
00238     
00239     <b> Usage:</b>
00240     
00241         <b>\#include</b> <<a href="basicgeometry_8hxx-source.html">vigra/basicgeometry.hxx</a>><br>
00242         Namespace: vigra
00243     
00244     \code
00245     Image dest(src.width(), src.height());
00246     
00247     vigra::reflectImage(srcImageRange(src), destImage(dest), vigra::horizontal | vigra::vertical);
00248     
00249     \endcode
00250 
00251     <b> Required Interface:</b>
00252     
00253     \code
00254     SrcImageIterator src_upperleft, src_lowerright;
00255     DestImageIterator dest_upperleft;
00256     
00257     SrcAccessor src_accessor;
00258     
00259     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00260 
00261     \endcode
00262     
00263     <b> Preconditions:</b>
00264     
00265     \code
00266     src_lowerright.x - src_upperleft.x > 1
00267     src_lowerright.y - src_upperleft.y > 1
00268     \endcode
00269     
00270 */
00271 doxygen_overloaded_function(template <...> void reflectImage)
00272 
00273 template <class SrcIterator, class SrcAccessor, 
00274           class DestIterator, class DestAccessor>
00275 void reflectImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00276                   DestIterator id, DestAccessor ad, Reflect reflect)
00277 {
00278     
00279     int ws = end.x - is.x;
00280     int hs = end.y - is.y;
00281 
00282     int x, y;
00283 
00284     if(reflect == horizontal)
00285     {//flipImage
00286         is.y += (hs-1);
00287         for(x=0; x<ws; ++x, ++is.x, ++id.x) 
00288         {
00289             typename SrcIterator::column_iterator  cs = is.columnIterator();
00290             typename DestIterator::column_iterator cd = id.columnIterator();
00291             for(y=0; y!=hs;y++, cs--, cd++)
00292             {
00293                 ad.set(as(cs), cd);
00294             }
00295         }
00296     }
00297     else if(reflect == vertical)
00298     {//flopImage
00299         is.x += (ws-1);
00300         for(x=0; x < ws; ++x, --is.x, ++id.x) 
00301         {
00302 
00303             typename SrcIterator::column_iterator cs = is.columnIterator();
00304             typename DestIterator::column_iterator cd = id.columnIterator();
00305             for(y=0; y!=hs;y++, cs++, cd++)
00306             {
00307                 ad.set(as(cs), cd);
00308             }
00309         }
00310     }
00311     else if(reflect == (horizontal | vertical))
00312     {//flipFlopImage   //???
00313         end.x--;
00314         end.y--;
00315         for(x=0; x != ws; x++, end.x--, id.x++)
00316         {
00317             typename SrcIterator::column_iterator cs = end.columnIterator();
00318             typename DestIterator::column_iterator cd = id.columnIterator();
00319             for(y=0; y != hs; y++, cs--, cd++)
00320             {
00321                 ad.set(as(cs), cd);
00322             }
00323         }
00324     }
00325     else 
00326         vigra_fail("reflectImage(): "
00327                    "This function reflects horizontal or vertical,"
00328                    "   'and' is included");
00329 }
00330 
00331 template <class SrcImageIterator, class SrcAccessor,
00332           class DestImageIterator, class DestAccessor>
00333 inline void 
00334 reflectImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00335               pair<DestImageIterator, DestAccessor> dest, Reflect reflect)
00336 {
00337     reflectImage(src.first, src.second, src.third, dest.first, dest.second, reflect);
00338 }
00339 
00340 /********************************************************/
00341 /*                                                      */
00342 /*                    transposeImage                   */
00343 /*                                                      */
00344 /********************************************************/
00345 
00346 enum Transpose{major = 1, minor = 2};
00347 
00348 /** \brief Transpose an image over the major or minor diagonal.
00349 
00350     The transposition direction refers to the axis, i.e.
00351     major transposition turns the upper right corner into the lower left one, 
00352     whereas minor transposition changes the upper left corner into the lower right one. 
00353     The directions are selected by the enum values
00354     <tt>vigra::major</tt> and <tt>vigra::minor</tt>. The two directions 
00355     can also be "or"ed together to perform both reflections simultaneously 
00356     (see example below) -- this is the same as a 180 degree rotation.
00357     
00358     <b> Declarations:</b>
00359     
00360     pass arguments explicitly:
00361     \code
00362     namespace vigra {
00363         template <class SrcIterator, class SrcAccessor,
00364                   class DestIterator, class DestAccessor>
00365         void 
00366         transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00367                        DestIterator id, DestAccessor ad, Transpose axis);
00368     }
00369     \endcode
00370     
00371     use argument objects in conjunction with \ref ArgumentObjectFactories :
00372     \code
00373     namespace vigra {
00374         template <class SrcImageIterator, class SrcAccessor,
00375               class DestImageIterator, class DestAccessor>
00376         inline void 
00377         transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00378                        pair<DestImageIterator, DestAccessor> dest, Transpose axis);
00379     }
00380     \endcode
00381     
00382     <b> Usage:</b>
00383     
00384         <b>\#include</b> <<a href="basicgeometry_8hxx-source.html">vigra/basicgeometry.hxx</a>><br>
00385         Namespace: vigra
00386     
00387     \code
00388     Image dest(src.width(), src.height());
00389     
00390     vigra::transposeImage(srcImageRange(src), destImage(dest), vigra::major | vigra::minor);
00391     
00392     \endcode
00393 
00394     <b> Required Interface:</b>
00395     
00396     \code
00397     SrcImageIterator src_upperleft, src_lowerright;
00398     DestImageIterator dest_upperleft;
00399     
00400     SrcAccessor src_accessor;
00401     
00402     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00403 
00404     \endcode
00405     
00406     <b> Preconditions:</b>
00407     
00408     \code
00409     src_lowerright.x - src_upperleft.x > 1
00410     src_lowerright.y - src_upperleft.y > 1
00411     \endcode
00412     
00413 */
00414 doxygen_overloaded_function(template <...> void transposeImage)
00415 
00416 template <class SrcIterator, class SrcAccessor, 
00417           class DestIterator, class DestAccessor>
00418 void transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00419                     DestIterator id, DestAccessor ad, Transpose transpose)
00420 {
00421     int ws = end.x - is.x;
00422     int hs = end.y - is.y;
00423 
00424     int x, y;
00425 
00426     if(transpose == major)
00427     {//Die Funktion spiegelt das Bild um (0,0) (1,1) Diagonale
00428         for(x=0; x != ws; x++, is.x++, id.y++)
00429         {
00430 
00431             typename SrcIterator::column_iterator cs = is.columnIterator();
00432             typename DestIterator::row_iterator rd = id.rowIterator();
00433             for(y=0; y != hs; y++, cs++, rd++)
00434             {
00435                 ad.set(as(cs), rd);
00436             }
00437         }
00438     }
00439     else if(transpose == minor)
00440     {//Die Funktion spiegelt das Bild (1,0) (0,1) Diagonale
00441         end.x--;
00442         end.y--;
00443         for(x=0; x != ws; x++, --end.x, ++id.y)
00444         {
00445 
00446             typename SrcIterator::column_iterator cs = end.columnIterator();
00447             typename DestIterator::row_iterator rd = id.rowIterator();
00448             for(y=0; y != hs; y++, --cs, ++rd)
00449             {
00450                 ad.set(as(cs), rd);
00451             }
00452         }
00453     }
00454     else if(transpose == (major | minor))
00455     {//flipFlopImage  //???
00456         end.x--;
00457         end.y--;
00458         for(x=0; x != ws; x++, end.x--, id.x++)
00459         {
00460             typename SrcIterator::column_iterator cs = end.columnIterator();
00461             typename DestIterator::column_iterator cd = id.columnIterator();
00462             for(y=0; y != hs; y++, cs--, cd++)
00463             {
00464                 ad.set(as(cs), cd);
00465             }
00466         }
00467     
00468     }
00469     else 
00470         vigra_fail("transposeImage(): "
00471                    "This function transposes major or minor,"
00472                    "   'and' is included");
00473 
00474 }
00475 
00476 template <class SrcImageIterator, class SrcAccessor,
00477           class DestImageIterator, class DestAccessor>
00478 inline void 
00479 transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00480               pair<DestImageIterator, DestAccessor> dest, Transpose transpose)
00481 {
00482     transposeImage(src.first, src.second, src.third, dest.first, dest.second, transpose);
00483 }
00484 
00485 /********************************************************/
00486 /*                                                      */
00487 /*                        resampleLine                  */
00488 /*                                                      */
00489 /********************************************************/
00490 
00491 /*
00492 * Vergroessert eine Linie um einen Faktor. 
00493 * Ist z.B. der Faktor = 4 so werden in der
00494 * neuen Linie(Destination) jedes Pixel genau 4 mal 
00495 * vorkommen, also es findet auch keine Glaetung 
00496 * statt (NoInterpolation). Als Parameter sollen
00497 * der Anfangs-, der Enditerator und der Accessor
00498 * der Ausgangslinie (Source line), der Anfangsiterator
00499 * und Accessor der Ziellinie (destination line) und
00500 * anschliessend der Faktor um den die Linie (Zeile)
00501 * vergroessert bzw. verkleinert werden soll. 
00502 */
00503 template <class SrcIterator, class SrcAccessor, 
00504           class DestIterator, class DestAccessor>
00505 void resampleLine(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
00506                   DestIterator dest_iter, DestAccessor dest_acc, double factor)
00507 {
00508     // The width of the src line.      
00509     int src_width = src_iter_end - src_iter;
00510  
00511     vigra_precondition(src_width > 0,
00512                        "resampleLine(): input image too small.");
00513     vigra_precondition(factor > 0.0,
00514                        "resampleLine(): factor must be positive.");
00515     
00516     if (factor >= 1.0)
00517     {
00518         int int_factor = (int)factor;
00519         double dx = factor - int_factor;
00520         double saver = dx;
00521         for ( ; src_iter != src_iter_end ; ++src_iter, saver += dx)
00522         {
00523             if (saver >= 1.0)
00524             {
00525                 saver = saver - (int)saver;
00526                 dest_acc.set(src_acc(src_iter), dest_iter);
00527                 ++dest_iter;
00528             }
00529             for(int i = 0 ; i < int_factor ; i++, ++dest_iter)
00530             {
00531                 dest_acc.set(src_acc(src_iter), dest_iter);
00532             }
00533         }
00534     }
00535     else
00536     {
00537         DestIterator dest_end = dest_iter + (int)VIGRA_CSTD::ceil(src_width*factor);  
00538         factor = 1.0/factor;
00539         int int_factor = (int)factor;
00540         double dx = factor - int_factor;
00541         double saver = dx;
00542         src_iter_end -= 1;
00543         for ( ; src_iter != src_iter_end && dest_iter != dest_end ; 
00544               ++dest_iter, src_iter += int_factor, saver += dx)
00545         {
00546             if (saver >= 1.0)
00547             {
00548                 saver = saver - (int)saver;
00549                 ++src_iter;
00550             }
00551             dest_acc.set(src_acc(src_iter), dest_iter);
00552         }
00553         if (dest_iter != dest_end)
00554         {
00555             dest_acc.set(src_acc(src_iter_end), dest_iter);
00556         }
00557     }
00558 }
00559 
00560 inline int sizeForResamplingFactor(int oldsize, double factor)
00561 {
00562     return (factor < 1.0)
00563         ? (int)VIGRA_CSTD::ceil(oldsize * factor) 
00564         : (int)(oldsize * factor);
00565 }
00566 
00567 
00568 /********************************************************/
00569 /*                                                      */
00570 /*                     resampleImage                    */
00571 /*                                                      */
00572 /********************************************************/
00573 
00574 /** \brief Resample image by a given factor.
00575 
00576     This algorithm is very fast and does not require any arithmetic on the pixel types.    
00577     The input image must have a size of at
00578     least 2x2. Destiniation pixels are directly copied from the appropriate
00579     source pixels. The size of the result image is the product of <tt>factor</tt>
00580     and the original size, where we round up if <tt>factor < 1.0</tt> and down otherwise.
00581     This size calculation is the main difference to the convention used in the similar 
00582     function \ref resizeImageNoInterpolation():
00583     there, the result size is calculated as <tt>n*(old_width-1)+1</tt> and 
00584     <tt>n*(old_height-1)+1</tt>. This is because \ref resizeImageNoInterpolation() 
00585     does not replicate the last pixel in every row/column in order to make it compatible
00586     with the other functions of the <tt>resizeImage...</tt> family.
00587     
00588     The function can be called with different resampling factors for x and y, or
00589     with a single factor to be used for both directions.
00590 
00591     It should also be noted that resampleImage() is implemented so that an enlargement followed
00592     by the corresponding shrinking reproduces the original image. The function uses accessors. 
00593     
00594     <b> Declarations:</b>
00595     
00596     pass arguments explicitly:
00597     \code
00598     namespace vigra {
00599         template <class SrcIterator, class SrcAccessor,
00600                   class DestIterator, class DestAccessor>
00601         void 
00602         resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00603                       DestIterator id, DestAccessor ad, double factor);
00604                       
00605         template <class SrcIterator, class SrcAccessor,
00606                   class DestIterator, class DestAccessor>
00607         void 
00608         resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00609                       DestIterator id, DestAccessor ad, double xfactor, double yfactor);
00610     }
00611     \endcode
00612     
00613     use argument objects in conjunction with \ref ArgumentObjectFactories :
00614     \code
00615     namespace vigra {
00616         template <class SrcImageIterator, class SrcAccessor,
00617               class DestImageIterator, class DestAccessor>
00618         inline void 
00619         resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00620                       pair<DestImageIterator, DestAccessor> dest, double factor);
00621                       
00622         template <class SrcImageIterator, class SrcAccessor,
00623               class DestImageIterator, class DestAccessor>
00624         inline void 
00625         resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00626                       pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor);
00627     }
00628     \endcode
00629     
00630     <b> Usage:</b>
00631     
00632         <b>\#include</b> <<a href="basicgeometry_8hxx-source.html">vigra/basicgeometry.hxx</a>><br>
00633         Namespace: vigra
00634     
00635     \code
00636     double factor = 2.0;
00637     Image dest((int)(factor*src.width()), (int)(factor*src.height()));
00638     
00639     vigra::resampleImage(srcImageRange(src), destImage(dest), factor);
00640     
00641     \endcode
00642 
00643     <b> Required Interface:</b>
00644     
00645     \code
00646     SrcImageIterator src_upperleft, src_lowerright;
00647     DestImageIterator dest_upperleft;
00648     
00649     SrcAccessor src_accessor;
00650     
00651     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00652 
00653     \endcode
00654     
00655     <b> Preconditions:</b>
00656     
00657     \code
00658     src_lowerright.x - src_upperleft.x > 1
00659     src_lowerright.y - src_upperleft.y > 1
00660     \endcode
00661     
00662 */
00663 doxygen_overloaded_function(template <...> void resampleImage)
00664 
00665 template <class SrcIterator, class SrcAccessor,
00666           class DestIterator, class DestAccessor>
00667 void 
00668 resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00669               DestIterator id, DestAccessor ad, double xfactor, double yfactor)
00670 {
00671     int width_old = iend.x - is.x;
00672     int height_old = iend.y - is.y;
00673     
00674     //Bei Verkleinerung muss das dest-Bild ceiling(src*factor), da z.B.
00675     //aus 6x6 grossem Bild wird eins 18x18 grosses gemacht bei Vergroesserungsfaktor 3.1
00676     //umgekehrt damit wir vom 18x18 zu 6x6 (und nicht 5x5) bei Vergroesserung von 1/3.1
00677     //muss das kleinste Integer das groesser als 18/3.1 ist genommen werden.
00678     int height_new = sizeForResamplingFactor(height_old, yfactor);
00679     int width_new = sizeForResamplingFactor(width_old, xfactor);
00680     
00681     vigra_precondition((width_old > 1) && (height_old > 1),
00682                  "resampleImage(): "
00683                  "Source image to small.\n");
00684     vigra_precondition((width_new > 1) && (height_new > 1),
00685                  "resampleImage(): "
00686                  "Destination image to small.\n");
00687         
00688     typedef typename SrcAccessor::value_type SRCVT;
00689     typedef BasicImage<SRCVT> TmpImage;
00690     typedef typename TmpImage::traverser TmpImageIterator;
00691 
00692     BasicImage<SRCVT> tmp(width_old, height_new);
00693     
00694     int x,y;
00695     
00696     typename BasicImage<SRCVT>::Iterator yt = tmp.upperLeft();
00697 
00698     for(x=0; x<width_old; ++x, ++is.x, ++yt.x) 
00699     {
00700         typename SrcIterator::column_iterator c1 = is.columnIterator();
00701         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
00702         resampleLine(c1, c1 + height_old, sa, ct, tmp.accessor(), yfactor);
00703     }
00704 
00705     yt = tmp.upperLeft();
00706 
00707     for(y=0; y < height_new; ++y, ++yt.y, ++id.y) 
00708     {
00709         typename DestIterator::row_iterator rd = id.rowIterator();
00710         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
00711         resampleLine(rt, rt + width_old, tmp.accessor(), rd, ad, xfactor);
00712     }
00713 
00714 }
00715 
00716 template <class SrcIterator, class SrcAccessor,
00717           class DestIterator, class DestAccessor>
00718 void 
00719 resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00720               DestIterator id, DestAccessor ad, double factor)
00721 {
00722   resampleImage(is, iend, sa, id, ad, factor, factor);
00723 }
00724 
00725 template <class SrcImageIterator, class SrcAccessor,
00726           class DestImageIterator, class DestAccessor>
00727 inline void 
00728 resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00729               pair<DestImageIterator, DestAccessor> dest, double factor)
00730 {
00731   resampleImage(src.first, src.second, src.third, dest.first, dest.second, factor);
00732 }
00733 
00734 template <class SrcImageIterator, class SrcAccessor,
00735           class DestImageIterator, class DestAccessor>
00736 inline void 
00737 resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00738               pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor)
00739 {
00740   resampleImage(src.first, src.second, src.third, dest.first, dest.second, xfactor, yfactor);
00741 }
00742 
00743 //@}
00744 
00745 } // namespace vigra
00746 
00747 
00748 #endif /* VIGRA_BASICGEOMETRY_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (5 Nov 2009)