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

vigra/basicgeometry.hxx VIGRA

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> <vigra/basicgeometry.hxx><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 inline 
00206 Reflect operator|(Reflect l, Reflect r)
00207 {
00208     return Reflect((unsigned int)l | (unsigned int)r);
00209 }
00210 
00211 /** \brief Reflect image horizontally or vertically.
00212 
00213     The reflection direction refers to the reflection axis, i.e.
00214     horizontal reflection turns the image upside down, vertical reflection
00215     changes left for right. The directions are selected by the enum values
00216     <tt>vigra::horizontal</tt> and <tt>vigra::vertical</tt>. The two directions 
00217     can also be "or"ed together to perform both reflections simultaneously 
00218     (see example below) -- this is the same as a 180 degree rotation. 
00219     
00220     <b> Declarations:</b>
00221     
00222     pass arguments explicitly:
00223     \code
00224     namespace vigra {
00225         template <class SrcIterator, class SrcAccessor,
00226                   class DestIterator, class DestAccessor>
00227         void 
00228         reflectImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00229                      DestIterator id, DestAccessor ad, Reflect axis);
00230     }
00231     \endcode
00232     
00233     use argument objects in conjunction with \ref ArgumentObjectFactories :
00234     \code
00235     namespace vigra {
00236         template <class SrcImageIterator, class SrcAccessor,
00237               class DestImageIterator, class DestAccessor>
00238         inline void 
00239         reflectImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00240                      pair<DestImageIterator, DestAccessor> dest, Reflect axis);
00241     }
00242     \endcode
00243     
00244     <b> Usage:</b>
00245     
00246         <b>\#include</b> <vigra/basicgeometry.hxx><br>
00247         Namespace: vigra
00248     
00249     \code
00250     Image dest(src.width(), src.height());
00251     
00252     vigra::reflectImage(srcImageRange(src), destImage(dest), vigra::horizontal | vigra::vertical);
00253     
00254     \endcode
00255 
00256     <b> Required Interface:</b>
00257     
00258     \code
00259     SrcImageIterator src_upperleft, src_lowerright;
00260     DestImageIterator dest_upperleft;
00261     
00262     SrcAccessor src_accessor;
00263     
00264     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00265 
00266     \endcode
00267     
00268     <b> Preconditions:</b>
00269     
00270     \code
00271     src_lowerright.x - src_upperleft.x > 1
00272     src_lowerright.y - src_upperleft.y > 1
00273     \endcode
00274     
00275 */
00276 doxygen_overloaded_function(template <...> void reflectImage)
00277 
00278 template <class SrcIterator, class SrcAccessor, 
00279           class DestIterator, class DestAccessor>
00280 void reflectImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00281                   DestIterator id, DestAccessor ad, Reflect reflect)
00282 {
00283     
00284     int ws = end.x - is.x;
00285     int hs = end.y - is.y;
00286 
00287     int x, y;
00288 
00289     if(reflect == horizontal)
00290     {//flipImage
00291         is.y += (hs-1);
00292         for(x=0; x<ws; ++x, ++is.x, ++id.x) 
00293         {
00294             typename SrcIterator::column_iterator  cs = is.columnIterator();
00295             typename DestIterator::column_iterator cd = id.columnIterator();
00296             for(y=0; y!=hs;y++, cs--, cd++)
00297             {
00298                 ad.set(as(cs), cd);
00299             }
00300         }
00301     }
00302     else if(reflect == vertical)
00303     {//flopImage
00304         is.x += (ws-1);
00305         for(x=0; x < ws; ++x, --is.x, ++id.x) 
00306         {
00307 
00308             typename SrcIterator::column_iterator cs = is.columnIterator();
00309             typename DestIterator::column_iterator cd = id.columnIterator();
00310             for(y=0; y!=hs;y++, cs++, cd++)
00311             {
00312                 ad.set(as(cs), cd);
00313             }
00314         }
00315     }
00316     else if(reflect == (horizontal | vertical))
00317     {//flipFlopImage   //???
00318         end.x--;
00319         end.y--;
00320         for(x=0; x != ws; x++, end.x--, id.x++)
00321         {
00322             typename SrcIterator::column_iterator cs = end.columnIterator();
00323             typename DestIterator::column_iterator cd = id.columnIterator();
00324             for(y=0; y != hs; y++, cs--, cd++)
00325             {
00326                 ad.set(as(cs), cd);
00327             }
00328         }
00329     }
00330     else 
00331         vigra_fail("reflectImage(): "
00332                    "This function reflects horizontal or vertical,"
00333                    "   'and' is included");
00334 }
00335 
00336 template <class SrcImageIterator, class SrcAccessor,
00337           class DestImageIterator, class DestAccessor>
00338 inline void 
00339 reflectImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00340               pair<DestImageIterator, DestAccessor> dest, Reflect reflect)
00341 {
00342     reflectImage(src.first, src.second, src.third, dest.first, dest.second, reflect);
00343 }
00344 
00345 /********************************************************/
00346 /*                                                      */
00347 /*                    transposeImage                   */
00348 /*                                                      */
00349 /********************************************************/
00350 
00351 // names clash with sys/types.h on Mac OS / Darwin, see docs below
00352 enum Transpose{major = 1, minor = 2};
00353 
00354 /** \brief Transpose an image over the major or minor diagonal.
00355 
00356     The transposition direction refers to the axis, i.e.
00357     major transposition turns the upper right corner into the lower left one, 
00358     whereas minor transposition changes the upper left corner into the lower right one. 
00359     The directions are selected by the enum values
00360     <tt>vigra::major</tt> and <tt>vigra::minor</tt>. The two directions 
00361     can also be "or"ed together to perform both reflections simultaneously 
00362     (see example below) -- this is the same as a 180 degree rotation.
00363     (Caution: When doing multi-platform development, you should be
00364     aware that some <sys/types.h> define major/minor, too.  Do not omit
00365     the vigra namespace prefix.)
00366     
00367     <b> Declarations:</b>
00368     
00369     pass arguments explicitly:
00370     \code
00371     namespace vigra {
00372         template <class SrcIterator, class SrcAccessor,
00373                   class DestIterator, class DestAccessor>
00374         void 
00375         transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00376                        DestIterator id, DestAccessor ad, Transpose axis);
00377     }
00378     \endcode
00379     
00380     use argument objects in conjunction with \ref ArgumentObjectFactories :
00381     \code
00382     namespace vigra {
00383         template <class SrcImageIterator, class SrcAccessor,
00384               class DestImageIterator, class DestAccessor>
00385         inline void 
00386         transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00387                        pair<DestImageIterator, DestAccessor> dest, Transpose axis);
00388     }
00389     \endcode
00390     
00391     <b> Usage:</b>
00392     
00393         <b>\#include</b> <vigra/basicgeometry.hxx><br>
00394         Namespace: vigra
00395     
00396     \code
00397     Image dest(src.width(), src.height());
00398     
00399     vigra::transposeImage(srcImageRange(src), destImage(dest), vigra::major | vigra::minor);
00400     
00401     \endcode
00402 
00403     <b> Required Interface:</b>
00404     
00405     \code
00406     SrcImageIterator src_upperleft, src_lowerright;
00407     DestImageIterator dest_upperleft;
00408     
00409     SrcAccessor src_accessor;
00410     
00411     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00412 
00413     \endcode
00414     
00415     <b> Preconditions:</b>
00416     
00417     \code
00418     src_lowerright.x - src_upperleft.x > 1
00419     src_lowerright.y - src_upperleft.y > 1
00420     \endcode
00421     
00422 */
00423 doxygen_overloaded_function(template <...> void transposeImage)
00424 
00425 template <class SrcIterator, class SrcAccessor, 
00426           class DestIterator, class DestAccessor>
00427 void transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
00428                     DestIterator id, DestAccessor ad, Transpose transpose)
00429 {
00430     int ws = end.x - is.x;
00431     int hs = end.y - is.y;
00432 
00433     int x, y;
00434 
00435     if(transpose == major)
00436     {//Die Funktion spiegelt das Bild um (0,0) (1,1) Diagonale
00437         for(x=0; x != ws; x++, is.x++, id.y++)
00438         {
00439 
00440             typename SrcIterator::column_iterator cs = is.columnIterator();
00441             typename DestIterator::row_iterator rd = id.rowIterator();
00442             for(y=0; y != hs; y++, cs++, rd++)
00443             {
00444                 ad.set(as(cs), rd);
00445             }
00446         }
00447     }
00448     else if(transpose == minor)
00449     {//Die Funktion spiegelt das Bild (1,0) (0,1) Diagonale
00450         end.x--;
00451         end.y--;
00452         for(x=0; x != ws; x++, --end.x, ++id.y)
00453         {
00454 
00455             typename SrcIterator::column_iterator cs = end.columnIterator();
00456             typename DestIterator::row_iterator rd = id.rowIterator();
00457             for(y=0; y != hs; y++, --cs, ++rd)
00458             {
00459                 ad.set(as(cs), rd);
00460             }
00461         }
00462     }
00463     else if(transpose == (major | minor))
00464     {//flipFlopImage  //???
00465         end.x--;
00466         end.y--;
00467         for(x=0; x != ws; x++, end.x--, id.x++)
00468         {
00469             typename SrcIterator::column_iterator cs = end.columnIterator();
00470             typename DestIterator::column_iterator cd = id.columnIterator();
00471             for(y=0; y != hs; y++, cs--, cd++)
00472             {
00473                 ad.set(as(cs), cd);
00474             }
00475         }
00476     
00477     }
00478     else 
00479         vigra_fail("transposeImage(): "
00480                    "This function transposes major or minor,"
00481                    "   'and' is included");
00482 
00483 }
00484 
00485 template <class SrcImageIterator, class SrcAccessor,
00486           class DestImageIterator, class DestAccessor>
00487 inline void 
00488 transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00489               pair<DestImageIterator, DestAccessor> dest, Transpose transpose)
00490 {
00491     transposeImage(src.first, src.second, src.third, dest.first, dest.second, transpose);
00492 }
00493 
00494 /********************************************************/
00495 /*                                                      */
00496 /*                        resampleLine                  */
00497 /*                                                      */
00498 /********************************************************/
00499 
00500 /*
00501 * Vergroessert eine Linie um einen Faktor. 
00502 * Ist z.B. der Faktor = 4 so werden in der
00503 * neuen Linie(Destination) jedes Pixel genau 4 mal 
00504 * vorkommen, also es findet auch keine Glaetung 
00505 * statt (NoInterpolation). Als Parameter sollen
00506 * der Anfangs-, der Enditerator und der Accessor
00507 * der Ausgangslinie (Source line), der Anfangsiterator
00508 * und Accessor der Ziellinie (destination line) und
00509 * anschliessend der Faktor um den die Linie (Zeile)
00510 * vergroessert bzw. verkleinert werden soll. 
00511 */
00512 template <class SrcIterator, class SrcAccessor, 
00513           class DestIterator, class DestAccessor>
00514 void resampleLine(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
00515                   DestIterator dest_iter, DestAccessor dest_acc, double factor)
00516 {
00517     // The width of the src line.      
00518     int src_width = src_iter_end - src_iter;
00519  
00520     vigra_precondition(src_width > 0,
00521                        "resampleLine(): input image too small.");
00522     vigra_precondition(factor > 0.0,
00523                        "resampleLine(): factor must be positive.");
00524     
00525     if (factor >= 1.0)
00526     {
00527         int int_factor = (int)factor;
00528         double dx = factor - int_factor;
00529         double saver = dx;
00530         for ( ; src_iter != src_iter_end ; ++src_iter, saver += dx)
00531         {
00532             if (saver >= 1.0)
00533             {
00534                 saver = saver - (int)saver;
00535                 dest_acc.set(src_acc(src_iter), dest_iter);
00536                 ++dest_iter;
00537             }
00538             for(int i = 0 ; i < int_factor ; i++, ++dest_iter)
00539             {
00540                 dest_acc.set(src_acc(src_iter), dest_iter);
00541             }
00542         }
00543     }
00544     else
00545     {
00546         DestIterator dest_end = dest_iter + (int)VIGRA_CSTD::ceil(src_width*factor);  
00547         factor = 1.0/factor;
00548         int int_factor = (int)factor;
00549         double dx = factor - int_factor;
00550         double saver = dx;
00551         src_iter_end -= 1;
00552         for ( ; src_iter != src_iter_end && dest_iter != dest_end ; 
00553               ++dest_iter, src_iter += int_factor, saver += dx)
00554         {
00555             if (saver >= 1.0)
00556             {
00557                 saver = saver - (int)saver;
00558                 ++src_iter;
00559             }
00560             dest_acc.set(src_acc(src_iter), dest_iter);
00561         }
00562         if (dest_iter != dest_end)
00563         {
00564             dest_acc.set(src_acc(src_iter_end), dest_iter);
00565         }
00566     }
00567 }
00568 
00569 inline int sizeForResamplingFactor(int oldsize, double factor)
00570 {
00571     return (factor < 1.0)
00572         ? (int)VIGRA_CSTD::ceil(oldsize * factor) 
00573         : (int)(oldsize * factor);
00574 }
00575 
00576 
00577 /********************************************************/
00578 /*                                                      */
00579 /*                     resampleImage                    */
00580 /*                                                      */
00581 /********************************************************/
00582 
00583 /** \brief Resample image by a given factor.
00584 
00585     This algorithm is very fast and does not require any arithmetic on the pixel types.    
00586     The input image must have a size of at
00587     least 2x2. Destiniation pixels are directly copied from the appropriate
00588     source pixels. The size of the result image is the product of <tt>factor</tt>
00589     and the original size, where we round up if <tt>factor < 1.0</tt> and down otherwise.
00590     This size calculation is the main difference to the convention used in the similar 
00591     function \ref resizeImageNoInterpolation():
00592     there, the result size is calculated as <tt>n*(old_width-1)+1</tt> and 
00593     <tt>n*(old_height-1)+1</tt>. This is because \ref resizeImageNoInterpolation() 
00594     does not replicate the last pixel in every row/column in order to make it compatible
00595     with the other functions of the <tt>resizeImage...</tt> family.
00596     
00597     The function can be called with different resampling factors for x and y, or
00598     with a single factor to be used for both directions.
00599 
00600     It should also be noted that resampleImage() is implemented so that an enlargement followed
00601     by the corresponding shrinking reproduces the original image. The function uses accessors. 
00602     
00603     <b> Declarations:</b>
00604     
00605     pass arguments explicitly:
00606     \code
00607     namespace vigra {
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 factor);
00613                       
00614         template <class SrcIterator, class SrcAccessor,
00615                   class DestIterator, class DestAccessor>
00616         void 
00617         resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00618                       DestIterator id, DestAccessor ad, double xfactor, double yfactor);
00619     }
00620     \endcode
00621     
00622     use argument objects in conjunction with \ref ArgumentObjectFactories :
00623     \code
00624     namespace vigra {
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 factor);
00630                       
00631         template <class SrcImageIterator, class SrcAccessor,
00632               class DestImageIterator, class DestAccessor>
00633         inline void 
00634         resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00635                       pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor);
00636     }
00637     \endcode
00638     
00639     <b> Usage:</b>
00640     
00641         <b>\#include</b> <vigra/basicgeometry.hxx><br>
00642         Namespace: vigra
00643     
00644     \code
00645     double factor = 2.0;
00646     Image dest((int)(factor*src.width()), (int)(factor*src.height()));
00647     
00648     vigra::resampleImage(srcImageRange(src), destImage(dest), factor);
00649     
00650     \endcode
00651 
00652     <b> Required Interface:</b>
00653     
00654     \code
00655     SrcImageIterator src_upperleft, src_lowerright;
00656     DestImageIterator dest_upperleft;
00657     
00658     SrcAccessor src_accessor;
00659     
00660     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
00661 
00662     \endcode
00663     
00664     <b> Preconditions:</b>
00665     
00666     \code
00667     src_lowerright.x - src_upperleft.x > 1
00668     src_lowerright.y - src_upperleft.y > 1
00669     \endcode
00670     
00671 */
00672 doxygen_overloaded_function(template <...> void resampleImage)
00673 
00674 template <class SrcIterator, class SrcAccessor,
00675           class DestIterator, class DestAccessor>
00676 void 
00677 resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00678               DestIterator id, DestAccessor ad, double xfactor, double yfactor)
00679 {
00680     int width_old = iend.x - is.x;
00681     int height_old = iend.y - is.y;
00682     
00683     //Bei Verkleinerung muss das dest-Bild ceiling(src*factor), da z.B.
00684     //aus 6x6 grossem Bild wird eins 18x18 grosses gemacht bei Vergroesserungsfaktor 3.1
00685     //umgekehrt damit wir vom 18x18 zu 6x6 (und nicht 5x5) bei Vergroesserung von 1/3.1
00686     //muss das kleinste Integer das groesser als 18/3.1 ist genommen werden.
00687     int height_new = sizeForResamplingFactor(height_old, yfactor);
00688     int width_new = sizeForResamplingFactor(width_old, xfactor);
00689     
00690     vigra_precondition((width_old > 1) && (height_old > 1),
00691                  "resampleImage(): "
00692                  "Source image too small.\n");
00693     vigra_precondition((width_new > 1) && (height_new > 1),
00694                  "resampleImage(): "
00695                  "Destination image too small.\n");
00696         
00697     typedef typename SrcAccessor::value_type SRCVT;
00698     typedef BasicImage<SRCVT> TmpImage;
00699     typedef typename TmpImage::traverser TmpImageIterator;
00700 
00701     BasicImage<SRCVT> tmp(width_old, height_new);
00702     
00703     int x,y;
00704     
00705     typename BasicImage<SRCVT>::Iterator yt = tmp.upperLeft();
00706 
00707     for(x=0; x<width_old; ++x, ++is.x, ++yt.x) 
00708     {
00709         typename SrcIterator::column_iterator c1 = is.columnIterator();
00710         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
00711         resampleLine(c1, c1 + height_old, sa, ct, tmp.accessor(), yfactor);
00712     }
00713 
00714     yt = tmp.upperLeft();
00715 
00716     for(y=0; y < height_new; ++y, ++yt.y, ++id.y) 
00717     {
00718         typename DestIterator::row_iterator rd = id.rowIterator();
00719         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
00720         resampleLine(rt, rt + width_old, tmp.accessor(), rd, ad, xfactor);
00721     }
00722 
00723 }
00724 
00725 template <class SrcIterator, class SrcAccessor,
00726           class DestIterator, class DestAccessor>
00727 void 
00728 resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
00729               DestIterator id, DestAccessor ad, double factor)
00730 {
00731   resampleImage(is, iend, sa, id, ad, factor, 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 factor)
00739 {
00740   resampleImage(src.first, src.second, src.third, dest.first, dest.second, factor);
00741 }
00742 
00743 template <class SrcImageIterator, class SrcAccessor,
00744           class DestImageIterator, class DestAccessor>
00745 inline void 
00746 resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00747               pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor)
00748 {
00749   resampleImage(src.first, src.second, src.third, dest.first, dest.second, xfactor, yfactor);
00750 }
00751 
00752 //@}
00753 
00754 } // namespace vigra
00755 
00756 
00757 #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.9.0 (Tue Nov 6 2012)