* doc/doxyfuns.sty: add new commands.
* doc/examples/Makefile.am
* doc/examples/examples.mk
* doc/examples/fill.cc
* doc/examples/tuto3/colorize.cc
* doc/examples/tuto3/fill_non_generic.cc.raw
* doc/examples/tuto3/first_routine.cc
* doc/examples/tuto3/println.cc
* doc/examples/tuto3/trace.cc: add new examples used in the doc.
* doc/figures/colorize-1.pgm
* doc/figures/colorize-2.ppm
* doc/figures/figures.mk
* doc/figures/fill-1.ppm
* doc/figures/fill-2.ppm
* doc/outputs/colorize.txt
* doc/outputs/first_routine.txt
* doc/outputs/outputs.mk
* doc/outputs/println.txt
* doc/outputs/trace.txt: add new reference files.
* doc/ref_guide/ref_guide.tex: fix URL and missing spaces.
* doc/tutorial/tutorial.tex: write chapter "Getting started with
Milena".
---
milena/ChangeLog | 31 ++
milena/doc/doxyfuns.sty | 4 +
milena/doc/examples/Makefile.am | 16 +-
milena/doc/examples/examples.mk | 8 +
milena/doc/examples/fill.cc | 17 +
milena/doc/examples/tuto3/colorize.cc | 25 ++
milena/doc/examples/tuto3/fill_non_generic.cc.raw | 8 +
milena/doc/examples/tuto3/first_routine.cc | 98 ++++++
milena/doc/examples/tuto3/println.cc | 33 ++
milena/doc/examples/tuto3/trace.cc | 25 ++
milena/doc/figures/colorize-1.pgm | Bin 0 -> 141 bytes
milena/doc/figures/colorize-2.ppm | Bin 0 -> 191 bytes
milena/doc/figures/figures.mk | 2 +
milena/doc/figures/fill-1.ppm | Bin 0 -> 12406 bytes
milena/doc/figures/fill-2.ppm | Bin 0 -> 12406 bytes
milena/doc/outputs/outputs.mk | 1 +
milena/doc/outputs/println.txt | 22 ++
milena/doc/outputs/trace.txt | 12 +
milena/doc/ref_guide/ref_guide.tex | 22 +-
milena/doc/tutorial/tutorial.tex | 328 ++++++++++++++++++++-
20 files changed, 635 insertions(+), 17 deletions(-)
create mode 100644 milena/doc/examples/tuto3/colorize.cc
create mode 100644 milena/doc/examples/tuto3/fill_non_generic.cc.raw
create mode 100644 milena/doc/examples/tuto3/first_routine.cc
create mode 100644 milena/doc/examples/tuto3/println.cc
create mode 100644 milena/doc/examples/tuto3/trace.cc
create mode 100644 milena/doc/figures/colorize-1.pgm
create mode 100644 milena/doc/figures/colorize-2.ppm
create mode 100644 milena/doc/figures/fill-1.ppm
create mode 100644 milena/doc/figures/fill-2.ppm
create mode 100644 milena/doc/outputs/colorize.txt
create mode 100644 milena/doc/outputs/first_routine.txt
create mode 100644 milena/doc/outputs/println.txt
create mode 100644 milena/doc/outputs/trace.txt
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 6117e06..1c20f7d 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,34 @@
+2009-04-17 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
+ Update tutorial - Write "Getting started with Milena".
+
+ * doc/doxyfuns.sty: add new commands.
+
+ * doc/examples/Makefile.am
+ * doc/examples/examples.mk
+ * doc/examples/fill.cc
+ * doc/examples/tuto3/colorize.cc
+ * doc/examples/tuto3/fill_non_generic.cc.raw
+ * doc/examples/tuto3/first_routine.cc
+ * doc/examples/tuto3/println.cc
+ * doc/examples/tuto3/trace.cc: add new examples used in the doc.
+
+ * doc/figures/colorize-1.pgm
+ * doc/figures/colorize-2.ppm
+ * doc/figures/figures.mk
+ * doc/figures/fill-1.ppm
+ * doc/figures/fill-2.ppm
+ * doc/outputs/colorize.txt
+ * doc/outputs/first_routine.txt
+ * doc/outputs/outputs.mk
+ * doc/outputs/println.txt
+ * doc/outputs/trace.txt: add new reference files.
+
+ * doc/ref_guide/ref_guide.tex: fix URL and missing spaces.
+
+ * doc/tutorial/tutorial.tex: write chapter "Getting started with
+ Milena".
+
2009-04-15 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
Small fixes.
diff --git a/milena/doc/doxyfuns.sty b/milena/doc/doxyfuns.sty
index 5424d05..a5fd47b 100644
--- a/milena/doc/doxyfuns.sty
+++ b/milena/doc/doxyfuns.sty
@@ -225,3 +225,7 @@ $$
\textbf{\textit{#1}}
}
+\newcommand{\B}[1]{
+\textbf{#1}
+}
+
diff --git a/milena/doc/examples/Makefile.am b/milena/doc/examples/Makefile.am
index c343312..57209da 100644
--- a/milena/doc/examples/Makefile.am
+++ b/milena/doc/examples/Makefile.am
@@ -17,6 +17,7 @@ noinst_PROGRAMS = \
fill-subdomain \
fill-subdomain-shorter \
fill-subimage-cfun \
+ first_routine \
forall-piter \
fun-p2v-1 \
graph-data \
@@ -50,6 +51,13 @@ tuto2_first_image \
tuto3_rw_image \
tuto4_genericity_and_algorithms
+# Tuto3
+noinst_PROGRAMS += \
+colorize \
+println \
+trace
+
+
accu_right_instanciation_SOURCES = accu-right-instanciation.cc
borderthickness_SOURCES = borderthickness.cc
box2d_bbox_SOURCES = box2d-bbox.cc
@@ -64,6 +72,7 @@ fill_part_image_SOURCES = fill-part-image.cc
fill_subdomain_SOURCES = fill-subdomain.cc
fill_subdomain_shorter_SOURCES = fill-subdomain-shorter.cc
fill_subimage_cfun_SOURCES = fill-subimage-cfun.cc
+first_routine_SOURCES = tuto3/first_routine.cc
forall_piter_SOURCES = forall-piter.cc
fun_p2v_1_SOURCES = fun-p2v-1.cc
graph_data_SOURCES = graph-data.cc
@@ -95,6 +104,11 @@ tuto2_first_image_SOURCES = tuto2_first_image.cc
tuto3_rw_image_SOURCES = tuto3_rw_image.cc
tuto4_genericity_and_algorithms_SOURCES = tuto4_genericity_and_algorithms.cc
+# Tuto 3
+colorize_SOURCES = tuto3/colorize.cc
+println_SOURCES = tuto3/println.cc
+trace_SOURCES = tuto3/trace.cc
+
all: clean-figures
mkdir -p $(OUTPUTS_BUILDDIR)
mkdir -p $(FIGURES_BUILDDIR)
@@ -171,7 +185,7 @@ fix-refdata:
split-samples:
mkdir -p $(EXAMPLES_BUILDDIR)
@failcom='exit 1'; \
- list='$(EXAMPLES_SRCDIR)/*.cc'; for file in $$list; do \
+ list=`find $(EXAMPLES_SRCDIR) -type f -name '*.cc'`; for file in $$list; do \
$(DOC_SRCDIR)/tools/split_sample.sh $$file cc $(EXAMPLES_BUILDDIR)\
|| eval $$failcom; \
done
diff --git a/milena/doc/examples/examples.mk b/milena/doc/examples/examples.mk
index 65b0a3f..4449d52 100644
--- a/milena/doc/examples/examples.mk
+++ b/milena/doc/examples/examples.mk
@@ -48,13 +48,21 @@ examples/point-1.cc \
examples/box2d-bbox.cc \
examples/forall-piter.cc \
examples/ima-size.cc \
+examples/tuto2 \
examples/examples.mk \
+examples/tuto4 \
examples/borderthickness.cc \
examples/Makefile.in \
examples/ima-load.cc \
examples/ima-has.cc \
examples/win-create-1.cc \
examples/samples.mk \
+examples/tuto3 \
+examples/tuto3/fill_non_generic.cc.raw \
+examples/tuto3/colorize.cc \
+examples/tuto3/println.cc \
+examples/tuto3/trace.cc \
+examples/tuto3/first_routine.cc \
examples/accu-wrong-instanciation.cc.raw \
examples/accu-right-instanciation.cc \
examples/ima2d-5.cc \
diff --git a/milena/doc/examples/fill.cc b/milena/doc/examples/fill.cc
index 0e98634..c4184b4 100644
--- a/milena/doc/examples/fill.cc
+++ b/milena/doc/examples/fill.cc
@@ -1,4 +1,6 @@
#include <mln/essential/2d.hh>
+#include <tests/data.hh>
+#include <doc/tools/sample_utils.hh>
// \{
template <typename I>
@@ -12,4 +14,19 @@ void fill(I& ima, mln_value(I) v)
int main()
{
+ using namespace mln;
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, MLN_IMG_DIR "/small.ppm");
+
+ // \{
+ box2d b(20,20);
+ fill((ima | b).rw(), literal::green);
+ // \}
+ doc::ppmsave(ima, "fill");
+
+ // \{
+ fill(ima, literal::green);
+ // \}
+ doc::ppmsave(ima, "fill");
}
diff --git a/milena/doc/examples/tuto3/colorize.cc
b/milena/doc/examples/tuto3/colorize.cc
new file mode 100644
index 0000000..59dba6f
--- /dev/null
+++ b/milena/doc/examples/tuto3/colorize.cc
@@ -0,0 +1,25 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/colorize.hh>
+#include <doc/tools/sample_utils.hh>
+
+int main()
+{
+ using namespace mln;
+ using namespace mln::value;
+
+ // \{
+ int_u8 vals[25] = { 100, 100, 200, 200, 230,
+ 100, 100, 200, 230, 230,
+ 140, 140, 140, 0, 0,
+ 65, 186, 65, 127, 127,
+ 65, 65, 65, 127, 127 };
+
+ image2d<int_u8> ima = make::image2d(vals);
+ image2d<rgb8> ima_color = debug::colorize(rgb8(), ima, 230);
+ // \}
+
+ doc::pgmsave(ima, "colorize");
+ doc::ppmsave(ima_color, "colorize");
+}
diff --git a/milena/doc/examples/tuto3/fill_non_generic.cc.raw
b/milena/doc/examples/tuto3/fill_non_generic.cc.raw
new file mode 100644
index 0000000..d2cd39b
--- /dev/null
+++ b/milena/doc/examples/tuto3/fill_non_generic.cc.raw
@@ -0,0 +1,8 @@
+// Java or C -like code
+
+void fill(image ima, unsigned char v)
+{
+ for (int i = 0; i < ima->nrows; ++i)
+ for (int j = 0; j < ima->ncols; ++j)
+ ima->data[i][j] = v;
+}
diff --git a/milena/doc/examples/tuto3/first_routine.cc
b/milena/doc/examples/tuto3/first_routine.cc
new file mode 100644
index 0000000..a0eb870
--- /dev/null
+++ b/milena/doc/examples/tuto3/first_routine.cc
@@ -0,0 +1,98 @@
+#include <mln/essential/2d.hh>
+#include <tests/data.hh>
+#include <doc/tools/sample_utils.hh>
+
+// \{
+namespace mln
+{
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ my_algorithm(const Image<I>& ima_,
+ const Neighborhood<N>& nbh_)
+ {
+ trace::entering("my_algorithm");
+
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ typedef value::label_8 V;
+ V nlabels;
+ mln_ch_value(I,V) lbl = labeling::blobs(ima, nbh, nlabels);
+ util::array<unsigned>
+ count = labeling::compute(accu::meta::count(), lbl, nlabels);
+
+ mln_concrete(I) output;
+ initialize(output, ima);
+ data::fill(output, literal::one);
+
+ for (unsigned i = 1; i <= nlabels; ++i)
+ if (count[i] < 10u)
+ data::fill((output | pw::value(lbl) == pw::cst(i)).rw(), literal::zero);
+
+ trace::exiting("my_algorithm");
+ return output;
+ }
+
+} // end of namespace mln
+// \}
+
+namespace sandbox
+{
+
+ using namespace mln;
+
+ // \{
+ template <typename I, typename N>
+ mln_concrete(I)
+ my_algorithm(const Image<I>& ima_,
+ const Neighborhood<N>& nbh_)
+ // \}
+ {
+ // \{
+ trace::entering("my_algorithm");
+ // \}
+
+ // \{
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+ // \}
+
+ // \{
+ typedef value::label_8 V;
+ V nlabels;
+ mln_ch_value(I,V) lbl = labeling::blobs(ima, nbh, nlabels);
+ util::array<unsigned>
+ count = labeling::compute(accu::meta::count(), lbl, nlabels);
+ // \}
+
+ // \{
+ mln_concrete(I) output;
+ initialize(output, ima);
+ data::fill(output, literal::one);
+ // \}
+
+ // \{
+ for (unsigned i = 1; i <= nlabels; ++i)
+ if (count[i] < 10u)
+ data::fill((output | pw::value(lbl) == pw::cst(i)).rw(), literal::zero);
+ // \}
+
+ // \{
+ trace::exiting("my_algorithm");
+ return output;
+ // \}
+ }
+
+} // end of namespace mln
+
+int main()
+{
+ mln::image2d<bool> test(2,2);
+ mln_assertion(sandbox::my_algorithm(test, mln::c4())
+ == mln::my_algorithm(test, mln::c4()));
+}
diff --git a/milena/doc/examples/tuto3/println.cc b/milena/doc/examples/tuto3/println.cc
new file mode 100644
index 0000000..8ee60be
--- /dev/null
+++ b/milena/doc/examples/tuto3/println.cc
@@ -0,0 +1,33 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/data/fill.hh>
+#include <mln/border/fill.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/println.hh>
+#include <mln/debug/println_with_border.hh>
+
+int main()
+{
+ using namespace mln;
+ using namespace mln::value;
+
+ {
+ std::cout << "// \\{" << std::endl;
+ // \{
+ image2d<int_u8> ima(5,5);
+ data::fill(ima, 2);
+ debug::println(ima);
+ // \}
+ std::cout << "// \\}" << std::endl;
+ }
+
+ {
+ std::cout << "// \\{" << std::endl;
+ // \{
+ image2d<int_u8> ima(5,5);
+ data::fill(ima, 2);
+ border::fill(ima, 7);
+ debug::println_with_border(ima);
+ // \}
+ std::cout << "// \\}" << std::endl;
+ }
+}
diff --git a/milena/doc/examples/tuto3/trace.cc b/milena/doc/examples/tuto3/trace.cc
new file mode 100644
index 0000000..3e0cd41
--- /dev/null
+++ b/milena/doc/examples/tuto3/trace.cc
@@ -0,0 +1,25 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/value/label_8.hh>
+#include <mln/labeling/blobs.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/geom/bbox.hh>
+
+int main()
+{
+ using namespace mln;
+ using namespace mln::value;
+
+ image2d<bool> ima(200,300);
+ label_8 nlabels;
+ // \{
+ // ...
+ trace::quiet = false;
+
+ labeling::blobs(ima, c4(), nlabels);
+
+ trace::quiet = true;
+
+ geom::bbox(ima);
+ // ...
+ // \}
+}
diff --git a/milena/doc/figures/colorize-1.pgm b/milena/doc/figures/colorize-1.pgm
new file mode 100644
index 0000000000000000000000000000000000000000..d7222c74ff5c14fbc536a26736f4f4a3d9427ee7
GIT binary patch
literal 141
zcmWGA<x*B~Pt8j$N-RlDQAny(@XgFg%}Z1;)H6^}$S5f(u+rDh2Z`wA6s4r<r50qC
zB<iIV0d=_sc!oGC1f>?ICKe@UC?w{kD7d7SrRL-p<fi78DEK5M<pT}PFRE0~@CkBp
m)#Nf&Fy%5bHRVc4IdS3{ka+g2r>BR3!Eu*keZ8Y2kN^O=qA;8Q
literal 0
HcmV?d00001
diff --git a/milena/doc/figures/colorize-2.ppm b/milena/doc/figures/colorize-2.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..c7b0c0151897e22f7a089ef8d7f16af669a11061
GIT binary patch
literal 191
zcmWGA<5E^|Pt8j$N-RlDQAny(@XgFg%}Z1;)H6^}$S5f(u+rDh2Z`wA6s4r<r50qC
zB<iIV0d=_sc!oGC1f>?ICKe@UC?w{kD7d7SrRL-p<fi78DEK5M<pT}PFRE0~@CkBp
z)#Nf&Fy%5bHRTeKkOCq<#jQZ3ILQpo1+szYV$L!MVgQ3p2d@_fhyuy?T3dh!$bcXS
F7XaWkM92UD
literal 0
HcmV?d00001
diff --git a/milena/doc/figures/figures.mk b/milena/doc/figures/figures.mk
index 41dba2b..42d8724 100644
--- a/milena/doc/figures/figures.mk
+++ b/milena/doc/figures/figures.mk
@@ -27,6 +27,7 @@ figures/logical-not-3.pbm \
figures/tuto4_genericity_and_algorithms-3.pbm \
figures/tuto4_genericity_and_algorithms-1.ppm \
figures/extend-4.ppm \
+figures/fill-2.ppm \
figures/tuto4_genericity_and_algorithms-8.ppm \
figures/labeling-compute-1.pbm \
figures/tuto3_rw_image-3.ppm \
@@ -35,4 +36,5 @@ figures/tuto4_genericity_and_algorithms-8.pgm \
figures/extend-2.ppm \
figures/tuto4_genericity_and_algorithms-2.ppm \
figures/fill-subdomain-1.pbm \
+figures/fill-1.ppm \
figures/tuto3_rw_image-2.ppm
diff --git a/milena/doc/figures/fill-1.ppm b/milena/doc/figures/fill-1.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..ce4039f142f1e01315853e4bfbac4a24efa81e6f
GIT binary patch
literal 12406
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
G@c#vb$#MJu
literal 0
HcmV?d00001
diff --git a/milena/doc/figures/fill-2.ppm b/milena/doc/figures/fill-2.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..4d4213108284b26441c0e14fdac067d72373e8c0
GIT binary patch
literal 12406
zcmeIu!3u&v6oui|^As1_)Ml(u7wrNi0t1m=V9Xl|rZNqIPha*HEq*ww1LrKhGBs;C
z>!98RZKR&%+Vwg(+1s5+8^UyqqVd<*-ZyG>>VmTmzpV1|ayv<-FLnOjiW?fq^sW6k
zJ#`3DxO!YpM?cG^sIq)((pb{i9FoMWJ}ZI%0tg_000IagfB*srAb<b@2q1s}0tg_0
n00IagfB*srAb<b@2q1s}0tg_000IagfB*srAb<b@e=hI^FboyG
literal 0
HcmV?d00001
diff --git a/milena/doc/outputs/colorize.txt b/milena/doc/outputs/colorize.txt
new file mode 100644
index 0000000..e69de29
diff --git a/milena/doc/outputs/first_routine.txt b/milena/doc/outputs/first_routine.txt
new file mode 100644
index 0000000..e69de29
diff --git a/milena/doc/outputs/outputs.mk b/milena/doc/outputs/outputs.mk
index 1e4c9cf..bb57832 100644
--- a/milena/doc/outputs/outputs.mk
+++ b/milena/doc/outputs/outputs.mk
@@ -7,6 +7,7 @@ outputs/accu-right-instanciation.txt \
outputs/extend.txt \
outputs/ima2d-1.txt \
outputs/borderthickness.txt \
+outputs/first_routine.txt \
outputs/ima-save.txt \
outputs/fill-subimage-cfun.txt \
outputs/labeling-compute.txt \
diff --git a/milena/doc/outputs/println.txt b/milena/doc/outputs/println.txt
new file mode 100644
index 0000000..307681c
--- /dev/null
+++ b/milena/doc/outputs/println.txt
@@ -0,0 +1,22 @@
+// \{
+2 2 2 2 2
+2 2 2 2 2
+2 2 2 2 2
+2 2 2 2 2
+2 2 2 2 2
+
+// \}
+// \{
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+
+// \}
diff --git a/milena/doc/outputs/trace.txt b/milena/doc/outputs/trace.txt
new file mode 100644
index 0000000..f1506c7
--- /dev/null
+++ b/milena/doc/outputs/trace.txt
@@ -0,0 +1,12 @@
+labeling::blobs {
+ core::initialize {}
+ data::fill {
+ data::fill_with_value {
+ data::impl::fill_with_value_one_block {
+ data::memset_ {
+ data::impl::memset_ {}
+ } data::memset_
+ } data::impl::fill_with_value_one_block
+ } data::fill_with_value
+ } data::fill
+} labeling::blobs - 0.08s
diff --git a/milena/doc/ref_guide/ref_guide.tex b/milena/doc/ref_guide/ref_guide.tex
index 59b6199..1464207 100644
--- a/milena/doc/ref_guide/ref_guide.tex
+++ b/milena/doc/ref_guide/ref_guide.tex
@@ -140,8 +140,8 @@ A copy of the license is provided in the file COPYING.DOC.
The latest version of Olena is available at the following addresses:
\begin{itemize}
- \item
http://www.lrde.epita.fr/dload/olena/olena.tar.gz
- \item
http://www.lrde.epita.fr/dload/olena/olena.tar.bz2
+ \item
\href{http://www.lrde.epita.fr/dload/olena/olena.tar.gz}{http://www.lrde.epita.fr/dload/olena/olena.tar.gz}
+ \item
\href{http://www.lrde.epita.fr/dload/olena/olena.tar.bz2}{http://www.lrde.epita.fr/dload/olena/olena.tar.bz2}
\end{itemize}
@@ -151,19 +151,19 @@ The latest version of Olena is available at the following
addresses:
First uncompress the archive. According to the downloaded archive, the options
are different.
\begin{verbatim}
-$tar zxvf olena.tar.gz
+$ tar zxvf olena.tar.gz
\end{verbatim}
Or
\begin{verbatim}
-$tar jxvf olena.tar.bz2
+$ tar jxvf olena.tar.bz2
\end{verbatim}
Then follow these steps:
\begin{verbatim}
-$mkdir olena-build
-$cd olena-build
-$../olena-1.0/configure && make
-$sudo make install
+$ mkdir olena-build
+$ cd olena-build
+$ ../olena-1.0/configure && make
+$ sudo make install
\end{verbatim}
@@ -241,7 +241,7 @@ Before writing your first program, please be ware of these hints:
slow down a program though and these tests can be disabled by compiling
using \code{-DNDEBUG}.
\begin{verbatim}
-g++ -DNDEBUG -Ipath/to/mln my_program.cc
+$ g++ -DNDEBUG -Ipath/to/mln my_program.cc
\end{verbatim}
\item If you decide to use optimization flags to compile for debugging,
@@ -1681,7 +1681,7 @@ You can extend the range of supported files by installing
third-parties librarie
\end{itemize}
\doxysection{ioim}{ImageMagick}
- \href{http://www.imagemagick.org/}{http://www.imagemagick.org/}
+ \href{http://www.imagemagick.org}{http://www.imagemagick.org}
You have to install ImageMagick with Magick++ support. You will be able to
load every file recognized as an image by ImageMagick.
@@ -1701,7 +1701,7 @@ You can extend the range of supported files by installing
third-parties librarie
installation.
\doxysection{iodcm}{GDCM}
-
\href{http://apps.sourceforge.net/mediawiki/gdcm/}{http://apps.sourceforge.net/mediawiki/gdcm/}
+
\href{http://apps.sourceforge.net/mediawiki/gdcm}{http://apps.sourceforge.net/mediawiki/gdcm}
GDCM is a library for manipulating DICOM files. DICOM files are used in
medical imaging.
diff --git a/milena/doc/tutorial/tutorial.tex b/milena/doc/tutorial/tutorial.tex
index 3326b24..a69e28f 100644
--- a/milena/doc/tutorial/tutorial.tex
+++ b/milena/doc/tutorial/tutorial.tex
@@ -466,18 +466,18 @@ There are other ways to get to know what is the status of the
project.
\begin{itemize}
\item Olena's trac\\
- \href{https://trac.lrde.org/olena} \\
+ \href{https://trac.lrde.org/olena}{https://trac.lrde.org/olena} \\
Here is the roadmap, the current open tickets/bugs/improvements which
are taken in consideration. A source browser is also available.
\item Olena's Buildfarm \\
- \href{https://buildfarm.lrde.org/buildfarm/oln/} \\
+
\href{https://buildfarm.lrde.org/buildfarm/oln/}{https://buildfarm.lrde.org/buildfarm/oln/}
\\
The official buildfarm. Every night and after each commit, tests
are compiled and run. The buildfarm can show you whether it is safe
to update your svn copy of Milena or not\ldots
\item Test failures
- \href{http://www.lrde.epita.fr/dload/olena/test-failures-daily.html}
+
\href{http://www.lrde.epita.fr/dload/olena/test-failures-daily.html}{http://www.lrde.epita.fr/dload/olena/test-failures-daily.html}
\\
Through this page, you can see exactly which tests do not compile or pass.
This page is updated every night.
@@ -703,13 +703,18 @@ Text and image outputs will be respectively stored in
Few tools are provided with Milena. They can be considered as full program
examples.
-Currently two tools are available:
+Currently two tools are available: \\
+
\begin{tabular}{l l}
area\_flooding.cc & FIXME:description \\
\hline
seed2tiling.cc & FIXME:description \\
\end{tabular}
+%
+\bigskip
+%
+
To build these tools, run:
\begin{verbatim}
$ cd /my/path/to/olena-1.0/build/milena/tools
@@ -749,7 +754,319 @@ In the installed path prefix, Milena's files are located in:
%====================================
\doxychapter{tuto3}{Getting started with Milena}
-** intent
+\doxysection{getfamiliargen}{Getting familiar with genericity}
+
+One of Milena's main features is its genericity. In order to understand how to
+take benefit of it, let's see what genericity really means for us and how it is
+illustrated in the library.
+
+A \B{Generic algorithm} is written once, without duplicates, and works on
+different kind of input.
+
+Let's have a look to a small example. In any image processing library, we may be
+interested in a small routine to fill an image with data. A common
+implementation would look like this one:
+
+\doxyrawcode{tuto3/fill_non_generic}
+
+In this example, there are a lot of \B{implicit} assumptions about the input:
+\begin{itemize}
+ \item The input image has to be 2D;
+ \item Its definition domain has to be a rectangle starting at (0,0);
+ \item Data cannot be of a different type than \type{unsigned char};
+ \item Image data need to be stored as a 2D array in RAM.
+\end{itemize}
+So, what would happen if we would like to use it for 3D images, use rgb8 as
+value or even work on a region of interest?
+
+This implementation would require to be reimplemented and the user would have to
+deal with the various version of the fill routine. For the developer, it is error
+prone, redundant and hard to maintain. For the user, it is confusing and forces
+to always think about what he is manipulating.
+According to our definition, this algorithm is clearly \B{not} generic.
+
+This is not acceptable and that's why Milena is developped considering
+genericity and user/developer friendlyness.
+
+With Milena, the previous example would be written as follow:
+
+\doxycode{fill}
+
+In this version, the routine can take any kind of image types as arguments. So
+it is for the values: The expected type depends on the value used in the
+given image.
+The \code{for\_all} loop is also significantly generic to support any kind of
+images since the iterator guarantees it will pass through every sites.
+
+This code is more generic and remains really close to the common description of
+the generic algorithm.
+
+As a result, with this algorithm we can fill an image,...
+\doxycode[2]{fill}
+\doxyfigure[1]{fill}{3cm}
+
+... Or fill only a region of interest (a set of points).
+\doxycode[3]{fill}
+\doxyfigure[2]{fill}{3cm}
+
+
+
+\doxysection{firstgenalgo}{First generic algorithm}
+In this section, we will introduce several routines/tools which are useful while
+writing generic algorithms. It is more important to focus on these
+routines/tools than what this program actually does.
+
+
+Here is the full example:
+
+\doxycode[1]{first_routine}
+Let's see the different parts of the algorithm.
+
+
+\doxycode[2]{first_routine}
+The prototype is restrictive enough, readable and still generic.
+We use concepts to statically check that the generic type passed as
+parameter is what the routine expects. The ``exact'' image type is \type{I}. For
+instance an image of type \type{image2d} inherits from \type{Image<image2d>}. So
+an \type{image2d} is an \type{Image<I>}.
+Note that the return type of this function is defined by a macro.
+\code{mln\_concrete} is a macro hidding tricky mechanisms (traits) used in Milena.
+The important point to remember is that a generic function should not return
+\type{I} directly but \code{mln\_concrete(I)} instead.
+
+
+\doxycode[3]{first_routine}
+Like any Milena's routine, note that we use \code{trace}. This debugging tool
+will be detailled in section \ref{debughints}.
+
+
+\doxycode[4]{first_routine}
+Since the function take some arguments thanks their concept, these object cannot
+be used as such. Indeed, concepts are empty shells only used for dispatching and
+concept checking, that's the reason why they are parameterized with their exact
+type. The exact type let us know what is the real type of the object. To get an
+objet with the exact type, simply call \code{exact()}.
+Of course, it is always a good idea to add few preconditions to help during
+debug.
+
+
+\doxycode[5]{first_routine}
+In this portion of code, the image is labeled and the number of site per label
+is computed. This code does not depend on the image type at all. Again, a macro
+\code{mln\_ch\_value} (``mln change value'') helps us. \code{labeling::blobs} is
a routine returning an
+image of the same kind as the input image but with a different value.
+\code{mln\_ch\_value} enables the possibility of doing that, whatever the image type
+\type{I} and whatever its value type, it returns the same image type with a
+different value type.
+
+
+\doxycode[6]{first_routine}
+The output image is declared here. Like any variable, it must be initialized at
+some point. To do so, \code{initialize()} is provided. It is a generic routine
+which can initialize the geometry any kind of image with another image of the
+same kind.
+After this call, \var{output} has a valid domain and is valid. It can be used in
+an algorithm, here \code{data::fill}, to have its values modified.
+Note that the value passed to \code{data::fill} is also generic. The library
+includes few generic common values from which any value type can convert to.
+
+
+\doxycode[7]{first_routine}
+In this part, every region from the labeled image, of which cardinality is lower
+than 10 sites, is set to \val{literal::zero} in \var{output}.
+Once again, a generic value is used in order to avoid a constraints on the image
+value type.
+
+
+\doxycode[8]{first_routine}
+Don't forget to close the trace before exiting the function. Then return the
+result.
+
+
+
+%FIXME: add an example to show how a routine behavior depends on its arguments.
+% => cf. des images etendues ou non et un parcours de voisinage.
+
+
+\doxysection{compilhints}{Compilation}
+
+\doxysubsection{howtocompile}{Include path}
+
+If Milena has been installed in a custom directory, e.g. not /usr/include or
+/usr/local/include, the path to the library headers must be passed to the
+compiler.
+
+With g++ and MinGW, the option is \B{-I<path>}.
+\begin{verbatim}
+$ g++ -Ipath/to/mln my_program.cc
+\end{verbatim}
+
+For other compilers, please look at the documentation and search for ``include
+path''.
+
+
+\doxysubsection{liblink}{Library linking}
+As it is usually expected when using a library, no library linking is needed for
+the library itself.
+Milena is a ``header only'' library and is compiled ``on demand'' with
your
+program.
+
+If you use specific input/output you may need to link your program with the
+right graphic library. For more information, please refer to section
+\doxyref{inputoutput} in the Quick Reference Guide.
+
+
+\doxysubsection{compildndebug}{Disable Debug}
+By default, Olena enables a lot of internal pre and post conditions. Usually,
+this is a useful feature and it should be enabled. It can heavily slow down a
+program though and these tests can be disabled by compiling using -DNDEBUG:
+
+\begin{verbatim}
+$ g++ -DNDEBUG -Ipath/to/mln my_program.cc
+\end{verbatim}
+
+\doxysubsection{compoptimflags}{Compiler optimization flags}
+
+In this section you will find remarks about the compiler optimization flags and
+their impact on the compilation and execution time.
+
+
+\doxysubsubsection{compoptimgcc}{GCC}
+
+\begin{itemize}
+ \item \B{-O0}, combined with -DNDEBUG, it leads to the fastest compilation
+ time. The execution is somewhat slow though since dispatch functions and one
+ line members are not inlined by the compiler.
+ \item \B{-O1}, best compromise between compilation time and execution time.
+ \item \B{-O2}, \B{-O3}, combined with -DNDEBUG, it leads to the best execution
+ time. However these optimizations dramatically slow down the compilation and
+ requires much more memory at compile time.
+\end{itemize}
+
+\doxysubsubsection{compoptimother}{Other compilers}
+
+Currently, have not tested different optimization flags with other compilers. If
+you did, please report us your results.
+
+
+
+\doxysection{debughints}{Debug hints}
+
+\doxysubsection{gdbhints}{Using assertions and GDB}
+As said above, Milena already includes a lot of post and pre conditions.
+Thus, if you made a mistake in your code there is a high probability that it
+will be detected at run time. If an assertion fail, we advice you to compile
+with the following options:
+
+\begin{verbatim}
+$ g++ -ggdb -Ipath/to/mln my_program.cc
+\end{verbatim}
+
+Note that you \B{MUST NOT} compile \var{-DNDEBUG} other the assertions will be
+deactivated.
+Once compiled, restart the program with GDB.
+
+\begin{verbatim}
+$ gdb ./my_program
+\end{verbatim}
+
+In the GDB console, run it again.
+\begin{verbatim}
+(gdb) run <any parameter you may want to pass to the program>
+\end{verbatim}
+
+When an assertion fails, in the GDB console simply type:
+\begin{verbatim}
+(gdb) bt
+\end{verbatim}
+
+The full backtrace will be printed out and you will be able to find from where
+the error come from. The filenames, the line numbers and the parameters values
+are printed out in the backtrace as you can see in the following example:
+
+\begin{verbatim}
+#0 0xffffe410 in __kernel_vsyscall ()
+#1 0xb7d00640 in raise () from /lib/i686/cmov/libc.so.6
+#2 0xb7d02018 in abort () from /lib/i686/cmov/libc.so.6
+#3 0xb7cf95be in __assert_fail () from /lib/i686/cmov/libc.so.6
+#4 0x0804e094 in mln::image2d<bool>::has (this=0xbff32f34, p=@0xbff32f3c)
+ at /lrde/stockholm/lazzara/svn/olena/git/oln/milena/mln/core/image/image2d.hh:442
+#5 0x0804e6d7 in mln::image2d<bool>::operator() (this=0xbff32f34, p=@0xbff32f3c)
+ at /lrde/stockholm/lazzara/svn/olena/git/oln/milena/mln/core/image/image2d.hh:460
+#6 0x080490b0 in main () at test.cc:18
+\end{verbatim}
+
+
+
+\doxysubsection{traces}{Traces}
+Sometimes, compiling for GDB without optimization flags and with debug
+assertions enabled could lead to execution time dramaticaly high.
+If the function parameter values are not necessary for debbuging,
+a good alternative is the trace system provided in Milena.
+Each time a routine is called, a trace log is written.
+
+This trace allows to follow the stack trace at runtime. It also provides the
+time passed in each function call if the call last at least 10ms.
+
+In order to enable traces in a program, set the related global variable to
+true:
+\begin{verbatim}
+...
+trace::quiet = true;
+...
+\end{verbatim}
+
+Since it's a global variable, at anytime in the source code, the trace can be
+disabled.
+
+\doxycode[1]{trace}
+
+The previous code will produce the following trace:
+
+\begin{verbatim}
+labeling::blobs {
+ core::initialize {}
+ data::fill {
+ data::fill_with_value {
+ data::impl::fill_with_value_one_block {
+ data::memset_ {
+ data::impl::memset_ {}
+ } data::memset_
+ } data::impl::fill_with_value_one_block
+ } data::fill_with_value
+ } data::fill
+} labeling::blobs - 0.08s
+\end{verbatim}
+
+As you can see, \code{labeling::blobs} is located just after having set
+\var{trace::quiet} to \val{true} so its trace is part of the output.
+\code{geom::bbox}'s trace is not part of the output though since traces have
+been disabled just before it is called.
+
+
+\doxysubsection{debugroutines}{Debug routines}
+Milena also provides a lot of debug tools. Here is a small list of the tools:
+\begin{itemize}
+ \item mln::debug::println, print an image in the console.
+ \doxycode[1]{println}
+ \doxymoutput[1]{println}
+
+ \item mln::debug::println\_with\_border, print an image in the console withs
+ its border.
+ \doxycode[2]{println}
+ \doxymoutput[2]{println}
+
+ \item mln::debug::colorize, colorize a label image with random colors.
+ \doxycode[1]{colorize}
+
+ \begin{center}
+ \begin{tabular}{c c c}
+ \doxyfigure[1]{colorize}{3cm} & ~\huge{$\rightarrow$}~ &
+ \doxyfigure[2]{colorize}{3cm} \\
+ \end{tabular}
+ \end{center}
+\end{itemize}
+
A very simple processing chain; the target is the end-user!
@@ -763,6 +1080,7 @@ compilation time w.r.t compilation options (O1, DNDEBUG).
+
%====================================
\doxychapter{tuto4}{Step 4: Load and save images}
--
1.5.6.5