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