Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
2008__tour1.cc
1 // Copyright (C) 2001, 2007, 2008 EPITA Research and Development
2 // Laboratory
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 // File: tour1.cc.
28 
29 #include <oln/core/1d/image1d.hh>
30 
31 #include <oln/arith/plus.hh> // arith
32 
33 #include <oln/data/fill.hh> // data
34 #include <oln/data/paste.hh>
35 
36 #include <oln/debug/println.hh> // debug
37 
38 
39 int main()
40 {
41  // Olena is organized in a namespace hierarchy. Everything is
42  // declared by Olena within the 'oln::' namespace, and possibly a
43  // sub-namespace such as 'oln::arith::' (arithmetic operations on
44  // images), 'oln::morpho::' (morphological operations), etc. For
45  // the sake of simplicity, we will neglect the 'oln::' prefix in
46  // this file.
47 
48  using namespace oln;
49 
50  // There are three kinds of image dimensions supported for the
51  // moment: 1D, 2D, and 3D. The respective basic image types are
52  // respectively image1d, image2d, and image3d. All are template'd,
53  // parametrized by the kind of value associated to each point.
54  //
55  // We will start to use the 1D images, because there are less values
56  // to assign (!) and because they are easy to display. Although we
57  // will be in 1D, we will talk about "points" and "pixels", just
58  // like in the classical 2D world.
59 
60  // Here are the two most basic ways to build an image:
61 
62  image1d<int> img1a; // which builds an empty image;
63  image1d<int> img1b(20); // which builds an image with 20 pixels.
64 
65  // The type of values enclosed in those images is 'int' for
66  // integers.
67 
68  // The empty image has no data and its definition domain is still
69  // unset. We do not know yet the number of pixels it contains.
70  // However, it is really useful to have such an "empty image"
71  // because it is a placeholder for the result of some processing, or
72  // another image.
73 
74  // Trying to access the pixel value from an empty image leads to an
75  // error at run-time.
76 
77  // Assigning an image to another one is NOT a costly operation.
78  // Actually img1a behaves like some mathematical variable. Put
79  // differently it is just a name to designate an image. After the
80  // following instruction
81 
82  img1a = img1b;
83 
84  // Both variables img1a and img1b can be used equivalently to access
85  // the same data. Just like in maths we can state that "img1a IS
86  // img2b" and we only have ONE actual image in memory. The image
87  // definition---its domain and its pixel values--is shared by img1a
88  // AND img1b.
89 
90 
91  // Since an image is a function that maps values to points, to read
92  // or modify a pixel value, we just the same notation than the one
93  // of functions:
94 
95  img1a.at(0) = 7; // Assign value 7 to the 1st pixel of img1a.
96  img1a.at(10) = 51; // Assign value 51 to the 11th pixel of img1a.
97 
98  std::cout << "img1b.at(10) = " << img1b.at(10)
99  << std::endl; // Print 51 since img1b is img1a.
100 
101  // As you can see, Olena provides a unique easy syntax to access an
102  // image value, whatever we want to read this value or to modify it:
103  // "ima(p)", where p is a variable that represents a point of the 1D
104  // domain. In "val = ima(p)" we read the pixel value, whereas in
105  // "ima(p) = new_val" we write in an image. For 1D images, a 1D
106  // point behaves just like an index so the user can write "ima(i)"
107  // with i being an integer.
108 
109 
110  // A single image variable can be used to designate one image and
111  // then another one.
112 
113  image1d<int> img2a(20); // An image (not empty).
114  image1d<int> img2b(20); // Another one (not empty).
115  image1d<int> img; // A variable.
116 
117  img = img2a; // img is img2a
118  img.at(5) = 19; // so img2a at index 5 is set to 19.
119 
120  img = img2b; // img is NOW img2b
121  img.at(5) = 69; // so img2b at index 5 is set to 69.
122 
123  std::cout << (100 * img2a.at(5) + img2b.at(5)) // Gives 1969.
124  << std::endl;
125 
126 
127 
128  // In the Olena library, all image types behave like image1d:
129  //
130  // +-----------------------------------------------------------+
131  // | |
132  // | - an "empty" image actually is a mathematical variable |
133  // | |
134  // | => just think in a mathemetical way when dealing |
135  // | with images; |
136  // | |
137  // | |
138  // | - no dynamic memory allocation/deallocation is required |
139  // | |
140  // | the user never has to use "new / delete" (the C++ |
141  // | equivalent for the C "malloc / free") so she does |
142  // | not have to manipulate pointers or to directly |
143  // | access memory |
144  // | |
145  // | => Olena prevents the user from making mistakes; |
146  // | |
147  // | |
148  // | - image data/values can be shared between several |
149  // | variables and the memory used for image data is |
150  // | handled by the library |
151  // | |
152  // | => memory management is automatic. |
153  // | |
154  // | |
155  // +-----------------------------------------------------------+
156 
157 
158 
159 
160  image1d<char> img3a(0, 19); // These 1D image data go from the
161  // index 0 to the index 19; it thus has
162  // 20 points.
163 
164  // Memory has been allocated so data can be stored but pixel values
165  // have not been initialized yet. So we fill img3a, that is, all
166  // pixels of img3a, with the value 'a':
167  data::fill(img3a, 'a');
168 
169  // The "fill" algorithm is located in the sub-namespace "data"
170  // since this algorithm deals with the "data" of pixel values.
171 
172  // The full name of this routine is "oln::data::fill". To access
173  // to a particular algorithm, the proper file shall be included.
174  // The file names of algorithms strictly map their C++ name; so
175  // oln::data::fill is defined in the file "oln/data/fill.hh".
176 
177  // Most algorithms in Olena are constructed following the classical
178  // scheme: "output algo(input)", where the input image is only read.
179  // However some few algorithms take an input image in order to
180  // modify it.
181 
182  // Obsolete: To enforce this particular feature, the user shall
183  // Obsolete: explicitly state that the image is provided so that its data is
184  // Obsolete: modified "inplace".
185 
186  // Obsolete: The algorithm call shall be "data::fill(inplace(ima), val)".
187  // Obsolete: When forgetting the "inplace(..)" statement it does not compile.
188 
189 
190  // We then define below a second image to play with. As you can see
191  // this image has data for the indices 5 to 14 (so it has 10
192  // points). The definition domain of a 1D image can start from
193  // any index, even a negative one.
194  image1d<char> img3b(5, 14);
195 
196  // We initialize the image values.
197  data::fill(img3b, 'b');
198 
199  // Last we now paste the contents of img3b in img3a...
200  data::paste(img3b, img3a);
201 
202  // ...and print the result.
203  debug::println(img3a);
204 
205  // Before pasting, the couple of images looked like:
206  //
207  // index = 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
208  // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
209  //
210  // img3a = a a a a a a a a a a a a a a a a a a a a
211  // img3b = b b b b b b b b b b
212  //
213  // so after pasting we get:
214  // img3a = a a a a a b b b b b b b b b b a a a a a
215  //
216  // Just remember that a point is an absolute location on the
217  // discrete domain. For the 1D case, an index is thus NOT an
218  // offset. When we write "imgb(5)", we designate the first pixel of
219  // imgb since this image starts at index 5.
220 
221 
222  // With this simple example we can see that images defined on
223  // different domains (or set of points) can interoperate. The set
224  // of points an image is defined on can be accessed and printed.
225  // The following code:
226 
227  std::cout << "img3a.points() = " << img3a.points() << std::endl
228  << "img3b.points() = " << img3b.points() << std::endl;
229 
230  // gives:
231  // img3a.points() = { (0) .. (19) }
232  // img3b.points() = { (5) .. (14) }
233 
234  // The notion of point sets plays an important role in Olena. Many
235  // tests are performed at run-time to ensure that the program is
236  // correct.
237 
238  // For instance, the algorithm data::paste tests that the set of
239  // points of img3b (whose values are to be pasted) is a subset of
240  // the destination image. We can reproduce this same test:
241 
242  std::cout << (img3b.points() <= img3a.points() ?
243  "true" :
244  "false") << std::endl; // which gives 'true'.
245 
246  // Accessing the value of an image at a given point also performs a
247  // test to make sure that this point belongs to the image domain
248  // (and consequently that data access in memory is valid). For
249  // instance, calling "img3a(9)" actually runs a code equivalent to
250  // this test:
251 
252  point1d p(9);
253  std::cout << (img3a.points().has(p) ?
254  "true" :
255  "false") << std::endl; // which gives 'true'.
256 
257  // The type of 1D image points is "point1d". The 1D image type
258  // features the method "operator()(point1d p)"; when we write
259  // "img3a(9)" it is just a shortcut for "img3a( point1d(9) )".
260 
261  // When having a point we can access its index following:
262  std::cout << p.ind() << std::endl; // which gives 9.
263 
264  // To know if a point belongs to an image domain or not, we can run
265  // this shorter test:
266  std::cout << (img3a.has(p) ?
267  "true" :
268  "false") << std::endl; // which gives 'true'.
269 
270 
271  // Since the notion of point is independent from the image it
272  // applies on, we can form expressions where p is used on several
273  // images:
274 
275  img3a(p) = 'M', img3b(p) = 'W'; // At index 9, both values change.
276  debug::println(img3a);
277  debug::println(img3b);
278  // we obtain:
279  // a a a a a b b b b M b b b b b a a a a a
280  // b b b b W b b b b b
281 
282 
283  // To modify all the values of an image we can iterate over its
284  // domain with an index i:
285 
286  for (int i = 5; i <= 14; ++i)
287  img3b.at(i) = 'a' + i - 5;
288  debug::println(img3b);
289  // a b c d e f g h i j
290 
291  // There is a safer way to iterate that prevents from providing a
292  // wrong value for the minimum or maximum index value:
293  for (int i = img3b.min_ind(); i <= img3b.max_ind(); ++i)
294  img3b.at(i) = 'b' + i - img3b.min_ind();
295  debug::println(img3b);
296  // b c d e f g h i j k
297 
298 
299  // The Olena library was built with the following rationale:
300  //
301  // +-----------------------------------------------------------+
302  // | |
303  // | If you do not want to be "generic", if you are used to |
304  // | the classical way of browsing pixel values, you can! |
305  // | |
306  // +-----------------------------------------------------------+
307 
308 
309  // Indeed, the loops above depict the "classical" way to iterate
310  // over the contents of a 1D image. The next tour file introduces
311  // the solution provided by Olena to write better loops...
312 
313 
314  // Jump to tour1_extra.cc if you want some more information about
315  // image data management.
316 
317  // Jump to tour2.cc to continue the tour.
318 }