[ 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 // names clash with sys/types.h on Mac OS / Darwin, see docs below
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     (Caution: When doing multi-platform development, you should be
00358     aware that some <sys/types.h> define major/minor, too.  Do not omit
00359     the vigra namespace prefix.)
00360     
00361     <b> Declarations:</b>
00362     
00363     pass arguments explicitly:
00364     \code
00365     namespace vigra {
00366         template <class SrcIterator, class SrcAccessor,
00367                   class DestIterator, class DestAccessor>
00368         void 
00369         transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00370                        DestIterator id, DestAccessor ad, Transpose axis);
00371     }
00372     \endcode
00373     
00374     use argument objects in conjunction with \ref ArgumentObjectFactories :
00375     \code
00376     namespace vigra {
00377         template <class SrcImageIterator, class SrcAccessor,
00378               class DestImageIterator, class DestAccessor>
00379         inline void 
00380         transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00381                        pair<DestImageIterator, DestAccessor> dest, Transpose axis);
00382     }
00383     \endcode
00384     
00385     <b> Usage:</b>
00386     
00387         <b>\#include</b> <<a href="basicgeometry_8hxx-source.html">vigra/basicgeometry.hxx</a>><br>
00388         Namespace: vigra
00389     
00390     \code
00391     Image dest(src.width(), src.height());
00392     
00393     vigra::transposeImage(srcImageRange(src), destImage(dest), vigra::major | vigra::minor);
00394     
00395     \endcode
00396 
00397     <b> Required Interface:</b>
00398     
00399     \code
00400     SrcImageIterator src_upperleft, src_lowerright;
00401     DestImageIterator dest_upperleft;
00402     
00403     SrcAccessor src_accessor;
00404     
00405     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00406 
00407     \endcode
00408     
00409     <b> Preconditions:</b>
00410     
00411     \code
00412     src_lowerright.x - src_upperleft.x > 1
00413     src_lowerright.y - src_upperleft.y > 1
00414     \endcode
00415     
00416 */
00417 doxygen_overloaded_function(template <...> void transposeImage)
00418 
00419 template <class SrcIterator, class SrcAccessor, 
00420           class DestIterator, class DestAccessor>
00421 void transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00422                     DestIterator id, DestAccessor ad, Transpose transpose)
00423 {
00424     int ws = end.x - is.x;
00425     int hs = end.y - is.y;
00426 
00427     int x, y;
00428 
00429     if(transpose == major)
00430     {//Die Funktion spiegelt das Bild um (0,0) (1,1) Diagonale
00431         for(x=0; x != ws; x++, is.x++, id.y++)
00432         {
00433 
00434             typename SrcIterator::column_iterator cs = is.columnIterator();
00435             typename DestIterator::row_iterator rd = id.rowIterator();
00436             for(y=0; y != hs; y++, cs++, rd++)
00437             {
00438                 ad.set(as(cs), rd);
00439             }
00440         }
00441     }
00442     else if(transpose == minor)
00443     {//Die Funktion spiegelt das Bild (1,0) (0,1) Diagonale
00444         end.x--;
00445         end.y--;
00446         for(x=0; x != ws; x++, --end.x, ++id.y)
00447         {
00448 
00449             typename SrcIterator::column_iterator cs = end.columnIterator();
00450             typename DestIterator::row_iterator rd = id.rowIterator();
00451             for(y=0; y != hs; y++, --cs, ++rd)
00452             {
00453                 ad.set(as(cs), rd);
00454             }
00455         }
00456     }
00457     else if(transpose == (major | minor))
00458     {//flipFlopImage  //???
00459         end.x--;
00460         end.y--;
00461         for(x=0; x != ws; x++, end.x--, id.x++)
00462         {
00463             typename SrcIterator::column_iterator cs = end.columnIterator();
00464             typename DestIterator::column_iterator cd = id.columnIterator();
00465             for(y=0; y != hs; y++, cs--, cd++)
00466             {
00467                 ad.set(as(cs), cd);
00468             }
00469         }
00470     
00471     }
00472     else 
00473         vigra_fail("transposeImage(): "
00474                    "This function transposes major or minor,"
00475                    "   'and' is included");
00476 
00477 }
00478 
00479 template <class SrcImageIterator, class SrcAccessor,
00480           class DestImageIterator, class DestAccessor>
00481 inline void 
00482 transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00483               pair<DestImageIterator, DestAccessor> dest, Transpose transpose)
00484 {
00485     transposeImage(src.first, src.second, src.third, dest.first, dest.second, transpose);
00486 }
00487 
00488 /********************************************************/
00489 /*                                                      */
00490 /*                        resampleLine                  */
00491 /*                                                      */
00492 /********************************************************/
00493 
00494 /*
00495 * Vergroessert eine Linie um einen Faktor. 
00496 * Ist z.B. der Faktor = 4 so werden in der
00497 * neuen Linie(Destination) jedes Pixel genau 4 mal 
00498 * vorkommen, also es findet auch keine Glaetung 
00499 * statt (NoInterpolation). Als Parameter sollen
00500 * der Anfangs-, der Enditerator und der Accessor
00501 * der Ausgangslinie (Source line), der Anfangsiterator
00502 * und Accessor der Ziellinie (destination line) und
00503 * anschliessend der Faktor um den die Linie (Zeile)
00504 * vergroessert bzw. verkleinert werden soll. 
00505 */
00506 template <class SrcIterator, class SrcAccessor, 
00507           class DestIterator, class DestAccessor>
00508 void resampleLine(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
00509                   DestIterator dest_iter, DestAccessor dest_acc, double factor)
00510 {
00511     // The width of the src line.      
00512     int src_width = src_iter_end - src_iter;
00513  
00514     vigra_precondition(src_width > 0,
00515                        "resampleLine(): input image too small.");
00516     vigra_precondition(factor > 0.0,
00517                        "resampleLine(): factor must be positive.");
00518     
00519     if (factor >= 1.0)
00520     {
00521         int int_factor = (int)factor;
00522         double dx = factor - int_factor;
00523         double saver = dx;
00524         for ( ; src_iter != src_iter_end ; ++src_iter, saver += dx)
00525         {
00526             if (saver >= 1.0)
00527             {
00528                 saver = saver - (int)saver;
00529                 dest_acc.set(src_acc(src_iter), dest_iter);
00530                 ++dest_iter;
00531             }
00532             for(int i = 0 ; i < int_factor ; i++, ++dest_iter)
00533             {
00534                 dest_acc.set(src_acc(src_iter), dest_iter);
00535             }
00536         }
00537     }
00538     else
00539     {
00540         DestIterator dest_end = dest_iter + (int)VIGRA_CSTD::ceil(src_width*factor);  
00541         factor = 1.0/factor;
00542         int int_factor = (int)factor;
00543         double dx = factor - int_factor;
00544         double saver = dx;
00545         src_iter_end -= 1;
00546         for ( ; src_iter != src_iter_end && dest_iter != dest_end ; 
00547               ++dest_iter, src_iter += int_factor, saver += dx)
00548         {
00549             if (saver >= 1.0)
00550             {
00551                 saver = saver - (int)saver;
00552                 ++src_iter;
00553             }
00554             dest_acc.set(src_acc(src_iter), dest_iter);
00555         }
00556         if (dest_iter != dest_end)
00557         {
00558             dest_acc.set(src_acc(src_iter_end), dest_iter);
00559         }
00560     }
00561 }
00562 
00563 inline int sizeForResamplingFactor(int oldsize, double factor)
00564 {
00565     return (factor < 1.0)
00566         ? (int)VIGRA_CSTD::ceil(oldsize * factor) 
00567         : (int)(oldsize * factor);
00568 }
00569 
00570 
00571 /********************************************************/
00572 /*                                                      */
00573 /*                     resampleImage                    */
00574 /*                                                      */
00575 /********************************************************/
00576 
00577 /** \brief Resample image by a given factor.
00578 
00579     This algorithm is very fast and does not require any arithmetic on the pixel types.    
00580     The input image must have a size of at
00581     least 2x2. Destiniation pixels are directly copied from the appropriate
00582     source pixels. The size of the result image is the product of <tt>factor</tt>
00583     and the original size, where we round up if <tt>factor < 1.0</tt> and down otherwise.
00584     This size calculation is the main difference to the convention used in the similar 
00585     function \ref resizeImageNoInterpolation():
00586     there, the result size is calculated as <tt>n*(old_width-1)+1</tt> and 
00587     <tt>n*(old_height-1)+1</tt>. This is because \ref resizeImageNoInterpolation() 
00588     does not replicate the last pixel in every row/column in order to make it compatible
00589     with the other functions of the <tt>resizeImage...</tt> family.
00590     
00591     The function can be called with different resampling factors for x and y, or
00592     with a single factor to be used for both directions.
00593 
00594     It should also be noted that resampleImage() is implemented so that an enlargement followed
00595     by the corresponding shrinking reproduces the original image. The function uses accessors. 
00596     
00597     <b> Declarations:</b>
00598     
00599     pass arguments explicitly:
00600     \code
00601     namespace vigra {
00602         template <class SrcIterator, class SrcAccessor,
00603                   class DestIterator, class DestAccessor>
00604         void 
00605         resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00606                       DestIterator id, DestAccessor ad, double factor);
00607                       
00608         template <class SrcIterator, class SrcAccessor,
00609                   class DestIterator, class DestAccessor>
00610         void 
00611         resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00612                       DestIterator id, DestAccessor ad, double xfactor, double yfactor);
00613     }
00614     \endcode
00615     
00616     use argument objects in conjunction with \ref ArgumentObjectFactories :
00617     \code
00618     namespace vigra {
00619         template <class SrcImageIterator, class SrcAccessor,
00620               class DestImageIterator, class DestAccessor>
00621         inline void 
00622         resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00623                       pair<DestImageIterator, DestAccessor> dest, double factor);
00624                       
00625         template <class SrcImageIterator, class SrcAccessor,
00626               class DestImageIterator, class DestAccessor>
00627         inline void 
00628         resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00629                       pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor);
00630     }
00631     \endcode
00632     
00633     <b> Usage:</b>
00634     
00635         <b>\#include</b> <<a href="basicgeometry_8hxx-source.html">vigra/basicgeometry.hxx</a>><br>
00636         Namespace: vigra
00637     
00638     \code
00639     double factor = 2.0;
00640     Image dest((int)(factor*src.width()), (int)(factor*src.height()));
00641     
00642     vigra::resampleImage(srcImageRange(src), destImage(dest), factor);
00643     
00644     \endcode
00645 
00646     <b> Required Interface:</b>
00647     
00648     \code
00649     SrcImageIterator src_upperleft, src_lowerright;
00650     DestImageIterator dest_upperleft;
00651     
00652     SrcAccessor src_accessor;
00653     
00654     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00655 
00656     \endcode
00657     
00658     <b> Preconditions:</b>
00659     
00660     \code
00661     src_lowerright.x - src_upperleft.x > 1
00662     src_lowerright.y - src_upperleft.y > 1
00663     \endcode
00664     
00665 */
00666 doxygen_overloaded_function(template <...> void resampleImage)
00667 
00668 template <class SrcIterator, class SrcAccessor,
00669           class DestIterator, class DestAccessor>
00670 void 
00671 resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00672               DestIterator id, DestAccessor ad, double xfactor, double yfactor)
00673 {
00674     int width_old = iend.x - is.x;
00675     int height_old = iend.y - is.y;
00676     
00677     //Bei Verkleinerung muss das dest-Bild ceiling(src*factor), da z.B.
00678     //aus 6x6 grossem Bild wird eins 18x18 grosses gemacht bei Vergroesserungsfaktor 3.1
00679     //umgekehrt damit wir vom 18x18 zu 6x6 (und nicht 5x5) bei Vergroesserung von 1/3.1
00680     //muss das kleinste Integer das groesser als 18/3.1 ist genommen werden.
00681     int height_new = sizeForResamplingFactor(height_old, yfactor);
00682     int width_new = sizeForResamplingFactor(width_old, xfactor);
00683     
00684     vigra_precondition((width_old > 1) && (height_old > 1),
00685                  "resampleImage(): "
00686                  "Source image to small.\n");
00687     vigra_precondition((width_new > 1) && (height_new > 1),
00688                  "resampleImage(): "
00689                  "Destination image to small.\n");
00690         
00691     typedef typename SrcAccessor::value_type SRCVT;
00692     typedef BasicImage<SRCVT> TmpImage;
00693     typedef typename TmpImage::traverser TmpImageIterator;
00694 
00695     BasicImage<SRCVT> tmp(width_old, height_new);
00696     
00697     int x,y;
00698     
00699     typename BasicImage<SRCVT>::Iterator yt = tmp.upperLeft();
00700 
00701     for(x=0; x<width_old; ++x, ++is.x, ++yt.x) 
00702     {
00703         typename SrcIterator::column_iterator c1 = is.columnIterator();
00704         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
00705         resampleLine(c1, c1 + height_old, sa, ct, tmp.accessor(), yfactor);
00706     }
00707 
00708     yt = tmp.upperLeft();
00709 
00710     for(y=0; y < height_new; ++y, ++yt.y, ++id.y) 
00711     {
00712         typename DestIterator::row_iterator rd = id.rowIterator();
00713         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
00714         resampleLine(rt, rt + width_old, tmp.accessor(), rd, ad, xfactor);
00715     }
00716 
00717 }
00718 
00719 template <class SrcIterator, class SrcAccessor,
00720           class DestIterator, class DestAccessor>
00721 void 
00722 resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00723               DestIterator id, DestAccessor ad, double factor)
00724 {
00725   resampleImage(is, iend, sa, id, ad, factor, factor);
00726 }
00727 
00728 template <class SrcImageIterator, class SrcAccessor,
00729           class DestImageIterator, class DestAccessor>
00730 inline void 
00731 resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00732               pair<DestImageIterator, DestAccessor> dest, double factor)
00733 {
00734   resampleImage(src.first, src.second, src.third, dest.first, dest.second, factor);
00735 }
00736 
00737 template <class SrcImageIterator, class SrcAccessor,
00738           class DestImageIterator, class DestAccessor>
00739 inline void 
00740 resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00741               pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor)
00742 {
00743   resampleImage(src.first, src.second, src.third, dest.first, dest.second, xfactor, yfactor);
00744 }
00745 
00746 //@}
00747 
00748 } // namespace vigra
00749 
00750 
00751 #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.1 (Mon Apr 16 2012)