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

2008__tour1.cc

00001 // Copyright (C) 2001, 2007, 2008 EPITA Research and Development
00002 // Laboratory
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 // File: tour1.cc.
00028 
00029 #include <oln/core/1d/image1d.hh>
00030 
00031 #include <oln/arith/plus.hh>    // arith
00032 
00033 #include <oln/data/fill.hh>    // data
00034 #include <oln/data/paste.hh>
00035 
00036 #include <oln/debug/println.hh> // debug
00037 
00038 
00039 int main()
00040 {
00041   // Olena is organized in a namespace hierarchy.  Everything is
00042   // declared by Olena within the 'oln::' namespace, and possibly a
00043   // sub-namespace such as 'oln::arith::' (arithmetic operations on
00044   // images), 'oln::morpho::' (morphological operations), etc.  For
00045   // the sake of simplicity, we will neglect the 'oln::' prefix in
00046   // this file.
00047 
00048   using namespace oln;
00049 
00050   // There are three kinds of image dimensions supported for the
00051   // moment: 1D, 2D, and 3D.  The respective basic image types are
00052   // respectively image1d, image2d, and image3d.  All are template'd,
00053   // parametrized by the kind of value associated to each point.
00054   //
00055   // We will start to use the 1D images, because there are less values
00056   // to assign (!) and because they are easy to display.  Although we
00057   // will be in 1D, we will talk about "points" and "pixels", just
00058   // like in the classical 2D world.
00059 
00060   // Here are the two most basic ways to build an image:
00061 
00062   image1d<int> img1a;      // which builds an empty image;
00063   image1d<int> img1b(20);  // which builds an image with 20 pixels.
00064 
00065   // The type of values enclosed in those images is 'int' for
00066   // integers.
00067 
00068   // The empty image has no data and its definition domain is still
00069   // unset.  We do not know yet the number of pixels it contains.
00070   // However, it is really useful to have such an "empty image"
00071   // because it is a placeholder for the result of some processing, or
00072   // another image.
00073 
00074   // Trying to access the pixel value from an empty image leads to an
00075   // error at run-time.
00076 
00077   // Assigning an image to another one is NOT a costly operation.
00078   // Actually img1a behaves like some mathematical variable.  Put
00079   // differently it is just a name to designate an image.  After the
00080   // following instruction
00081 
00082   img1a = img1b;
00083 
00084   // Both variables img1a and img1b can be used equivalently to access
00085   // the same data.  Just like in maths we can state that "img1a IS
00086   // img2b" and we only have ONE actual image in memory.  The image
00087   // definition---its domain and its pixel values--is shared by img1a
00088   // AND img1b.
00089 
00090 
00091   // Since an image is a function that maps values to points, to read
00092   // or modify a pixel value, we just the same notation than the one
00093   // of functions:
00094  
00095   img1a.at(0)  = 7;   // Assign value  7 to the  1st pixel of img1a.
00096   img1a.at(10) = 51;  // Assign value 51 to the 11th pixel of img1a.
00097 
00098   std::cout << "img1b.at(10) = " << img1b.at(10)
00099             << std::endl; // Print 51 since img1b is img1a.
00100 
00101   // As you can see, Olena provides a unique easy syntax to access an
00102   // image value, whatever we want to read this value or to modify it:
00103   // "ima(p)", where p is a variable that represents a point of the 1D
00104   // domain.  In "val = ima(p)" we read the pixel value, whereas in
00105   // "ima(p) = new_val" we write in an image.  For 1D images, a 1D
00106   // point behaves just like an index so the user can write "ima(i)"
00107   // with i being an integer.
00108 
00109 
00110   // A single image variable can be used to designate one image and
00111   // then another one.
00112 
00113   image1d<int> img2a(20); // An image (not empty).
00114   image1d<int> img2b(20); // Another one (not empty).
00115   image1d<int> img;       // A variable.
00116 
00117   img = img2a; // img is img2a
00118   img.at(5) = 19; // so img2a at index 5 is set to 19.
00119 
00120   img = img2b; // img is NOW img2b
00121   img.at(5) = 69; // so img2b at index 5 is set to 69.
00122 
00123   std::cout << (100 * img2a.at(5) + img2b.at(5)) // Gives 1969.
00124             << std::endl;
00125 
00126 
00127 
00128   // In the Olena library, all image types behave like image1d:
00129   //
00130   //  +-----------------------------------------------------------+
00131   //  |                                                           |
00132   //  |  - an "empty" image actually is a mathematical variable   |
00133   //  |                                                           |
00134   //  |        => just think in a mathemetical way when dealing   |
00135   //  |           with images;                                    |
00136   //  |                                                           |
00137   //  |                                                           |
00138   //  |  - no dynamic memory allocation/deallocation is required  |
00139   //  |                                                           |
00140   //  |        the user never has to use "new / delete" (the C++  |
00141   //  |        equivalent for the C "malloc / free") so she does  |
00142   //  |        not have to manipulate pointers or to directly     |
00143   //  |        access memory                                      |
00144   //  |                                                           |
00145   //  |        => Olena prevents the user from making mistakes;   |
00146   //  |                                                           |
00147   //  |                                                           |
00148   //  |  - image data/values can be shared between several        |
00149   //  |    variables and the memory used for image data is        |
00150   //  |    handled by the library                                 |
00151   //  |                                                           |
00152   //  |        => memory management is automatic.                 |
00153   //  |                                                           |
00154   //  |                                                           |
00155   //  +-----------------------------------------------------------+
00156 
00157 
00158 
00159 
00160   image1d<char> img3a(0, 19);  // These 1D image data go from the
00161                                // index 0 to the index 19; it thus has
00162                                // 20 points.
00163 
00164   // Memory has been allocated so data can be stored but pixel values
00165   // have not been initialized yet.  So we fill img3a, that is, all
00166   // pixels of img3a, with the value 'a':
00167   data::fill(img3a, 'a');
00168 
00169   // The "fill" algorithm is located in the sub-namespace "data"
00170   // since this algorithm deals with the "data" of pixel values.
00171 
00172   // The full name of this routine is "oln::data::fill".  To access
00173   // to a particular algorithm, the proper file shall be included.
00174   // The file names of algorithms strictly map their C++ name; so
00175   // oln::data::fill is defined in the file "oln/data/fill.hh".
00176 
00177   // Most algorithms in Olena are constructed following the classical
00178   // scheme: "output algo(input)", where the input image is only read.
00179   // However some few algorithms take an input image in order to
00180   // modify it.
00181 
00182   // Obsolete:  To enforce this particular feature, the user shall
00183   // Obsolete:  explicitly state that the image is provided so that its data is
00184   // Obsolete:  modified "inplace".
00185 
00186   // Obsolete:  The algorithm call shall be "data::fill(inplace(ima), val)".
00187   // Obsolete:  When forgetting the "inplace(..)" statement it does not compile.
00188 
00189 
00190   // We then define below a second image to play with.  As you can see
00191   // this image has data for the indices 5 to 14 (so it has 10
00192   // points).  The definition domain of a 1D image can start from
00193   // any index, even a negative one.
00194   image1d<char> img3b(5, 14);
00195 
00196   // We initialize the image values.
00197   data::fill(img3b, 'b');
00198 
00199   // Last we now paste the contents of img3b in img3a...
00200   data::paste(img3b, img3a);
00201 
00202   // ...and print the result.
00203   debug::println(img3a);
00204 
00205   // Before pasting, the couple of images looked like:
00206   //
00207   // index = 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
00208   //         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
00209   //                           
00210   // img3a = a a a a a a a a a a a a a a a a a a a a
00211   // img3b =           b b b b b b b b b b
00212   //
00213   // so after pasting we get:
00214   // img3a = a a a a a b b b b b b b b b b a a a a a
00215   //
00216   // Just remember that a point is an absolute location on the
00217   // discrete domain.  For the 1D case, an index is thus NOT an
00218   // offset.  When we write "imgb(5)", we designate the first pixel of
00219   // imgb since this image starts at index 5.
00220 
00221 
00222   // With this simple example we can see that images defined on
00223   // different domains (or set of points) can interoperate.  The set
00224   // of points an image is defined on can be accessed and printed.
00225   // The following code:
00226 
00227   std::cout << "img3a.points() = " << img3a.points() << std::endl
00228             << "img3b.points() = " << img3b.points() << std::endl;
00229 
00230   // gives:
00231   // img3a.points() = { (0) .. (19) }
00232   // img3b.points() = { (5) .. (14) }
00233 
00234   // The notion of point sets plays an important role in Olena.  Many
00235   // tests are performed at run-time to ensure that the program is
00236   // correct.
00237 
00238   // For instance, the algorithm data::paste tests that the set of
00239   // points of img3b (whose values are to be pasted) is a subset of
00240   // the destination image.  We can reproduce this same test:
00241 
00242   std::cout << (img3b.points() <= img3a.points() ?
00243                 "true" :
00244                 "false") << std::endl;  // which gives 'true'.
00245 
00246   // Accessing the value of an image at a given point also performs a
00247   // test to make sure that this point belongs to the image domain
00248   // (and consequently that data access in memory is valid).  For
00249   // instance, calling "img3a(9)" actually runs a code equivalent to
00250   // this test:
00251 
00252   point1d p(9);
00253   std::cout << (img3a.points().has(p) ?
00254                 "true" :
00255                 "false") << std::endl; // which gives 'true'.
00256 
00257   // The type of 1D image points is "point1d".  The 1D image type
00258   // features the method "operator()(point1d p)"; when we write
00259   // "img3a(9)" it is just a shortcut for "img3a( point1d(9) )".
00260 
00261   // When having a point we can access its index following:
00262   std::cout << p.ind() << std::endl;  // which gives 9.
00263 
00264   // To know if a point belongs to an image domain or not, we can run
00265   // this shorter test:
00266   std::cout << (img3a.has(p) ?
00267                 "true" :
00268                 "false") << std::endl; // which gives 'true'.
00269 
00270 
00271   // Since the notion of point is independent from the image it
00272   // applies on, we can form expressions where p is used on several
00273   // images:
00274 
00275   img3a(p) = 'M', img3b(p) = 'W';  // At index 9, both values change.
00276   debug::println(img3a);
00277   debug::println(img3b);
00278   // we obtain:
00279   // a a a a a b b b b M b b b b b a a a a a
00280   // b b b b W b b b b b
00281 
00282 
00283   // To modify all the values of an image we can iterate over its
00284   // domain with an index i:
00285 
00286   for (int i = 5; i <= 14; ++i)
00287     img3b.at(i) = 'a' + i - 5;
00288   debug::println(img3b);
00289   // a b c d e f g h i j
00290 
00291   // There is a safer way to iterate that prevents from providing a
00292   // wrong value for the minimum or maximum index value:
00293   for (int i = img3b.min_ind(); i <= img3b.max_ind(); ++i)
00294     img3b.at(i) = 'b' + i - img3b.min_ind();
00295   debug::println(img3b);
00296   // b c d e f g h i j k
00297 
00298 
00299   // The Olena library was built with the following rationale:
00300   //
00301   //  +-----------------------------------------------------------+
00302   //  |                                                           |
00303   //  |  If you do not want to be "generic", if you are used to   |
00304   //  |  the classical way of browsing pixel values, you can!     |
00305   //  |                                                           |
00306   //  +-----------------------------------------------------------+
00307 
00308 
00309   // Indeed, the loops above depict the "classical" way to iterate
00310   // over the contents of a 1D image.  The next tour file introduces
00311   // the solution provided by Olena to write better loops...
00312 
00313 
00314   // Jump to tour1_extra.cc if you want some more information about
00315   // image data management.
00316 
00317   // Jump to tour2.cc to continue the tour.
00318 }

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