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

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