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 }