last-svn-commit-835-g78843e4 Compute font and boldness data.

* scribo/core/component_features_data.hh, * scribo/core/component_info.hh, * scribo/core/line_info.hh, * scribo/core/paragraph_info.hh, * scribo/core/paragraph_set.hh: Add support for text features in core structures. * scribo/debug/text_color_image.hh: New debug routine. * scribo/estim/components_features.hh: * scribo/estim/font_boldness.hh, * scribo/estim/font_color.hh, * scribo/estim/internal/compute_skeleton.hh: New. * scribo/io/xml/internal/extended_page_xml_visitor.hh, * scribo/io/xml/internal/full_xml_visitor.hh: Use text features in XML. * scribo/primitive/extract/components.hh, * scribo/text/extract_lines.hh: Add new overloads * scribo/text/extract_lines_with_features.hh: New. * scribo/toolchain/internal/content_in_doc_functor.hh: Update call to extract::components. * src/debug/Makefile.am, * src/debug/show_components_boldness.cc, * src/debug/show_components_color.cc, * src/debug/show_lines_boldness.cc: New debug examples. * tests/Makefile.am, * tests/estim/Makefile.am, * tests/estim/font_boldness.cc, * tests/estim/font_color.cc: New tests. * tests/img/phillip.pbm, * tests/img/phillip.ppm: New test data. --- scribo/ChangeLog | 43 ++++ scribo/scribo/core/component_features_data.hh | 68 ++++++ scribo/scribo/core/component_info.hh | 40 ++++- scribo/scribo/core/line_info.hh | 118 +++++++++++- scribo/scribo/core/paragraph_info.hh | 102 +++++++++- scribo/scribo/core/paragraph_set.hh | 11 + scribo/scribo/debug/text_color_image.hh | 100 +++++++++ scribo/scribo/estim/components_features.hh | 169 +++++++++++++++ scribo/scribo/estim/font_boldness.hh | 215 ++++++++++++++++++++ scribo/scribo/estim/font_color.hh | 206 +++++++++++++++++++ scribo/scribo/estim/internal/compute_skeleton.hh | 112 ++++++++++ .../io/xml/internal/extended_page_xml_visitor.hh | 9 +- scribo/scribo/io/xml/internal/full_xml_visitor.hh | 33 ++-- scribo/scribo/primitive/extract/components.hh | 70 ++++--- scribo/scribo/text/extract_lines.hh | 22 ++ scribo/scribo/text/extract_lines_with_features.hh | 131 ++++++++++++ .../toolchain/internal/content_in_doc_functor.hh | 3 +- scribo/src/debug/Makefile.am | 16 ++ scribo/src/debug/show_components_boldness.cc | 72 +++++++ scribo/src/debug/show_components_color.cc | 73 +++++++ scribo/src/debug/show_lines_boldness.cc | 199 ++++++++++++++++++ scribo/tests/Makefile.am | 5 +- scribo/tests/estim/Makefile.am | 29 +++ scribo/tests/estim/font_boldness.cc | 46 ++++ scribo/tests/estim/font_color.cc | 48 +++++ scribo/tests/img/phillip.pbm | Bin 0 -> 1633 bytes scribo/tests/img/phillip.ppm | 5 + 27 files changed, 1895 insertions(+), 50 deletions(-) create mode 100644 scribo/scribo/core/component_features_data.hh create mode 100644 scribo/scribo/debug/text_color_image.hh create mode 100644 scribo/scribo/estim/components_features.hh create mode 100644 scribo/scribo/estim/font_boldness.hh create mode 100644 scribo/scribo/estim/font_color.hh create mode 100644 scribo/scribo/estim/internal/compute_skeleton.hh create mode 100644 scribo/scribo/text/extract_lines_with_features.hh create mode 100644 scribo/src/debug/show_components_boldness.cc create mode 100644 scribo/src/debug/show_components_color.cc create mode 100644 scribo/src/debug/show_lines_boldness.cc create mode 100644 scribo/tests/estim/Makefile.am create mode 100644 scribo/tests/estim/font_boldness.cc create mode 100644 scribo/tests/estim/font_color.cc create mode 100644 scribo/tests/img/phillip.pbm create mode 100644 scribo/tests/img/phillip.ppm diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 4592e73..2fc8d6d 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,48 @@ 2011-04-05 Guillaume Lazzara <z@lrde.epita.fr> + Compute font and boldness data. + + * scribo/core/component_features_data.hh, + * scribo/core/component_info.hh, + * scribo/core/line_info.hh, + * scribo/core/paragraph_info.hh, + * scribo/core/paragraph_set.hh: Add support for text features in + core structures. + + * scribo/debug/text_color_image.hh: New debug routine. + + * scribo/estim/components_features.hh: + * scribo/estim/font_boldness.hh, + * scribo/estim/font_color.hh, + * scribo/estim/internal/compute_skeleton.hh: New. + + * scribo/io/xml/internal/extended_page_xml_visitor.hh, + * scribo/io/xml/internal/full_xml_visitor.hh: Use text features in + XML. + + * scribo/primitive/extract/components.hh, + * scribo/text/extract_lines.hh: Add new overloads + + * scribo/text/extract_lines_with_features.hh: New. + + * scribo/toolchain/internal/content_in_doc_functor.hh: Update call + to extract::components. + + * src/debug/Makefile.am, + * src/debug/show_components_boldness.cc, + * src/debug/show_components_color.cc, + * src/debug/show_lines_boldness.cc: New debug examples. + + * tests/Makefile.am, + * tests/estim/Makefile.am, + * tests/estim/font_boldness.cc, + * tests/estim/font_color.cc: New tests. + + * tests/img/phillip.pbm, + * tests/img/phillip.ppm: New test data. + +2011-04-05 Guillaume Lazzara <z@lrde.epita.fr> + Add a new alignments extraction routine. * scribo/primitive/extract/alignments.hh, diff --git a/scribo/scribo/core/component_features_data.hh b/scribo/scribo/core/component_features_data.hh new file mode 100644 index 0000000..f5ba60f --- /dev/null +++ b/scribo/scribo/core/component_features_data.hh @@ -0,0 +1,68 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_CORE_COMPONENT_FEATURES_DATA_HH +# define SCRIBO_CORE_COMPONENT_FEATURES_DATA_HH + +/// \file +/// +/// \brief Component features data structure. + + +# include <scribo/core/def/color_type.hh> + +namespace scribo +{ + + struct component_features_data + { + bool valid; + scribo::def::color_type color; + float boldness; + }; + + + std::ostream& + operator<<(std::ostream& ostr, const component_features_data& data); + + +# ifndef MLN_INCLUDE_ONLY + + inline + std::ostream& + operator<<(std::ostream& ostr, const component_features_data& data) + { + return ostr << "features[" + << "valid=" << data.valid + << ", color=" << data.color + << ", boldness=" << data.boldness + << "]" << std::endl; + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace scribo + +#endif // ! SCRIBO_CORE_COMPONENT_FEATURES_DATA_HH diff --git a/scribo/scribo/core/component_info.hh b/scribo/scribo/core/component_info.hh index f825aee..164a242 100644 --- a/scribo/scribo/core/component_info.hh +++ b/scribo/scribo/core/component_info.hh @@ -36,6 +36,7 @@ # include <mln/core/alias/point2d.hh> # include <mln/util/object_id.hh> +# include <scribo/core/component_features_data.hh> # include <scribo/core/concept/serializable.hh> # include <scribo/core/tag/component.hh> # include <scribo/core/tag/line.hh> @@ -64,6 +65,13 @@ namespace scribo // The number of pixels in this component. unsigned card() const; + + bool has_features() const; + void update_features(const component_features_data& features); + + const component_features_data& features() const; + + component::Tag tag() const; void update_tag(component::Tag tag); @@ -72,12 +80,14 @@ namespace scribo bool is_valid() const; - private: + protected: component_id_t id_; mln::box2d bbox_; mln::point2d mass_center_; unsigned card_; + component_features_data features_; + component::Tag tag_; component::Type type_; }; @@ -106,9 +116,12 @@ namespace scribo unsigned card, component::Type type) : id_(id), bbox_(bbox), mass_center_(mass_center), card_(card), - tag_(component::None), type_(type) + type_(type) { - + if (!bbox.is_valid()) + tag_ = component::Ignored; + else + tag_ = component::None; } @@ -142,6 +155,26 @@ namespace scribo return card_; } + inline + bool + component_info::has_features() const + { + return features_.valid; + } + + inline + void + component_info::update_features(const component_features_data& features) + { + features_ = features; + } + + inline + const component_features_data& + component_info::features() const + { + return features_; + } inline component::Tag @@ -193,6 +226,7 @@ namespace scribo << ", mass_center=" << info.mass_center() << ", card=" << info.card() << ", tag=" << info.tag() + << ", features=" << info.features() << ")" << std::endl; } diff --git a/scribo/scribo/core/line_info.hh b/scribo/scribo/core/line_info.hh index 749e627..73d7856 100644 --- a/scribo/scribo/core/line_info.hh +++ b/scribo/scribo/core/line_info.hh @@ -43,10 +43,13 @@ # include <mln/core/alias/box2d.hh> # include <mln/core/alias/point2d.hh> # include <mln/accu/stat/median_h.hh> +# include <mln/accu/stat/mean.hh> # include <mln/accu/shape/bbox.hh> # include <mln/math/min.hh> # include <mln/util/object_id.hh> # include <mln/value/int_u.hh> +# include <mln/math/sqr.hh> +# include <mln/value/rgb8.hh> # include <scribo/core/tag/component.hh> # include <scribo/core/tag/line.hh> @@ -69,6 +72,7 @@ namespace scribo namespace internal { + /// Data structure for \c scribo::line_info<I>. template <typename L> struct line_info_data @@ -120,6 +124,14 @@ namespace scribo bool indented_; + float boldness_; + float boldness_reliability_; + + mln::value::rgb8 color_; + + // sqrt(Max(VAR(R), VAR(G), VAR(B))) + float color_reliability_; + std::string text_; std::string html_text_; @@ -128,6 +140,19 @@ namespace scribo }; + + // Functor used to sort components ids. + // Order by location from left to right. + template <typename L> + struct sort_comp_ids + { + sort_comp_ids(const component_set<L>& comp_set); + bool operator()(const component_id_t& l, const component_id_t& r) const; + + component_set<L> comps_; + }; + + } // end of namespace scribo::internal @@ -181,6 +206,12 @@ namespace scribo unsigned pixel_area() const; + float boldness() const; + float boldness_reliability() const; + + const mln::value::rgb8& color() const; + float color_reliability() const; + int baseline() const; int meanline() const; int ascent() const; @@ -530,6 +561,38 @@ namespace scribo template <typename L> + float + line_info<L>::boldness() const + { + return data_->boldness_; + } + + + template <typename L> + float + line_info<L>::boldness_reliability() const + { + return data_->boldness_reliability_; + } + + + template <typename L> + const mln::value::rgb8& + line_info<L>::color() const + { + return data_->color_; + } + + + template <typename L> + float + line_info<L>::color_reliability() const + { + return data_->color_reliability_; + } + + + template <typename L> int line_info<L>::baseline() const { @@ -919,6 +982,20 @@ namespace scribo char_space, char_width; + // FIXME: we should use the median for computing the line + // color. Means should be kept for variance computation. + mln::accu::stat::mean<mln::value::int_u<8> > + color_red, + color_green, + color_blue, + boldness; + + float + sum2_red = 0, + sum2_green = 0, + sum2_blue = 0, + sum2_boldness = 0; + unsigned pixel_area = 0; mln::accu::shape::bbox<P> bbox; @@ -941,8 +1018,8 @@ namespace scribo ref_line = mln::math::min(comp_set(c).bbox().pmin().row(), ref_line); } - // FIXME: compute font color! + unsigned used_comps = 0; for_all_elements(i, data_->components_) { unsigned c = data_->components_(i); @@ -959,6 +1036,22 @@ namespace scribo if (comp_set(c).type() == component::Punctuation) continue; + // This component will be used for stats, the counter is + // incremented. + ++used_comps; + + // Compute boldness + boldness.take(comp_set(c).features().boldness); + sum2_boldness += mln::math::sqr<float>(comp_set(c).features().boldness); + + // Compute color + color_red.take(comp_set(c).features().color.red()); + color_green.take(comp_set(c).features().color.green()); + color_blue.take(comp_set(c).features().color.blue()); + + sum2_red += mln::math::sqr<unsigned>(comp_set(c).features().color.red()); + sum2_green += mln::math::sqr<unsigned>(comp_set(c).features().color.green()); + sum2_blue += mln::math::sqr<unsigned>(comp_set(c).features().color.blue()); // FIXME: we must guaranty here that the relationship is from @@ -1018,6 +1111,25 @@ namespace scribo data_->components_.hook_std_vector_().end(), internal::sort_comp_ids<L>(comp_set)); + // Boldness + data_->boldness_ = boldness.to_result(); + data_->boldness_reliability_ = std::sqrt(sum2_boldness); + + // Color + data_->color_ = mln::value::rgb8(color_red, color_green, color_blue); + + // FIXME: we may prefer using the non-biased variance. + float + var_red = sum2_red / (float)(used_comps) + - mln::math::sqr<float>(color_red.to_result()), + var_green = sum2_green / (float)(used_comps) + - mln::math::sqr<float>(color_green.to_result()), + var_blue = sum2_blue / (float)(used_comps) + - mln::math::sqr<float>(color_blue.to_result()); + + data_->color_reliability_ = std::sqrt(std::max(var_red, + std::max(var_green, var_blue))); + // Char space if (char_space.card() < 2) data_->char_space_ = 0; @@ -1074,6 +1186,10 @@ namespace scribo << ", type=" << info.type() << ", bbox=" << info.bbox() << ", ebbox=" << info.ebbox() + << ", boldness=" << info.boldness() + << ", boldness_reliability=" << info.boldness_reliability() + << ", color=" << info.color() + << ", color_reliability=" << info.color_reliability() << ", components=" << info.component_ids() << ", baseline=" << info.baseline() << ", meanline=" << info.meanline() diff --git a/scribo/scribo/core/paragraph_info.hh b/scribo/scribo/core/paragraph_info.hh index f4b1309..2a9b626 100644 --- a/scribo/scribo/core/paragraph_info.hh +++ b/scribo/scribo/core/paragraph_info.hh @@ -44,6 +44,13 @@ namespace scribo paragraph_info(); paragraph_info(const line_links<L>& llinks); + /*! \brief Add a new line to this paragraph + + This method is provided for an incremental construction. + + Once this method has been called, needs_stats_update() will + return true until force_stats_update() is called. + */ void add_line(const line_info<L>& line); const mln::box2d& bbox() const; @@ -54,12 +61,25 @@ namespace scribo unsigned nlines() const; + // FIXME: add boldness? + + const mln::value::rgb8& color() const; + float color_reliability() const; + bool is_valid() const; + bool needs_stats_update() const; + void force_stats_update(); + private: mln::util::array<line_id_t> line_ids_; mln::accu::shape::bbox<mln_site(L)> bbox_; line_links<L> llinks_; + + mln::value::rgb8 color_; + float color_reliability_; + + bool needs_stats_update_; }; @@ -68,12 +88,13 @@ namespace scribo template <typename L> paragraph_info<L>::paragraph_info() + : needs_stats_update_(false) { } template <typename L> paragraph_info<L>::paragraph_info(const line_links<L>& llinks) - : llinks_(llinks) + : llinks_(llinks), needs_stats_update_(false) { } @@ -83,6 +104,9 @@ namespace scribo { line_ids_.append(line.id()); bbox_.take(line.bbox()); + + // More data may need to be updated! + needs_stats_update_ = true; } template <typename L> @@ -115,12 +139,86 @@ namespace scribo } template <typename L> + const mln::value::rgb8& + paragraph_info<L>::color() const + { + return color_; + } + + + template <typename L> + float + paragraph_info<L>::color_reliability() const + { + return color_reliability_; + } + + template <typename L> bool paragraph_info<L>::is_valid() const { return llinks_.is_valid(); } + template <typename L> + bool + paragraph_info<L>::needs_stats_update() const + { + return needs_stats_update_; + } + + template <typename L> + void + paragraph_info<L>::force_stats_update() + { + if (!needs_stats_update_) + return; + + const line_set<L>& lines = llinks_.lines(); + + mln::accu::stat::mean<mln::value::int_u<8> > + color_red, + color_green, + color_blue; + + float + sum2_red = 0, + sum2_green = 0, + sum2_blue = 0; + + for_all_elements(e, line_ids_) + { + unsigned lid = line_ids_(e); + + color_red.take(lines(lid).color().red()); + color_green.take(lines(lid).color().green()); + color_blue.take(lines(lid).color().blue()); + sum2_red += mln::math::sqr<unsigned>(lines(lid).color().red()); + sum2_green += mln::math::sqr<unsigned>(lines(lid).color().green()); + sum2_blue += mln::math::sqr<unsigned>(lines(lid).color().blue()); + } + + color_ = mln::value::rgb8(color_red.to_result(), + color_green.to_result(), + color_blue.to_result()); + + float + var_red = sum2_red / (float)line_ids_.nelements() + - mln::math::sqr<float>(color_red.to_result()), + var_green = sum2_green / (float)line_ids_.nelements() + - mln::math::sqr<float>(color_green.to_result()), + var_blue = sum2_blue / (float)line_ids_.nelements() + - mln::math::sqr<float>(color_blue.to_result()); + + color_reliability_ = std::sqrt(std::max(var_red, + std::max(var_green, var_blue))); + + // Update color + + // FIXME: Update paragraph stats + + needs_stats_update_ = false; + } template <typename L> std::ostream& @@ -129,6 +227,8 @@ namespace scribo return ostr << "paragraph_info(" << "line_ids=" << info.line_ids() << ", bbox=" << info.bbox() + << ", color=" << info.color() + << ", color_reliability=" << info.color_reliability() << ")" << std::endl; } diff --git a/scribo/scribo/core/paragraph_set.hh b/scribo/scribo/core/paragraph_set.hh index f081472..ec9f51b 100644 --- a/scribo/scribo/core/paragraph_set.hh +++ b/scribo/scribo/core/paragraph_set.hh @@ -95,6 +95,11 @@ namespace scribo scribo::paragraph_set<L> paragraph(const line_links<L>& llinks); + /// \brief Construct a paragraph set from line set information. + template <typename L> + scribo::paragraph_set<L> + paragraph(const scribo::line_set<L>& lines); + } // end of namespace scribo::make @@ -239,6 +244,9 @@ namespace scribo parset(par_id).add_line(lines(l)); } + for_all_paragraphs(p, parset) + parset(p).force_stats_update(); + return parset; } @@ -264,6 +272,9 @@ namespace scribo parset(par_id).add_line(lines(l)); } + for_all_paragraphs(p, parset) + parset(p).force_stats_update(); + return parset; } diff --git a/scribo/scribo/debug/text_color_image.hh b/scribo/scribo/debug/text_color_image.hh new file mode 100644 index 0000000..f8d76c8 --- /dev/null +++ b/scribo/scribo/debug/text_color_image.hh @@ -0,0 +1,100 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_DEBUG_TEXT_COLOR_IMAGE_HH +# define SCRIBO_DEBUG_TEXT_COLOR_IMAGE_HH + +/// \file +/// +/// Draw text components with their respective colors. + +# include <mln/core/image/image2d.hh> +# include <mln/value/rgb8.hh> +# include <mln/data/fill.hh> +# include <mln/literal/white.hh> +# include <mln/util/array.hh> + +# include <mln/pw/all.hh> +# include <mln/core/image/dmorph/image_if.hh> + +# include <scribo/core/macros.hh> +# include <scribo/core/document.hh> + +namespace scribo +{ + + namespace debug + { + using namespace mln; + + template <typename L> + image2d<value::rgb8> + text_color_image(const document<L>& doc); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename L> + image2d<mln::value::rgb8> + text_color_image(const document<L>& doc) + { + image2d<value::rgb8> debug; + initialize(debug, doc.binary_image()); + data::fill(debug, literal::white); + + const paragraph_set<L>& parset = doc.paragraphs(); + const line_set<L>& lines = doc.lines(); + const component_set<L>& comp_set = lines.components(); + const L& lbl = comp_set.labeled_image(); + + for_all_paragraphs(p, parset) + { + const mln::util::array<line_id_t>& line_ids = parset(p).line_ids(); + + for_all_paragraph_lines(lid, line_ids) + { + line_id_t l = line_ids(lid); + const mln::util::array<component_id_t>& comps = lines(l).component_ids(); + + for_all_elements(e, comps) + { + unsigned comp_id = comps(e); + data::fill(((debug | comp_set(comp_id).bbox()).rw() | (pw::value(lbl) == pw::cst(comp_id))).rw(), + parset(p).color()); + } + + } + } + + return debug; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::debug + +} // end of namespace scribo + +#endif // ! SCRIBO_DEBUG_TEXT_COLOR_IMAGE_HH diff --git a/scribo/scribo/estim/components_features.hh b/scribo/scribo/estim/components_features.hh new file mode 100644 index 0000000..ee34123 --- /dev/null +++ b/scribo/scribo/estim/components_features.hh @@ -0,0 +1,169 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_ESTIM_COMPONENT_FEATURES_HH +# define SCRIBO_ESTIM_COMPONENT_FEATURES_HH + +# include <mln/core/image/image2d.hh> +# include <mln/core/alias/neighb2d.hh> +# include <mln/topo/skeleton/crest.hh> +# include <mln/topo/skeleton/is_simple_point.hh> +# include <mln/transform/distance_front.hh> +# include <mln/logical/not.hh> +# include <mln/make/w_window2d_int.hh> +# include <mln/value/int_u8.hh> +# include <mln/arith/revert.hh> +# include <mln/morpho/skeleton_constrained.hh> +# include <mln/core/routine/extend.hh> +# include <mln/labeling/blobs.hh> +# include <mln/accu/stat/mean.hh> + + +# include <mln/data/compute.hh> +# include <mln/io/pbm/save.hh> +# include <mln/io/pgm/save.hh> +# include <mln/util/timer.hh> + +# include <scribo/core/component_set.hh> +# include <scribo/estim/font_color.hh> +# include <scribo/estim/font_boldness.hh> + +#include <mln/data/convert.hh> + + +namespace scribo +{ + + namespace estim + { + + using namespace mln; + + /// \brief Compute components features. + /// + /// \sa component_features_data + // + template <typename I, typename J, typename L> + component_set<L> + components_features(const Image<I>& input, const Image<J>& bin_input, + const component_set<L>& components); + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename I, typename J, typename L> + component_set<L> + components_features(const Image<I>& input, const Image<J>& bin_input, + const component_set<L>& components) + { + trace::entering("scribo::estim::components_features"); + + component_set<L> output = components.duplicate(); + + component_features_data features; + features.valid = true; + + typedef mln_concrete(J) B; + B skel; + L skel_lbl; + mln_value(L) nlabels; + + util::timer t; + t.start(); + { + int psi = 7; + int vals[] = { 0, 9, 0, 9, 0, + 9, 6, 4, 6, 9, + 0, 4, 0, 4, 0, + 9, 6, 4, 6, 9, + 0, 9, 0, 9, 0 }; + + typedef mln_ch_value(I,value::int_u8) dist_t; + dist_t + dist = transform::distance_front(logical::not_(bin_input), c8(), + mln::make::w_window2d_int(vals), + mln_max(value::int_u8)); + t.stop(); + std::cout << "Distance front " << t << std::endl; + t.restart(); + + dist_t dist_map = arith::revert(dist); + + t.stop(); + std::cout << "Revert " << t << std::endl; + t.restart(); + + B K = topo::skeleton::crest(bin_input, dist, c8(), psi); + + t.stop(); + std::cout << "Crest " << t << std::endl; + t.restart(); + + skel = + morpho::skeleton_constrained(bin_input, c8(), + topo::skeleton::is_simple_point<B,neighb2d>, + extend(K, false), dist_map); + + t.stop(); + std::cout << "Skeleton constrained " << t << std::endl; + } + t.restart(); + + const L& lbl = output.labeled_image(); + + for_all_comps(c, output) + { + // Estimate component color + features.color = data::compute(accu::meta::stat::mean(), + ((input | output(c).bbox()) + | (pw::value(lbl) == pw::cst(c) + && pw::value(skel)))); + + + // Estimate component boldness + features.boldness = internal::boldness_from_lbl( + (lbl | output(c).bbox()) | (pw::value(lbl) == pw::cst(c)), + (skel | output(c).bbox()) | (pw::value(lbl) == pw::cst(c))); + + output(c).update_features(features); + } + + + t.stop(); + std::cout << "compute color and boldness " << t << std::endl; + + trace::exiting("scribo::estim::components_features"); + return output; + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::estim + +} // end of namespace scribo + +# endif // ! SCRIBO_ESTIM_COMPONENT_FEATURES_HH diff --git a/scribo/scribo/estim/font_boldness.hh b/scribo/scribo/estim/font_boldness.hh new file mode 100644 index 0000000..0b145bf --- /dev/null +++ b/scribo/scribo/estim/font_boldness.hh @@ -0,0 +1,215 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_ESTIM_FONT_BOLDNESS_HH +# define SCRIBO_ESTIM_FONT_BOLDNESS_HH + +/// \file +/// +/// \brief Estimate the font color. + +# include <mln/core/image/image2d.hh> +# include <mln/core/alias/neighb2d.hh> + +# include <mln/labeling/blobs.hh> +# include <mln/accu/stat/mean.hh> +# include <mln/value/next.hh> + +# include <scribo/core/macros.hh> +# include <scribo/core/def/lbl_type.hh> +# include <scribo/estim/internal/compute_skeleton.hh> + + +namespace scribo +{ + + namespace estim + { + + using namespace mln; + + /// \brief Estimate the font color. + // + template <typename I> + float + font_boldness(const Image<I>& text_ima); + + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + + template <typename I, typename J> + float + boldness_from_lbl(const Image<I>& ima_lbl_, + const Image<J>& skel_) + { + trace::entering("scribo::estim::internal::boldness_from_lbl"); + + const I& ima_lbl = exact(ima_lbl_); + const J& skel = exact(skel_); + mln_precondition(ima_lbl.is_valid()); + mln_precondition(skel.is_valid()); + + mln_piter(I) p(ima_lbl.domain()); + int skel_p = 0, ima_p = 0; + + for_all(p) + { + if (skel(p)) + ++skel_p; + + if (ima_lbl(p)) + ++ima_p; + } + + float res = ima_p / (float) skel_p; + + trace::exiting("scribo::estim::internal::boldness_from_lbl"); + return res; + } + + + // FIXME: this version is invalid!!! It supposes that image and + // skeleton labeling associate the same id to a component and + // its corresponding skeleton. This is wrong! + template <typename I, typename J> + float + boldness_from_lbl(const Image<I>& ima_lbl_, + const mln_value(I)& nlabels, + const Image<J>& skel_lbl_) + { + trace::entering("scribo::estim::internal::boldness_from_lbl"); + + const I& ima_lbl = exact(ima_lbl_); + const J& skel_lbl = exact(skel_lbl_); + mln_precondition(ima_lbl.is_valid()); + mln_precondition(skel_lbl.is_valid()); + + mln_piter(I) p(ima_lbl.domain()); + std::vector<int> skel_p(value::next(nlabels), 0); + std::vector<int> ima_p(value::next(nlabels), 0); + + for_all(p) + { + int val = skel_lbl(p); + + if (val) + ++skel_p[val]; + + val = ima_lbl(p); + + if (val) + ++ima_p[val]; + } + + accu::stat::mean<float> mean; + for_all_ncomponents(i, nlabels) + mean.take(ima_p[i] / skel_p[i]); + + // double variance = 0.; + // for (unsigned int i = 0; i < nlabels; ++i) + // variance += ((ima_p[i] / skel_p[i]) - mean.to_result()) * ((ima_p[i] / skel_p[i]) - mean.to_result()); + + // variance /= nlabels; + + trace::exiting("scribo::estim::internal::boldness_from_lbl"); + return mean.to_result(); + } + + } // end of namespace scribo::estim::internal + + + // IMPLEMENTATIONS + + namespace impl + { + + namespace generic + { + + template <typename I> + float + font_boldness(const Image<I>& ima_) + { + trace::entering("scribo::estim::impl::generic::font_boldness"); + + const I& ima = exact(ima_); + mln_precondition(ima.is_valid()); + mlc_is(mln_value(I), bool)::check(); + + typedef scribo::def::lbl_type V; + typedef mln_ch_value(I,V) L; + + mln_concrete(I) skel = internal::compute_skeleton(ima); + + V nslabels; + L slbl = labeling::blobs(skel, c8(), nslabels); + + V nlabels; + L lbl = labeling::blobs(ima, c8(), nlabels); + + float + output = internal::boldness_from_lbl(lbl, nlabels, slbl); + + trace::exiting("scribo::estim::impl::generic::font_boldness"); + return output; + } + + } // end of namespace scribo::estim::generic::impl + + } // end of namespace scribo::estim::impl + + + + // FACADE + + template <typename I> + float + font_boldness(const Image<I>& ima) + { + trace::entering("scribo::estim::font_boldness"); + + mln_precondition(exact(ima).is_valid()); + mlc_is(mln_value(I), bool)::check(); + + float output = impl::generic::font_boldness(ima); + + trace::exiting("scribo::estim::font_boldness"); + return output; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::estim + +} // end of namespace scribo + +# endif // ! SCRIBO_ESTIM_FONT_BOLDNESS_HH + + + diff --git a/scribo/scribo/estim/font_color.hh b/scribo/scribo/estim/font_color.hh new file mode 100644 index 0000000..9a3c429 --- /dev/null +++ b/scribo/scribo/estim/font_color.hh @@ -0,0 +1,206 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_ESTIM_FONT_COLOR_HH +# define SCRIBO_ESTIM_FONT_COLOR_HH + +/// \file +/// +/// \brief Estimate the font color. + +# include <mln/core/image/image2d.hh> +# include <mln/core/alias/neighb2d.hh> +# include <mln/value/int_u8.hh> +# include <mln/labeling/compute.hh> +# include <mln/accu/stat/mean.hh> +# include <mln/accu/stat/median_h.hh> +# include <mln/value/int_u12.hh> +# include <mln/value/rgb8.hh> + +# include <scribo/estim/internal/compute_skeleton.hh> + + +namespace scribo +{ + + namespace estim + { + + using namespace mln; + + /// \brief Estimate the font color. + // + template <typename I, typename J> + mln_value(I) + font_color(const Image<I>& text_ima, const Image<J>& bin_text_ima); + + +# ifndef MLN_INCLUDE_ONLY + + namespace impl + { + + template <typename I, typename J> + mln_value(I) + font_color_rgb(const Image<I>& text_ima_, + const Image<J>& bin_text_ima_) + { + trace::entering("scribo::estim::impl::font_color_rgb"); + + typedef mln_value(I) V1; + typedef mln_value(J) V2; + //mlc_is(V1, value::rgb)::check(); + mlc_is(V2, bool)::check(); + + const I& text_ima = exact(text_ima_); + const J& bin_text_ima = exact(bin_text_ima_); + + mln_concrete(J) skel = internal::compute_skeleton(bin_text_ima); + + value::int_u8 nlabels = 0; + mln_ch_value(I,value::int_u8) + lbl = labeling::blobs(skel, c8(), nlabels); + + util::array<algebra::vec<3u, float> > res = + labeling::compute(accu::meta::stat::mean(), text_ima, lbl, nlabels); + + accu::stat::median_h<value::int_u12> m_red; + accu::stat::median_h<value::int_u12> m_green; + accu::stat::median_h<value::int_u12> m_blue; + m_red.init(); + m_green.init(); + m_blue.init(); + + mln_value(I) med_rgb; + + for (unsigned int i = 1; i <= nlabels; ++i) + { + m_red.take(res[i][0]); + m_green.take(res[i][1]); + m_blue.take(res[i][2]); + } + + med_rgb.red() = m_red.to_result(); + med_rgb.green() = m_green.to_result(); + med_rgb.blue() = m_blue.to_result(); + + trace::exiting("scribo::estim::impl::font_color_rgb"); + return med_rgb; + } + + + template <typename I, typename J> + mln_value(I) + font_color_grayscale(const Image<I>& text_ima_, + const Image<J>& bin_text_ima_) + { + trace::entering("scribo::estim::impl::font_color_grayscale"); + + typedef mln_value(I) V1; + typedef mln_value(J) V2; + //mlc_is(V1, value::rgb)::check(); + mlc_is(V2, bool)::check(); + + const I& text_ima = exact(text_ima_); + const J& bin_text_ima = exact(bin_text_ima_); + + mln_concrete(J) skel = internal::compute_skeleton(bin_text_ima); + + value::int_u8 nlabels = 0; + mln_ch_value(J,value::int_u8) lbl = labeling::blobs(skel, c8(), nlabels); + + util::array<algebra::vec<3u, float> > res = + labeling::compute(accu::meta::stat::mean(), text_ima, lbl, nlabels); + + accu::stat::median_h<value::int_u12> m_val; + m_val.init(); + + mln_value(I) med_val; + for (unsigned int i = 1; i <= nlabels; ++i) + m_val.take(res[i][0]); + + med_val = m_val.to_result(); + + trace::exiting("scribo::estim::impl::font_color_grayscale"); + return med_val; + } + + } // end of namespace scribo::estim::impl + + + // DISPATCH + + namespace internal + { + + template <typename I, typename J> + mln_value(I) + font_color_dispatch(const value::rgb8&, + const Image<I>& text_ima, const Image<J>& bin_text_ima) + { + return impl::font_color_rgb(exact(text_ima), exact(bin_text_ima)); + } + + + template <typename V, typename I, typename J> + mln_value(I) + font_color_dispatch(const V&, + const Image<I>& text_ima, const Image<J>& bin_text_ima) + { + return impl::font_color_grayscale(exact(text_ima), exact(bin_text_ima)); + } + + + template <typename I, typename J> + mln_value(I) + font_color_dispatch(const Image<I>& text_ima, const Image<J>& bin_text_ima) + { + return font_color_dispatch(mln_value(I)(), text_ima, bin_text_ima); + } + + } // end of namespace scribo::estim::internal + + + // FACADE + + template <typename I, typename J> + mln_value(I) + font_color(const Image<I>& text_ima, const Image<J>& bin_text_ima) + { + trace::entering("scribo::estim::font_color"); + + mln_value(I) output = internal::font_color_dispatch(text_ima, bin_text_ima); + + trace::exiting("scribo::estim::font_color"); + return output; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::estim + +} // end of namespace scribo + +# endif // ! SCRIBO_ESTIM_FONT_COLOR_HH diff --git a/scribo/scribo/estim/internal/compute_skeleton.hh b/scribo/scribo/estim/internal/compute_skeleton.hh new file mode 100644 index 0000000..52ecf01 --- /dev/null +++ b/scribo/scribo/estim/internal/compute_skeleton.hh @@ -0,0 +1,112 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_ESTIM_INTERNAL_COMPUTE_SKELETON_HH +# define SCRIBO_ESTIM_INTERNAL_COMPUTE_SKELETON_HH + +/// \file +/// +/// \brief Compute a skeleton useful for font estimations. + + +# include <mln/core/image/image2d.hh> +# include <mln/core/alias/neighb2d.hh> +# include <mln/topo/skeleton/crest.hh> +# include <mln/topo/skeleton/is_simple_point.hh> +# include <mln/transform/distance_front.hh> +# include <mln/logical/not.hh> +# include <mln/make/w_window2d_int.hh> +# include <mln/value/int_u8.hh> +# include <mln/arith/revert.hh> +# include <mln/morpho/skeleton_constrained.hh> +# include <mln/core/routine/extend.hh> +# include <mln/labeling/blobs.hh> +# include <mln/accu/stat/mean.hh> +# include <mln/value/rgb8.hh> + + +namespace scribo +{ + + namespace estim + { + + namespace internal + { + using namespace mln; + + + /// \brief Compute a skeleton useful for font estimations. + // + template <typename I> + mln_concrete(I) + compute_skeleton(const Image<I>& input); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I> + mln_concrete(I) + compute_skeleton(const Image<I>& input_) + { + trace::entering("scribo::estim::internal::compute_skeleton"); + + const I& input = exact(input_); + mlc_is(mln_value(I), bool)::check(); + mln_precondition(input.is_valid()); + + int psi = 7; + int vals[] = { 0, 9, 0, 9, 0, + 9, 6, 4, 6, 9, + 0, 4, 0, 4, 0, + 9, 6, 4, 6, 9, + 0, 9, 0, 9, 0 }; + + mln_ch_value(I,value::int_u8) + dist = transform::distance_front(logical::not_(input), c8(), + mln::make::w_window2d_int(vals), + mln_max(value::int_u8)); + + mln_ch_value(I,value::int_u8) dist_map = arith::revert(dist); + mln_concrete(I) K = topo::skeleton::crest(input, dist, c8(), psi); + + mln_concrete(I) skel = + morpho::skeleton_constrained(input, c8(), + topo::skeleton::is_simple_point<I,neighb2d>, + extend(K, false), dist_map); + + trace::exiting("scribo::estim::internal::compute_skeleton"); + return skel; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::estim::internal + + } // end of namespace scribo::estim + +} // end of namespace scribo + +#endif // ! SCRIBO_ESTIM_INTERNAL_COMPUTE_SKELETON_HH diff --git a/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh b/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh index 44d8342..b906a4a 100644 --- a/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh +++ b/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh @@ -234,7 +234,10 @@ namespace scribo << "\" kerning=\"" << lines(fid).char_space(); // EXTENSIONS - Not officially supported - output << "\" baseline=\"" << lines(fid).baseline() + // FIXME: add boldness? + output << "\" color=\"" << parset(p).color() + << "\" color_reliability=\"" << parset(p).color_reliability() + << "\" baseline=\"" << lines(fid).baseline() << "\" meanline=\"" << lines(fid).meanline() << "\" x_height=\"" << lines(fid).x_height() << "\" d_height=\"" << lines(fid).d_height() @@ -271,6 +274,10 @@ namespace scribo output << " <line "; output << "id=\"" << line.id() + << "\" boldness=\"" << line.boldness() + << "\" boldness_reliability=\"" << line.boldness_reliability() + << "\" color=\"" << line.color() + << "\" color_reliability=\"" << line.color_reliability() << "\" txt_orientation=\"" << line.orientation() << "\" txt_reading_orientation=\"" << line.reading_orientation() << "\" txt_reading_direction=\"" << line.reading_direction() diff --git a/scribo/scribo/io/xml/internal/full_xml_visitor.hh b/scribo/scribo/io/xml/internal/full_xml_visitor.hh index 28f43e9..bba7691 100644 --- a/scribo/scribo/io/xml/internal/full_xml_visitor.hh +++ b/scribo/scribo/io/xml/internal/full_xml_visitor.hh @@ -251,20 +251,21 @@ namespace scribo output << " <component_set nelements=\"" << comp_set.nelements() << "\">" << std::endl; for_all_comps(c, comp_set) - { - output << " <component_info" - << " id=\"" << comp_set(c).id() - << "\" mass_center_x=\"" << comp_set(c).mass_center().col() - << "\" mass_center_y=\"" << comp_set(c).mass_center().row() - << "\" card=\"" << comp_set(c).card() - << "\" tag=\"" << comp_set(c).tag() - << "\" type=\"" << comp_set(c).type() - << "\" pmin_x=\"" << comp_set(c).bbox().pmin().col() - << "\" pmin_y=\"" << comp_set(c).bbox().pmin().row() - << "\" pmax_x=\"" << comp_set(c).bbox().pmax().col() - << "\" pmax_y=\"" << comp_set(c).bbox().pmax().row() - << "\"/>" << std::endl; - } + if (comp_set(c).is_valid()) + { + output << " <component_info" + << " id=\"" << comp_set(c).id() + << "\" mass_center_x=\"" << comp_set(c).mass_center().col() + << "\" mass_center_y=\"" << comp_set(c).mass_center().row() + << "\" card=\"" << comp_set(c).card() + << "\" tag=\"" << comp_set(c).tag() + << "\" type=\"" << comp_set(c).type() + << "\" pmin_x=\"" << comp_set(c).bbox().pmin().col() + << "\" pmin_y=\"" << comp_set(c).bbox().pmin().row() + << "\" pmax_x=\"" << comp_set(c).bbox().pmax().col() + << "\" pmax_y=\"" << comp_set(c).bbox().pmax().row() + << "\"/>" << std::endl; + } // Save labeled image @@ -426,6 +427,10 @@ namespace scribo output << " <line " << std::endl; output << "id=\"" << line.id() + << "\" boldness=\"" << line.boldness() + << "\" boldness_reliability=\"" << line.boldness_reliability() + << "\" color=\"" << line.color() + << "\" color_reliability=\"" << line.color_reliability() << "\" txt_orientation=\"" << line.orientation() << "\" txt_reading_orientation=\"" << line.reading_orientation() << "\" txt_reading_direction=\"" << line.reading_direction() diff --git a/scribo/scribo/primitive/extract/components.hh b/scribo/scribo/primitive/extract/components.hh index 849dd7b..fe2b523 100644 --- a/scribo/scribo/primitive/extract/components.hh +++ b/scribo/scribo/primitive/extract/components.hh @@ -48,6 +48,7 @@ # include <mln/extension/fill.hh> # include <scribo/core/component_set.hh> +# include <scribo/estim/components_features.hh> @@ -73,51 +74,64 @@ namespace scribo /// /// \return An image of labeled components. // + template <typename I, typename J, typename N, typename V> + inline + component_set<mln_ch_value(I,V)> + components(const Image<I>& input, const Image<J>& binary_input, + const Neighborhood<N>& nbh, V& ncomponents, + component::Type type = component::Undefined); + + template <typename I, typename N, typename V> inline component_set<mln_ch_value(I,V)> - components(const Image<I>& input, + components(const Image<I>& binary_input, const Neighborhood<N>& nbh, V& ncomponents, component::Type type = component::Undefined); # ifndef MLN_INCLUDE_ONLY - - namespace internal + template <typename I, typename J, typename N, typename V> + inline + component_set<mln_ch_value(I,V)> + components(const Image<I>& input, const Image<J>& binary_input, + const Neighborhood<N>& nbh, V& ncomponents, + component::Type type = component::Undefined) { + trace::entering("scribo::components"); - template <typename I, typename N, typename V> - inline - void - components_tests(const Image<I>& input, - const Neighborhood<N>& nbh, V& ncomponents, - component::Type type) - { - mlc_equal(mln_value(I),bool)::check(); + mlc_equal(mln_value(J),bool)::check(); // mlc_is_a(V, mln::value::Symbolic)::check(); - mln_precondition(exact(input).is_valid()); - mln_precondition(exact(nbh).is_valid()); - (void) input; - (void) nbh; - (void) ncomponents; - (void) type; - } + mln_precondition(exact(input).is_valid()); + mln_precondition(exact(binary_input).is_valid()); + mln_precondition(exact(nbh).is_valid()); + typedef mln_ch_value(I,V) L; + component_set<L> + output = extract::components(binary_input, nbh, ncomponents, type); - } // end of namespace scribo::primitive::extract::internal + output = estim::components_features(input, binary_input, output); + + trace::exiting("scribo::components"); + return output; + } template <typename I, typename N, typename V> inline component_set<mln_ch_value(I,V)> - components(const Image<I>& input, + components(const Image<I>& binary_input, const Neighborhood<N>& nbh, V& ncomponents, component::Type type = component::Undefined) { trace::entering("scribo::components"); - internal::components_tests(input, nbh, ncomponents, type); + mlc_equal(mln_value(I),bool)::check(); +// mlc_is_a(V, mln::value::Symbolic)::check(); + mln_precondition(exact(binary_input).is_valid()); + mln_precondition(exact(nbh).is_valid()); + typedef mln_ch_value(I,V) L; typedef mln::accu::shape::bbox<mln_site(L)> bbox_accu_t; @@ -125,14 +139,15 @@ namespace scribo typedef mln::accu::pair<bbox_accu_t, center_accu_t> pair_accu_t; // Setting extension value. - extension::fill(input, 0); + extension::fill(binary_input, false); mln::util::couple<L, - mln::util::couple<mln::util::array<mln_result(pair_accu_t)>, - mln::util::array<pair_accu_t> > > - - results = labeling::value_and_compute(input, true, nbh, ncomponents, - pair_accu_t()); + mln::util::couple< + mln::util::array<mln_result(pair_accu_t)>, + mln::util::array<pair_accu_t> > > + results = labeling::value_and_compute(binary_input, true, nbh, + ncomponents, + pair_accu_t()); component_set<L> output(results.first(), ncomponents, results.second().second(), type); @@ -141,6 +156,7 @@ namespace scribo return output; } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace scribo::primitive::extract diff --git a/scribo/scribo/text/extract_lines.hh b/scribo/scribo/text/extract_lines.hh index 53fd742..3e9254a 100644 --- a/scribo/scribo/text/extract_lines.hh +++ b/scribo/scribo/text/extract_lines.hh @@ -81,6 +81,12 @@ namespace scribo extract_lines(const Image<I>& input, const Neighborhood<N>& nbh); + /// \overload + template <typename L> + line_set<mln_ch_value(L,scribo::def::lbl_type)> + extract_lines(const component_set<L>& input); + + # ifndef MLN_INCLUDE_ONLY @@ -119,6 +125,22 @@ namespace scribo if (exact(separators).is_valid()) comps.add_separators(separators); + line_set<mln_ch_value(I,scribo::def::lbl_type)> + lines = extract_lines(comps); + + trace::exiting("scribo::text::extract_lines"); + return lines; + } + + + template <typename L> + line_set<mln_ch_value(L,scribo::def::lbl_type)> + extract_lines(const component_set<L>& comps) + { + trace::entering("scribo::text::extract_lines"); + + mln_precondition(comps.is_valid()); + /// Linking potential comps object_links<L> left_link = primitive::link::with_single_left_link_dmax_ratio( diff --git a/scribo/scribo/text/extract_lines_with_features.hh b/scribo/scribo/text/extract_lines_with_features.hh new file mode 100644 index 0000000..fd413eb --- /dev/null +++ b/scribo/scribo/text/extract_lines_with_features.hh @@ -0,0 +1,131 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#ifndef SCRIBO_TEXT_EXTRACT_LINES_WITH_FEATURES_HH +# define SCRIBO_TEXT_EXTRACT_LINES_WITH_FEATURES_HH + +/// \file +/// +/// Extract line of text bounding boxes. + + +# include <mln/core/concept/image.hh> + +# include <scribo/text/extract_lines.hh> + + +namespace scribo +{ + + namespace text + { + + using namespace mln; + + /// Extract lines of text in a binary image. + /*! + ** \param[in] input Original color image. + ** \param[in] input_binary A binary image. + ** \param[in] nbh A neighborhood used for labeling. + ** \param[in] separators A binary image with separator information. + ** + ** \return A set of lines. + */ + template <typename I, typename J, typename N> + line_set<mln_ch_value(I,scribo::def::lbl_type)> + extract_lines_with_features(const Image<I>& input, + const Image<J>& input_binary, + const Neighborhood<N>& nbh, + const mln_ch_value(I,bool)& separators); + + + /// \overload + template <typename I, typename J, typename N> + line_set<mln_ch_value(I,scribo::def::lbl_type)> + extract_lines_with_features(const Image<I>& input, + const Image<J>& input_binary, + const Neighborhood<N>& nbh); + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename I, typename J, typename N> + line_set<mln_ch_value(I,scribo::def::lbl_type)> + extract_lines_with_features(const Image<I>& input, + const Image<J>& input_binary, + const Neighborhood<N>& nbh) + { + mln_ch_value(I,bool) seps; + return extract_lines_with_features(input, input_binary, nbh, seps); + } + + + template <typename I, typename J, typename N> + line_set<mln_ch_value(I,scribo::def::lbl_type)> + extract_lines_with_features(const Image<I>& input_, + const Image<J>& input_binary_, + const Neighborhood<N>& nbh_, + const mln_ch_value(I,bool)& separators) + { + trace::entering("scribo::text::extract_lines_with_features"); + + const I& input = exact(input_); + const J& input_binary = exact(input_binary_); + const N& nbh = exact(nbh_); + + mln_precondition(input.is_valid()); + mln_precondition(input_binary.is_valid()); + mln_precondition(nbh.is_valid()); + + /// Finding comps. + typedef mln_ch_value(I,scribo::def::lbl_type) L; + scribo::def::lbl_type ncomps; + component_set<L> + comps = scribo::primitive::extract::components(input, input_binary, + nbh, ncomps); + + /// First filtering. + comps = scribo::filter::components_small(comps, 3); + + /// Use separators. + if (exact(separators).is_valid()) + comps.add_separators(separators); + + line_set<mln_ch_value(I,scribo::def::lbl_type)> + lines = extract_lines(comps); + + trace::exiting("scribo::text::extract_lines_with_features"); + return lines; + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::text + +} // end of namespace scribo + +#endif // ! SCRIBO_TEXT_EXTRACT_LINES_WITH_FEATURES_HH diff --git a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh index 624a54e..0a920a6 100644 --- a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh +++ b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh @@ -254,7 +254,8 @@ namespace scribo V ncomponents; component_set<L> - components = scribo::primitive::extract::components(input_cleaned, + components = scribo::primitive::extract::components(original_image, + input_cleaned, c8(), ncomponents); diff --git a/scribo/src/debug/Makefile.am b/scribo/src/debug/Makefile.am index 60d7afa..be8bb78 100644 --- a/scribo/src/debug/Makefile.am +++ b/scribo/src/debug/Makefile.am @@ -22,6 +22,7 @@ noinst_PROGRAMS = \ show_groups_bboxes \ show_info_x_height \ show_info_median_inter_characters \ + show_lines_boldness \ show_separators \ show_links_left_right_links_validation \ show_links_bbox_h_ratio \ @@ -54,6 +55,7 @@ show_components_bboxes_SOURCES = show_components_bboxes.cc show_groups_bboxes_SOURCES = show_groups_bboxes.cc show_info_x_height_SOURCES = show_info_x_height.cc show_info_median_inter_characters_SOURCES = show_info_median_inter_characters.cc +show_lines_boldness_SOURCES = show_lines_boldness.cc show_separators_SOURCES = show_separators.cc show_links_left_right_links_validation_SOURCES = show_links_left_right_links_validation.cc show_links_bbox_h_ratio_SOURCES = show_links_bbox_h_ratio.cc @@ -83,6 +85,20 @@ show_objects_thin_SOURCES = show_objects_thin.cc if HAVE_MAGICKXX + noinst_PROGRAMS += show_components_color + show_components_color_SOURCES = show_components_color.cc + show_components_color_CPPFLAGS = $(AM_CPPFLAGS) \ + $(MAGICKXX_CPPFLAGS) + show_components_color_LDFLAGS = $(AM_LDFLAGS) \ + $(MAGICKXX_LDFLAGS) + + noinst_PROGRAMS += show_components_boldness + show_components_boldness_SOURCES = show_components_boldness.cc + show_components_boldness_CPPFLAGS = $(AM_CPPFLAGS) \ + $(MAGICKXX_CPPFLAGS) + show_components_boldness_LDFLAGS = $(AM_LDFLAGS) \ + $(MAGICKXX_LDFLAGS) + if HAVE_QT noinst_PROGRAMS += show_paragraph_blocks diff --git a/scribo/src/debug/show_components_boldness.cc b/scribo/src/debug/show_components_boldness.cc new file mode 100644 index 0000000..f9aca3f --- /dev/null +++ b/scribo/src/debug/show_components_boldness.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/core/image/dmorph/image_if.hh> +#include <mln/pw/all.hh> +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> +#include <mln/io/magick/load.hh> +#include <mln/value/int_u.hh> +#include <mln/literal/colors.hh> +#include <mln/draw/box.hh> + +#include <scribo/core/component_set.hh> +#include <scribo/primitive/extract/components.hh> + +int main(int argc, char *argv[]) +{ + using namespace mln; + using namespace scribo; + + if (argc != 4) + { + std::cerr << "Usage : " << argv[0] << " input.* input.pbm out.pgm" << std::endl; + return 1; + } + + Magick::InitializeMagick(0); + + typedef mln::value::int_u<30> V; + typedef image2d<V> L; + + image2d<value::rgb8> input; + io::magick::load(input, argv[1]); + + image2d<bool> input_bin; + io::pbm::load(input_bin, argv[2]); + + V ncomponents; + component_set<L> + components = scribo::primitive::extract::components(input, input_bin, c8(), + ncomponents); + + image2d<value::int_u8> output; + initialize(output, input); + data::fill(output, 0); + + const L& lbl = components.labeled_image(); + for_all_comps(c, components) + if (components(c).is_valid()) + { + data::fill(((output | components(c).bbox()).rw() + | (pw::value(lbl) == pw::cst(c))).rw(), + components(c).features().boldness); + } + + io::pgm::save(output, argv[3]); +} diff --git a/scribo/src/debug/show_components_color.cc b/scribo/src/debug/show_components_color.cc new file mode 100644 index 0000000..a13b85b --- /dev/null +++ b/scribo/src/debug/show_components_color.cc @@ -0,0 +1,73 @@ +// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/core/image/dmorph/image_if.hh> +#include <mln/pw/all.hh> +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> +#include <mln/io/magick/load.hh> +#include <mln/value/int_u.hh> +#include <mln/literal/colors.hh> +#include <mln/draw/box.hh> + +#include <scribo/core/component_set.hh> +#include <scribo/primitive/extract/components.hh> + +int main(int argc, char *argv[]) +{ + using namespace mln; + using namespace scribo; + + if (argc != 4) + { + std::cerr << "Usage : " << argv[0] << " input.* input.pbm out.ppm" << std::endl; + return 1; + } + + Magick::InitializeMagick(0); + + typedef mln::value::int_u<30> V; + typedef image2d<V> L; + + image2d<value::rgb8> input; + io::magick::load(input, argv[1]); + + image2d<bool> input_bin; + io::pbm::load(input_bin, argv[2]); + + V ncomponents; + component_set<L> + components = scribo::primitive::extract::components(input, input_bin, c8(), + ncomponents); + + image2d<value::rgb8> output; + initialize(output, input); + data::fill(output, literal::white); + + const L& lbl = components.labeled_image(); + for_all_comps(c, components) + if (components(c).is_valid()) + { + data::fill(((output | components(c).bbox()).rw() + | (pw::value(lbl) == pw::cst(c))).rw(), + components(c).features().color); + } + + io::ppm::save(output, argv[3]); +} diff --git a/scribo/src/debug/show_lines_boldness.cc b/scribo/src/debug/show_lines_boldness.cc new file mode 100644 index 0000000..a3815c0 --- /dev/null +++ b/scribo/src/debug/show_lines_boldness.cc @@ -0,0 +1,199 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/io/pbm/load.hh> +#include <mln/value/int_u16.hh> +#include <mln/draw/box_plain.hh> +#include <mln/pw/all.hh> +#include <mln/core/image/dmorph/image_if.hh> +#include <mln/data/convert.hh> +#include <mln/literal/colors.hh> + +#include <scribo/text/recognition.hh> + +#include <scribo/debug/usage.hh> + +#include <scribo/core/document.hh> +#include <scribo/core/component_set.hh> +#include <scribo/core/object_links.hh> +#include <scribo/core/object_groups.hh> + +#include <scribo/text/extract_lines_with_features.hh> +#include <scribo/estim/components_features.hh> + +#include <scribo/io/xml/save.hh> + + +const char *args_desc[][2] = +{ + {0, 0} +}; + + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 3) + return scribo::debug::usage(argv, + "Show text lines", + "input.pbm out_prefix", + args_desc); + + trace::entering("main"); + + image2d<bool> input; + mln::io::pbm::load(input, argv[1]); + + std::string prefix = argv[2]; + + typedef image2d<scribo::def::lbl_type> L; + + // Extract lines + line_set<L> + lines = text::extract_lines_with_features( + data::convert(value::rgb8(), input), input, c8()); + const component_set<L>& comp_set = lines.components(); + + mln::math::round<unsigned> round; + + // Min boldness / line + { + image2d<value::int_u8> min_boldness; + initialize(min_boldness, input); + + data::fill(min_boldness, 0); + for_all_lines(l, lines) + if (lines(l).is_textline()) + { + float min = 65000; + + // Compute min + for_all_line_comps(cid, lines(l).component_ids()) + { + unsigned id = lines(l).component_ids()(cid); + if (comp_set(id).features().boldness < min) + min = comp_set(id).features().boldness; + } + + // Draw + for_all_line_comps(cid, lines(l).component_ids()) + { + unsigned id = lines(l).component_ids()(cid); + data::fill(((min_boldness | comp_set(id).bbox()).rw() + | (pw::value(comp_set.labeled_image()) == pw::cst(id))).rw(), round(min)); + } + + } + + mln::io::pgm::save(min_boldness, prefix + "_min_boldness.pgm"); + } + + // Max boldness / line + { + image2d<value::int_u8> max_boldness; + initialize(max_boldness, input); + + data::fill(max_boldness, 0); + for_all_lines(l, lines) + if (lines(l).is_textline()) + { + float max = 65000; + + // Compute max + for_all_line_comps(cid, lines(l).component_ids()) + { + unsigned id = lines(l).component_ids()(cid); + if (comp_set(id).features().boldness < max) + max = comp_set(id).features().boldness; + } + + // Draw + for_all_line_comps(cid, lines(l).component_ids()) + { + unsigned id = lines(l).component_ids()(cid); + data::fill(((max_boldness | comp_set(id).bbox()).rw() + | (pw::value(comp_set.labeled_image()) == pw::cst(id))).rw(), round(max)); + } + + } + + mln::io::pgm::save(max_boldness, prefix + "_max_boldness.pgm"); + } + + + // Mean boldness / line + { + image2d<value::int_u8> min_boldness; + initialize(min_boldness, input); + + data::fill(min_boldness, 0); + for_all_lines(l, lines) + if (lines(l).is_textline()) + { + // Draw + for_all_line_comps(cid, lines(l).component_ids()) + { + unsigned id = lines(l).component_ids()(cid); + data::fill(((min_boldness | comp_set(id).bbox()).rw() + | (pw::value(comp_set.labeled_image()) == pw::cst(id))).rw(), round(lines(l).boldness())); + } + + } + + mln::io::pgm::save(min_boldness, prefix + "_mean_boldness.pgm"); + } + + // Stddev boldness / line + { + image2d<value::int_u8> min_boldness; + initialize(min_boldness, input); + + data::fill(min_boldness, 0); + for_all_lines(l, lines) + if (lines(l).is_textline()) + { + // Draw + for_all_line_comps(cid, lines(l).component_ids()) + { + unsigned id = lines(l).component_ids()(cid); + data::fill(((min_boldness | comp_set(id).bbox()).rw() + | (pw::value(comp_set.labeled_image()) == pw::cst(id))).rw(), round(lines(l).boldness_reliability())); + } + + } + + mln::io::pgm::save(min_boldness, prefix + "_stddev_boldness.pgm"); + } + + + trace::exiting("main"); +} + diff --git a/scribo/tests/Makefile.am b/scribo/tests/Makefile.am index 09768b1..1f227b7 100644 --- a/scribo/tests/Makefile.am +++ b/scribo/tests/Makefile.am @@ -1,5 +1,5 @@ -# Copyright (C) 2009, 2010 EPITA Research and Development Laboratory -# (LRDE). +# Copyright (C) 2009, 2010, 2011 EPITA Research and Development +# Laboratory (LRDE). # # This file is part of Olena. # @@ -31,6 +31,7 @@ SUBDIRS = \ binarization \ convert \ core \ + estim \ filter \ preprocessing \ primitive \ diff --git a/scribo/tests/estim/Makefile.am b/scribo/tests/estim/Makefile.am new file mode 100644 index 0000000..1c39ab6 --- /dev/null +++ b/scribo/tests/estim/Makefile.am @@ -0,0 +1,29 @@ +# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE). +# +# This file is part of Olena. +# +# Olena is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2 of the License. +# +# Olena is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Olena. If not, see <http://www.gnu.org/licenses/>. +# + +## Process this file through Automake to create Makefile.in. + +include $(top_srcdir)/scribo/tests/tests.mk + +check_PROGRAMS = \ + font_color \ + font_boldness + +font_color_SOURCES = font_color.cc +font_boldness_SOURCES = font_boldness.cc + +TESTS = $(check_PROGRAMS) diff --git a/scribo/tests/estim/font_boldness.cc b/scribo/tests/estim/font_boldness.cc new file mode 100644 index 0000000..9e85795 --- /dev/null +++ b/scribo/tests/estim/font_boldness.cc @@ -0,0 +1,46 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE). +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. + +/// \file + +#include <cstdio> +#include <cstdlib> + +#include <mln/core/image/image2d.hh> +#include <mln/data/compare.hh> + +#include <mln/io/ppm/load.hh> +#include <mln/io/pbm/load.hh> + +#include <mln/value/rgb8.hh> + +#include <scribo/estim/font_boldness.hh> + +#include "tests/data.hh" + +using namespace mln; + +int main() +{ + image2d<bool> input; + io::pbm::load(input, SCRIBO_IMG_DIR "/phillip.pbm"); + + float val = scribo::estim::font_boldness(input); + + mln_assertion(((int)(val * 100) / 100.f) == 18.44f); + + return 0; +} diff --git a/scribo/tests/estim/font_color.cc b/scribo/tests/estim/font_color.cc new file mode 100644 index 0000000..45c453d --- /dev/null +++ b/scribo/tests/estim/font_color.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE). +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. + +/// \file + +#include <cstdio> +#include <cstdlib> + +#include <mln/core/image/image2d.hh> +#include <mln/data/compare.hh> + +#include <mln/io/ppm/load.hh> +#include <mln/io/pbm/load.hh> + +#include <mln/value/rgb8.hh> + +#include <scribo/estim/font_color.hh> + +#include "tests/data.hh" + +using namespace mln; + +int main() +{ + image2d<value::rgb8> input_rgb; + io::ppm::load(input_rgb, SCRIBO_IMG_DIR "/phillip.ppm"); + image2d<bool> input_bin; + io::pbm::load(input_bin, SCRIBO_IMG_DIR "/phillip.pbm"); + + value::rgb8 val = scribo::estim::font_color(input_rgb, input_bin); + + mln_assertion(val == value::rgb8(77, 146, 140)); + + return 0; +} diff --git a/scribo/tests/img/phillip.pbm b/scribo/tests/img/phillip.pbm new file mode 100644 index 0000000000000000000000000000000000000000..ed60f945bbe7a0bf176fcb69695be9ed2ab9ac47 GIT binary patch literal 1633 zcmdth&x#W<90%}(912C4M@YbnUb-&G`sZK}b`fEPW$^)=wIjPw+fs|TAZGT>=27As z<d{Qj{Qi=ecE(mudND&v=ab+3GWlh4@pyb+y{hKbs$5r7b#<%W+{~(Zsg5U)l)7H8 zm(P!m79^9|YFbUI<;}XBd|2VBvy0bnU#iRMQ&q0sU#oIHRj1YGYPMK@tmbQVUS2Jb zbg{Zs56&-7&mNACpPZ<ZXXE&vwI6%y@g_zay$L$V-Jpdw#u}?#k=3&zHuzg>xOSsX z`9WnnHM>}5+6>6usbfsnDQ|s18$;^bcW_0WVr?Yt-q*=S-=){7;a#)RN}g`+`l^4U zI>+*1tQJlq2al9LYy^I-wpuiW<xn1&ww|7Zz7RF3h}<*XEE%+cGB#>Bo=p0V8LDgZ zZJ;b`om6aac~q)Z_LY4Zks(KIno&&|p0dC^DLUno4YXz~@BpDss<ZNt<QEmB`NEo! zIb|rq$fF1Jo@$?zMo5u6M#iEqNQN4BTA*q<78OFQ3>05b-BO06PSOZAxYZ4*B&D7; zMyw~goeESLJ3UaDE3{QjSzOk;R<+Yk;^WPVnF8`+>-q}8Dtn5$Q9bvRYPVJ6@L@R# z6TZ`Qe5`QTlfda1Q9QQAU`Em+Fea%oeML2JAhsHD1QDCmw2Gr;jT1g87SU_@o%}sa fwAZ>rG#qepc%Se7g6czg?Y~lUXtwW%@K5#=Ut6W* literal 0 HcmV?d00001 diff --git a/scribo/tests/img/phillip.ppm b/scribo/tests/img/phillip.ppm new file mode 100644 index 0000000..d668fcf --- /dev/null +++ b/scribo/tests/img/phillip.ppm @@ -0,0 +1,5 @@ +P6 +# CREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) +176 69 +255 +ýõóýôóýõñüóñýõòýõôýõóþõóÿøöÿùöÿù÷ÿùöÿ÷ôÿöôÿøôÿ÷ôÿøôÿùõÿùôÿùôÿùöÿù÷ÿøöÿ÷öÿøöÿú÷ÿúøÿúøÿùøÿúøÿúøÿùøÿù÷ÿüùÿüùÿû÷þøõýöôþ÷öÿùøÿù÷ÿúøÿûøÿûøÿûøÿýúÿýûÿþüÿþüÿþýÿþüÿýûÿþüÿþýÿÿþÿÿþÿÿýÿÿýÿþýÿþûÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþþþýýüûÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþöóþõóýõñüôñýõòýõôýöôýöóÿøöÿùöÿùöÿøöÿøõÿøôþøôþ÷ôÿùôþøõþøóþ÷óÿùöÿù÷þøöþ÷õÿ÷õÿùõÿùöÿùöÿù÷ÿúøÿúøÿùøÿùøÿüøÿûøÿüøþúöýøöþø÷ÿúùÿúøÿúøÿúøþù÷ýöôÿúøÿûúÿþýÿþüÿýûÿýúÿýûÿþüÿþüÿýûÿÿþÿÿýÿÿýÿþýÿþüÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿþýÿþýÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýöóþôóþöóþöóþøõþ÷õýöóýõôÿ÷öÿúöÿù÷ÿøöÿøöÿ÷ôþøõþ÷õÿùöþ÷õþ÷óýöóÿøõÿú÷þùöþøôþ÷ôÿ÷õÿú÷ÿúøÿûùÿûùÿûùÿúùÿúùÿûøÿûøÿüùÿüùÿûøÿúøÿúùÿúùÿûøÿúøþù÷ý÷öÿúùÿüûÿþûÿþüÿýúÿýúÿýúÿýúÿüúÿûúÿþýÿþýÿÿýÿÿýÿÿýÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿþþÿþýÿþýÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿþýÿþýÿþýÿýýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿþþÿþþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþýöôþöôþ÷ôÿ÷óÿù÷ÿù÷þøõþ÷õÿ÷õÿùöÿù÷ÿùöÿøöÿ÷õþøõþ÷ôÿøõÿùöþùõý÷ôÿ÷öÿú÷þù÷þ÷õþ÷õÿùøÿüúÿüúÿüúÿûúÿûúÿúùÿúøÿù÷ÿûùÿüùÿú÷ÿúøÿúøÿûùÿüùÿüùÿûúÿüúÿûùÿüûÿþüÿýûÿýûÿýúÿûùÿûùÿûùÿûùÿúùÿüûÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿþÿÿýÿÿýÿÿþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýýÿýþÿþþÿþþÿþþþþýþþþÿþþÿþþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþþ÷õþöõþøôÿöóÿùöÿù÷ÿùöÿøõÿøõÿùöÿù÷ÿù÷ÿøöÿùõþøôþöóÿùôÿùöÿúöÿùöÿùøÿûøþúøþ÷õþøõÿù÷ÿúùÿûøÿúøÿùøÿùøþøöþøöÿù÷ÿûùÿüùÿú÷ÿúøÿûøÿýúÿýùÿýùÿþüÿþüÿýûÿýüÿþüÿýûÿþûÿýúÿûùÿûùÿûùÿûùÿüúÿüûÿþýÿþýÿÿýÿÿýÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýýÿûýÿþþþþþþýýþýýþûûÿýþÿþþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþõóÿ÷ôÿùôÿ÷ôÿùöÿùöÿùöÿùöÿøõÿùõÿù÷ÿøöÿøöÿùõþùôþ÷ôÿúöÿûøÿû÷ÿúöÿøöÿúøÿùøÿøöÿøöþøöþù÷ÿú÷þø÷þø÷ÿùøþùöþù÷ÿûøÿýùÿüùÿûøÿûùÿûùÿýûÿûùÿüúÿþüÿþüÿþüÿýûÿüúÿüùÿýûÿþúþûøý÷öÿøöÿüúÿýûÿýüÿþýÿÿýÿÿýÿþýÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþýÿÿýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿþþÿþþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿþþÿþþÿþþþþþýûüþûüþýýþüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýôòþõóÿøóÿ÷ôþùöþøõþøõþøöÿ÷õÿ÷ôÿ÷õÿøöÿøõÿùõÿùõÿùöÿú÷ÿúöÿùõÿøôÿ÷õþù÷þøöÿø÷ÿù÷þù÷þù÷ÿøöþøöþø÷ÿùøÿúøÿúùÿüùÿüùÿüùÿûùÿûúÿüúÿýúÿûùÿûùÿýûÿþüÿþûÿýûÿüúÿüúÿýûÿýúþûøý÷õþøöÿýûÿýûÿþýÿþýÿýûÿýûÿþýÿþýÿÿþÿÿþÿÿýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿþþÿþýÿÿüÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿÿþÿÿþÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþþÿþþÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþþÿþýÿýýþýýüúûûúùþýýýûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýöòüóòýõòÿöóþùöþøõþùõþøõÿöôþöóþöóÿ÷õÿ÷õÿøôÿùõÿùõÿùõÿùõþ÷óþ÷óþöôý÷ôý÷ôÿøöÿù÷ÿùöþøõþ÷ôýöôÿøöÿøøÿùøÿù÷ÿúøÿûùÿüùÿûùÿûùÿüùÿûúÿúùÿúøÿûùÿýûÿüúÿûúÿýüÿýûÿýúÿýúÿýúþüøþûøÿüùÿüùÿüøÿüöÿûõÿüúÿÿüÿÿþÿÿþÿÿþÿÿýÿþþÿþþÿþþÿþþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿýÿÿûÿþ÷ÿúôÿøòÿü÷ÿÿüÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿÿÿþþÿþþÿþþÿþýÿýýÿþüÿüøÿúöÿøöÿýûÿÿþÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿýÿÿýÿÿþÿÿýÿÿüÿÿûÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿÿýÿþüÿüùÿûõÿüôÿþøÿÿúÿÿþÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýþûüýüüûùúûùùÿüüÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿý÷óüõòüôòÿõôÿùõÿøõÿøõÿ÷ôþôòýôòþöóÿ÷õÿ÷õÿøõÿùõÿøõÿùõÿùöþùöýøôýõóûôòýöôÿù÷ÿùöþøõý÷óýöóüõóþøõþø÷ÿù÷ÿùöÿùöÿûùÿûùÿûùÿúùÿûùÿûùÿúùÿûùÿúúÿûúÿûúÿûúÿþýÿýüÿúùÿúùÿüùÿû÷ÿúóþöìýòãúìÙöäÒúïæÿûøÿýúÿþýÿÿþÿþýÿþýÿþþÿþþÿþþÿþþÿþþÿýþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿþûÿüôþøßûðË÷äË÷ÖÅûç×ÿòðÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþþÿúúÿø÷ÿòðÿééþáÚýàÎûÞÄúßÖÿùóÿÿþÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿýÿþüÿüûÿüøÿúòÿùåÿùßÿøÓÿøêÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿýûÿöîþëÕýÞÂýèœýîÓÿéÙÿûõÿþüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿþþþüýýùúýüûûøúûøùÿüüÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøõÿøôþ÷óþöóþùôþøõÿøôÿ÷óþôòýõòÿ÷õÿ÷öÿøöÿøõÿøôÿøõÿùöÿú÷ÿú÷ÿùöýöóúñïûñîþòïþõðþõðýõïýôïþóîþôðþòñþõòþõñþöòþ÷öÿøöÿøöÿø÷ÿúùÿùøÿùøÿüúÿûûÿüûÿûúÿûúÿüûÿûúÿúùþùöüôí÷ëÞðâÕäÑÆÕŹş²µ¹ŽÓÚÚüú÷ÿýúÿþýÿÿýÿþüÿþûÿþþÿþþÿÿÿÿÿþÿþþÿýþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿýüÿÿþÿýûüôðòáÛÛÕÃŒ¶©§¶±ŠŠÉÅ»íÜÙÿùñÿþúÿÿþÿÿþÿÿþÿÿþÿÿþÿýüÿööýääùÒÍòÀÀêÉœÞÁ³Ì±¿À¯ÁÔÒðôôÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿþýþúöýìéúãäôçÛìÜÑãÚºÓͺÇɯÑËØÿüûÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿþÿýûþôïöçÔÛÍ®Á¿§³¯·ŽÓŽŽóîèÿ÷òÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿýÿÿýÿÿÿÿþþÿýýÿûýÿþýÿþþÿþþÿþþÿþýÿþýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ôÿ÷óþ÷óýõóþøõþøôÿøôÿ÷õÿöõÿøõÿ÷õÿöõÿöôþ÷ôþ÷óÿøôÿøõÿù÷ÿøõþöóûíêöÛØôØÓ÷ÖÑ÷ßÖ÷ç×÷ê×øãÖ÷ØÏøÛÕ÷ÓÑ÷娸䨸ëÜúåâüíçþðîþõóÿøöþù÷þ÷öÿúøÿúúÿûúÿúúÿûúÿûúÿù÷þ÷ö÷ðíÞÔÌÀ³©§±Š€€|¢{¯šÀÕ×üú÷ÿþûÿþýÿþýÿþüÿþüÿÿþÿÿþÿÿÿÿÿÿÿþþÿþýÿþýÿþþÿÿþÿÿþÿÿÿÿÿþÿÿþÿþþÿþýÿþýüùôèàÓ¶°« ²šr€oªp§ªåãÃýøëÿþýÿþýÿþþÿþþÿÿýÿüúúìçäȹČ®«y|ÊÐêòöÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿþýûùóåßÖž»¹®¡³¢€x¡}µ¢§ÉÙúúúÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿþÿüúüçä뺷¹·Šr¢oi°¡v¥Š¹µæÉÇÿööÿþýÿþýÿþýÿþþÿûûÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿþþÿþýÿþýÿþþÿÿýÿþýþüüþüüÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþõóÿöóþ÷óýöóÿ÷ôÿøöÿøõÿøõÿøõÿ÷ôÿöôÿöôÿöóþöóþöóÿøôÿøõÿù÷ÿøõýôïñÝØ×µ°Åµ«Ç±ªÈ»²Ì¿±É¿Èµ¯Æ¬§Èž±Ê°ªÌIJϻ®Òįڷ³åοðÖÐ÷çÚûæãþóîýöôþ÷öÿúùÿúùÿúùÿúúþúúý÷÷úñðäÛÛ¡ŽŽsY`Uer²¬ÈÜÜýûøÿþûÿýüÿýýÿþýÿþýÿþþÿþþÿýýÿýýÿþþÿýýÿýýÿþþÿþþÿþýÿÿþÿÿþÿÿþÿÿÿÿÿþþüûôðìŸËÇqQTRYY}¬Å°íìâÿüüÿþþÿþþÿþþÿþýýüúïåâž²wmbeU¡n¢ÄÔïõùÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþþûôôàÑѬ€dZ¢i aŠag¶ªµÛâýûúÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþýúøïÞÚ·§¥m©¢UL UJ `h¥ª°·òãêýö÷ÿýýÿþýÿüûÿûûÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýþýüþýýÿþýÿýýþûüûùúÿûûÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýôòýôòþõóþõóþöóÿ÷õÿøôÿ÷ôÿøõÿ÷ôÿöôÿ÷õÿöôÿöóÿöóÿøõÿùöÿù÷þøöûóîâÙΡ€|}w|tz{|¡§Ž©¡ËœªâŸ¹öæÙûòðýôóý÷÷ÿ÷÷ÿ÷÷ÿøùþúúýø÷÷ìëÐÅÅx¡UFYTc¹ÙèâþûùÿþüÿýüÿüûÿþýÿþýÿþþÿþþÿýýÿýýÿþþÿýþÿþþÿþþÿþþÿþýÿÿþÿþþÿþþÿÿÿÿþýûõôßÐТ«QMWOZ Xk ªÍÙÖÿúûÿÿþÿþýÿþýÿýüûù÷àÝÛ§€a¡cVaYt¬ÇÕøùúÿýýÿûýÿûýÿþþÿþýÿüüùñòÍÌÉmš] XbZ`zº¡ÎååþûûÿüýÿýþÿþþÿþÿÿýþÿüüúõóÖÕΡTVS]JY ^€ÐÆÏûööÿýýÿþþÿýýÿýýÿþþÿþþÿþþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýþýüþýüþüüþûüþûýýûûÿüýÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿûòïüóñþõóþõóþöóÿöôÿ÷óÿöóÿöôÿ÷ôÿöôÿ÷õÿöõÿöôÿ÷óÿöôÿ÷õÿ÷öþ÷ô÷òíÓÙÌ}£UUHKGWR QRR P PT[i ÏÇœîØÕûîéýõöÿ÷øÿöøÿùùÿúùþøöóêåÁºµfTSYTY¿¶éñêþüúÿþûÿýûÿüûÿýûÿþýÿþþÿþþÿþýÿþýÿüüÿüþÿþþÿÿþÿÿýÿþýÿþýÿþþÿþþÿþýÿüûøôñËÏÌl¥X£RQRKR\i «ÍÒú÷ùÿþýÿýýÿþýþýüøóòÕÔ×~£§[X_bTk®§œÖÛýùúÿýýÿûúÿûýÿþþÿþýþüûóì윌ŸcVQJ¢IU¥¢°¯Üèêþüûÿüýÿýþÿýþÿýþÿüüþùùñå깎Â`¡ AI§<DBN\r« «ÃÑúõõÿþýÿþþÿþþÿýþÿþþÿþþÿþþÿþþÿþþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿýýþýüþûüýüûýúüþýýÿüýÿýýÿþþÿþþÿþþÿþýÿÿþÿÿþúñîýóñþ÷óþ÷óÿ÷óÿ÷ôÿ÷óÿôóÿõóÿ÷óÿöôÿöôÿõôÿöôþ÷óþôóþõôþõôýôòòêèÀÈÃiNLB@DUKGGQ NQKVNZb¢À°°ñßÙýôôÿ÷øÿ÷øÿùúÿùùý÷ôîèÞŽŸ©aV]QOU¥¡ÉÈóöòÿýûÿþüÿýüÿüüÿýüÿþýÿþþÿýýÿýýÿþýÿüüÿüþÿýþÿýýÿüûÿüûÿûüÿÿþÿþþÿýýÿûûøöòÆ×Ïg V£HMYT SRgÆÌöõ÷ÿüüÿýýÿþýýûúòçè÷Án¡c_\R`m·ªÑããþúúÿüüÿùúÿûüÿüûÿûûþûùíðã©Â¬fc¢[BHU¢º±ëîíÿûúÿýþÿýýÿýýÿýþÿúüýøúìêì«ÁÂZ£RLMQ£QV£S]£ºÉöööÿþýÿüüÿûüÿýýÿýýÿþýÿÿýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþþþþþüüýüûýûüýüüþüüÿüüÿüýÿýýÿþýÿþýÿÿþÿÿþúóðþôòÿ÷óÿ÷óþ÷óþöóþöóþõóÿ÷óÿöóÿöôÿöõÿöõÿøõþ÷ôþõóþõóýôóûòðëÞÞ¯š®YMKJEORSEFRNYRWDQI\ÎŒÂøîêýôõþöøÿøøþ÷÷ûóñäÛÓŽTLWMXZ«š²ÐØûù÷ÿýûÿþüÿýûÿüüÿûüÿþýÿþþÿýýÿüüÿüüÿýýÿýþÿþþÿýýÿüûÿüüÿýüÿÿþÿþþÿýýÿúúùøõÍàÞh¥®Q¢QUYQVJe£¡ÊÐõõ÷ÿüûÿüûÿýúýûøïçæ³¶ºVbVTPh»žàéêþúúÿüüÿùúÿûüÿûûÿúúüõôã×Õ©§gabQ¢¢JS«®€ÏÇõöóÿûúÿýþÿýýÿüýÿýþÿûýýøúðëì¶¿ÃZ£^LRPWZb^©¬€Ïàùùùÿþýÿýüÿûûÿûýÿýýÿþüÿþüÿÿþÿÿþÿÿþÿÿýÿþþÿþþÿÿÿÿÿþÿþýÿþýÿÿþÿþþÿþþÿÿÿÿþþþûûþûüþüüþûûÿûûÿüýÿüýÿþýÿÿþÿÿþÿÿÿþõóþôóþ÷óþöòþöòþõóþóòþõôÿ÷ôÿöóÿöôÿööÿöõÿ÷õÿøöÿ÷õþöôþôôùóïãÙÙŠSKGLKXOSLEKFXOSBL>KW §æàØûññþö÷ýööýõõùðíÛÑÉŠKEOQ[h®±ÂÙåýúùÿüúÿüúÿüûÿüüÿüüÿýýÿýýÿýûÿüüÿûüÿüýÿýýÿýýÿüýÿûüÿþýÿÿýÿÿþÿþþþýýþúúûùøÜéé²»Wb`aSTNh³Ž»Úàû÷ùÿûûÿüúÿûùüùõèæÛ«£OZWYV cžÂîððÿúûÿýüÿúûÿùúÿ÷ùþøø÷îìÑÉÁz¢_W`OKg©°ÂÞÔüù÷ÿùúÿùûÿúüþùûþøûþøûü÷ùòòòÄÜ×c²£^OOY\OM¢g¯®Áßëüúúÿýýÿýýÿüüÿýýÿýýÿýüÿþýÿÿþÿÿþÿÿþÿÿýÿþþÿþþÿÿÿÿÿþÿþýÿþþÿþýÿþýÿþýÿþþþýýýúúýøúþûûþûûþüüþüýÿüýþþüþþüÿÿþÿÿÿÿ÷óþõòþöòþöòþöòþöóþôóÿ÷õÿøõÿ÷õÿööþöõþõôÿöôÿ÷õÿöôÿöôþõô÷òíÛÜÓ£€PJQHNRO¡©O¡ŽQ ºS¢»NšºB€±QTQFNGERuÇÎÀöîëýõõýööüóóõìêÐÆÃn?JNWQ|©¶Ôåìüùøþúúÿûúÿüúÿûûÿüûÿûûÿûûÿúúÿùûÿûûÿúûÿúûÿúûÿûüÿûýÿýýÿþþÿþþÿþþþýýþúúþùúñöõ²ÖÛa°¿Wš«UNNFY§ŽÏÛâîðýùúÿúûÿûûþùùøòíÙÜÉ©KT XMYl¬ÌØöôõÿûûÿúüÿüüþùûûöùû÷÷îìèÀÄ·gTSWNN€u«ÂÓåéýùøÿúúþúûþ÷úþøúû÷úü÷ùú÷ùöö÷ßííÒÖ^·YCQQNW¬ÀÇ×ãîòýúûýûûþûüÿýýÿüýÿýýÿûúÿûúÿûûÿýýÿÿþÿþýÿüüÿýýÿýüÿþýÿýýÿüýÿýüÿýúÿýúþýüýüûýùùúøøúøøýùúþúûþûûÿûýþûüþúùÿÿþÿÿÿÿ÷óþõòþöòþöòþöòþöôÿ÷ôÿ÷ôÿ÷ôÿ÷ôÿõôþöõþõôÿõóþõôþõóþõóýôòõîéÍÓÇrJ@WOTX}¹ÆÊÝËÞÍßÎÛvÃÎiª³[IGMREO c¿²ïëçûóôýööûóôïêé¿ÃÄ^9OFQD¯œâëïýøøþúúÿúúþúùýøùÿüúÿüûþúúþùúþøûþùûþùúý÷ùûõ÷ûõ÷ûöøýøùÿúüÿýüÿûûÿýüÿûûÿúûüüûäóó¢ÚákºÂQ«G¯¬J«šXžŸÍÛÖëòöö÷þùûÿüüÿüûüöôïáßų°l]WYLRd±ž¿ÚäûøøÿûüÿúûÿùúþøùûöøùõõììåµÈ±eR WIRJ«Ææìñûùùÿúúþûûþøúþøúú÷ùúôøüøùûøøôõ÷ÕêíËÕi¬ŽJ§X£[޵n»¿Òã×íòöøùýùúýúúþûûÿúúþùúþúúýùùúõöþøøÿûýÿþýÿþýÿüüÿýüÿýüÿýûþüúþùùÿûúÿúúÿùúþûúýúúýùúüùùûøùýúúýøùþüýÿýýÿýüÿýûÿÿþÿþþÿöóÿöóþ÷óýõòýôñþöôÿ÷ôÿöôÿöóÿöóþõóþõôþôôÿõóþõôþôóýóóûòñîå⻞žaRD]UVlª€»ÓÕàêíäëïäëïÜéíÉáåŠÏÔr±ŽFDFPFL W²¬êèåùóóûööúòóçà⬶œU?QBWO¢ŸÃìïñûö÷þúúÿúúþúùþùùÿûúþûúþùúþùúýùúüøúþúúýøùùõ÷öóôöóôùôõýøùÿûûÿüûÿüüÿúûÿýüþýýúüûçôóÃâä£ÓÚÕÚ×Ú¶ßæÜíñõö÷üøùþùúÿûûþüûùóòêâÞ³¶®SSGKDZqŽÂÕåïþúûÿûüþùûýøúýöøü÷øöððâÚØ¯£Q MeMZJ¥ÅÓíïôýùúþøúý÷ùý÷ùþùúýøúüøùüùùüøùú÷øôõ÷ÞìïºÞãÑÞÑß¢ÚæÆæìçõøûûûüùûýùúþûûþûûþùúýøùùöøüøùûøøüøùÿûüÿúûÿúûÿýüÿýüÿýüÿýüþüûÿüûÿýûÿüúÿúùþüùýûúþûúýúûþúûüùúû÷øýùüþüüþûüÿýýÿþþÿþýýôòþõòþ÷óýõòüôòþöôþöóþõóÿöôÿöôþõôþôóýôóþôóþôóþôóýóóùñðèßÛª§©WWNcX\³ª×ßÝóïð÷ñóùóô÷òòðïïÞæåªÌÈ[£E=IFKUª«æçäøóóúôõøððÞ×Ú£±NMP>R^££®ÎÎòòòùôöüøøýø÷ýööýöõþöõü÷õý÷÷ýøøü÷øúöøýùúþùúý÷øúööúööûööýøùÿúúþúúþùúÿùúÿüûÿüýþýýýüúö÷÷éñôãîòåïñïóôù÷øýøùü÷ùþúúÿûûþûúûöõéæâ€®¬OL:36Y±Äèíóþùûÿûýþùüýøúùóöüö÷õêíØÇÊJ;PFM`ªÓØòñõþùùýøùýøùýøùþúüþûüýûüüúûüøùûøùù÷øöôöîòôêôôíö÷ñ÷ùøøúýüýþüüýúüþûüþüüþúúþùùúöøùöøýøúþûùþùúþúûýùùûöøÿúûÿýýÿýüÿýüÿüüÿýýÿýûþüùþù÷þûøÿûúþúùûø÷ýùùüøùûøùûøúþùûþùûÿýúÿýýÿýýúòðþôòþ÷óþöóþ÷ôþõóþôóþõóÿ÷õÿ÷õþöôþõóýõôýõóýôóüóòûòò÷ïîáÜÕ§ VROXV Yº·æèæõïïúòôûóôùòò÷ðððìëÑÚÔy¥¡JA>MDSª¯äåäøóóúôõõííÖÌËGO KBIp¢ŠÅÛÚ÷õôúôôùòóúëêùàß÷ÙØùØÔ÷ßÖúêÞýñéüððùôõúõöýöøýö÷þøøýùøýøøýøøýø÷ûö÷ýö÷þö÷ÿ÷öþ÷öýööÿúùþùùû÷øøôö÷ôõøôôûö÷ýùùýùúÿûüþûúúö÷÷òóàåâ·®IBC15X¥ÁÊóòôúõùÿúýþûýýøúùô÷ùõ÷òìíÏÌÌlCJHCKr£ÁÛÝû÷ùþüúþûúþúúþûúþùùþùúþùúýûúýùúýøùü÷øùôõ÷ôôúøøþüùþûüþúûÿûûþùûþùûþûûþûúýúùýø÷ûõöùòöþö÷ÿõõÿñïþåäýöôûöøþúúÿüüÿüúÿüúþüùþùöþùïýöæûð×ùçÜþôæýùóû÷öýùøüùùûøùûøúþûüþýüþûúÿûúÿýûúñïþõóþ÷óþõóþöôþõóþôóÿöôÿ÷öÿ÷õþöôþöôÿ÷öþ÷õýöóûòòúññöîìÙÕÍ¡RHNKT\§ÃÈðìì÷ññüóõûóôúóóúóóöîîßÚÖ¡KM <J@S¶²åæåùóõúõöõîìÎÍÁqJSLQJ¥³ÙäæúõóøèéòÑ×ìÍÉßž³Ó¹³Î¶«ÎŸ²ÛÁµåÈÂóÐÖöïéöòðùóõýõ÷ÿùùþùùýøöûõíúñèõíæôæâ÷ßàøÔÙ÷ØÚ÷ÔÛûëåøòì÷ëè÷áãøééøððûööýøùþúûÿüýþûúùõöóêíÕÊÒz¡ŠSEB /G]¯¢ŽÕ×øô÷úõøþøûÿûüþùûüöøùõöíëêÁËÊfJL?G?~¥ÔàãüùúÿýýÿüüÿôöþãêûèêûòïüôòûóîúìëúßäùåèôÚáøíëûøñÿ÷ðÿóòÿóôÿùúþùúþúûþüýþüüýúùý÷÷üõôöìí÷ßåôÄÓðÎÐæžŸöìíùóöýøøþùøûöóùóïüöíöðáîæ»æÏ«ßÆÚ§éɬòÒ×ùòîüù÷üùøýùùýúüþýýþüüþúûÿþþÿÿýüóñþõóþõòýõòþöóþõôþõôÿöôþöôþöõþõõþõõÿ÷öÿøöþ÷õûóòûòòôêéÍÃÁp OHYTWgšª¹ÐØôîïùòóüóöýôõüôõüôõøðïá×ÓGNFN JY·éêèùóõùóõñëçÃŲgQ^S\M ±Ãæêë÷ñèíÜÍÐ±š¬²Š{v šŒ®ªáØÀóäáøòôþöøÿùùþùøùòêê߯ÕȮ˶¬ÄµªÅ©£Ä«€Å± ÉŽªÐ«Ïù̺¯É°¯ÎÁœãâÜùôôþøúÿûûÿüýþüûûøöðéæÅžcVD J|J[o¯£Ìâàüøùü÷ùûöùþúûýøúüöø÷ñóçäߪŸµULUHS?€£Ÿ²ãëëüøøÿùúþû÷øìåçȺÚγÛÏ·Öɵ֞«Õ³¥Óš Øœ¥ÓŒšÚÊ«ÞÌ·ÜÀ©à޶ôÔÓÿùøÿúüÿüýÿýþÿýýþûùýôíùçÚíÐ¶ÞÆµœ®¥¬²€ŠÖÍß÷óõùôõúñïñãÕåÏŒÒݪš€sm r©€³¬ÔÍ·ñïäùõôüùúüùúýøùþúûÿýüÿÿÿÿÿÿýõñþõóþõòýôñþõóþõôÿöôÿõôþõóþöôþõõþôôÿ÷öþ÷õþöôýóóûòñðå圱Ž[FHW`^w޳ÉÙáöïðûóôüôöüôõûóôúóó÷îìÛÖÏ MJHPQ]ÆÁîíëøòó÷ñòèâÞ®Ž©ZS\SRSœÍèâáâÚÎÀÀ¶aZLRZ^hu¡¬¡áËÓúóóýõ÷ýõøþøöòå௚}¥upifro{mrs§žÓÛøõöþøúþùûÿüýÿüüýúøðêåž»¯ZV MSI^¯±áëêþúûýøúýöùþúûþùúý÷ø÷ïïÞÎÊ¢OGXJJPªÌÉñôôûöøûöùü÷ôéçÛ©·¢x|rvhfrltpt²³ÈÕÒþùøÿûüÿûüÿýþÿýüýöííÞÅÏœ°Š¬jav¶ÂÙøóõùïìíÏÎÏ¥ iO71A L_gª¡ÐÞÍñëäúø÷ýùùùöøü÷øÿýýÿÿþÿÿÿþ÷óþõóþõòþôòþõóþõôþöôÿ÷õÿ÷öÿ÷öÿööÿööÿ÷÷þõóüóòüóòúòðêæâ޲Q6BSXXµºÛãéùóóüôõýôöûóôùñò÷îïñæåÊÂÁrSHMKUd€ÊÍñíî÷òóóîïàÚØ¡JLKM Da °ÃÕºÁ¥¯«n MB@NVYS~ZM l³³»ôååùóôûóöüööìå८£]\KE:?G[NU Ll£¯ÐàøôöþùûþùûÿúýÿüüýùõëêÜ€œSNJ?G\ŽœðóòÿûûþúüþøûÿûüÿûüþùùöñìÕÓÁyCCLSSg«¶ØØúùúýøúü÷øøñîÝØÇ³ZU§E>JENAR5NgŽ·ÄÛÝýøøÿûûÿûüÿûûýúøìï᫜€qY QL¡EW©ÅòêéêÑÀŸ¹s=A <E >LFA?¢^®«ÖÃÀöñîü÷øû÷÷úö÷þüüÿþýÿÿþÿøôþ÷óþõòþõòþöóþöôþöôÿ÷ôÿ÷õÿöõÿööÿööÿööþôóûòñûóòøñîãàÛ³¬R:BDJT¯»ééìûóóûóôýôôûòóùððôêéæÚÓ«©¬VTD N LUr§ŽÃÖÝóîñöðòóîïÚ×ÖBD;L@jš®ŠYJ8==OTZ HVDU €ªâÖÙøñóûóõúõöáäâššZVHB825IFUHt¢®ÄØæúööþùúþøúÿúüÿùúüóðàÕ̬QEH3CMª¥Ì×÷÷÷ÿüüþûýþúüÿýüÿüüýööñíêÊÍŸpCN<TGm°ÊÝæüøúþùûýøøöììÎÜf XP\:L0C;OAip¶ÆÖæëüøøÿøúÿùûþøùü÷öèîâÇ©B3E L\`«ÃçßÛœŸ²kWPG 9C2<1I >M M¶¯ëæèõòóöñóúõøýúúÿþýÿÿþÿ÷ôþ÷óþöóþöóþöóþöôÿöôÿõóÿõôÿõôÿõöÿõõÿõôþõóýôóüóò÷îëÚÓÌŠ P?L =FV ¹ÁïëìýóòüóóýóóûòñöéèíÒÐÒÀ¬LZCH KSŒÉÛæìöðòõîñòëíÐÌÐsIE>OAdzc@K:EIMPP9L <Fn¢€ÑÌÎúòóüô÷öóõÓãâr®«L]O>>/3M HSL}²°Ôáêü÷÷ý÷øýö÷þùùüöøøïëÒÇŒz¥VCTBBZ¡³¿ÚçýúúÿýýÿüýÿûýÿýýÿûúýöõïêâœÊªjTXG^Lw¯œÜæðýøúýöùúôöíåäµ°^M?_UUJ\BOJ\ªÈåíóþùùÿøúÿøúþøùüõöçèâ¥À«U8~I=EW² r98;LTKCZ;A 9Tx]€ áÝç÷ööøôöú÷ùúøùÿþýÿþþÿöóþöóþöóþöóþ÷ôÿöôþõôþôóþôóþôóþõôþóóþóôÿõôÿõóþôòõéæÎÁºmIHK=I[гÉÈòëëúîìõéçûèæöãÙíÎÄѱ¥ ¡dU`GC C`§ËÓìîñ÷ðòõîïíâ䟲ŸaMMPTDOPJL€EаM²ŽF§®<¢GQ>3D>Ab§¥ÁÌÊúóóüõøõñõÌåèaºÅF§·V©¶NŽEªG1CJ?BS¿ºâèìúôõúôõ÷òôúõöùóõñëêÃÅÁcC:IC>g€»Ðàìû÷úÿûýÿûýÿüþÿýýÿûûüòñæÍЊTDIFGRÂÎêïõûöùúôø÷ôöìîî¥ÎÏ9±Œ;©¹B²P ŽEªBCB:~QQhŒÓõõ÷ÿúúÿùúÿøúþøùüø÷íîé²ÎœR¢@HNSK^_<@5²D»_«œN€·@«±8 CJ GO\9f¯ªÄÐàõóôüøùýûûþüüÿýüÿýýþöóþõòýõòþõóþöóþõóþõóþôóþóóýóòþôóýóóþóóþôôþôóüóññç⟜³bARDEOiœººíÓÑðÒÏìÖÆìÌÁÜÉÄ«iIUVP>Iq²ŽÍÞâóðòôîñòêìæÙÚ®ªQRMRUG>IB¡f·Á ÍÚ¡ØáÑÜw¿ÎXŠS:6AVFd¢¢¹ÐÌøóóüõøøô÷âíñ©ÙæÓâ¢ÖâÐÜŒÅ`8<B;D[Äœêíí÷óóöòóöñóùôööóóçççÅŸO9M>G H~£ŸãéðüøúÿúýÿûþÿýþÿýýþüüûòïÝÏÍH~RGMOk¢ÍÑôóöüöùü÷úúöøóóöÑéî¡Úæ ÙåÐáËÚ ²Y` MGC}B[ª°Òßú÷ùÿùúÿøúÿøúÿøúýùø÷íéñ®_KFC3B{W]XT¬kÀÛ¡ÕçÀâë¿àèË×hM¢ EJ§|<=MnаÅÑòóòúöøþûûþûûÿúûÿýüþöòþôòýôñýôòþôòþôóþõóþôôþôóýóòþóóüóòýóòþôóýôóúñðëãÞ®œ®`JXCMRd»ª¥À¯ªŒ·£¯€Š~SL@UOS@_§ÊÒæìîôðòôîñòêìâ×ÓHRJRL~J 5MeŽŒÖáØéîçïñåðñÎâä¶¶T=ODR=c¥ŒÒÕøóôýöøüöøø÷øîóöìòõèðòßëëÂÒËl;<<>@`¢¡°ÏÊññï÷òôøôõöòóøóõòïðÜÞß¹¶LCT 79K¡ÃËòóõþùûÿùüÿúýÿûþÿýýþûûõðîÏÏÎyDaG¡J<gœÓÛú÷øþùúýøúû÷ùùõøõõùðôøñõøíóõäæé³·¿JCBYE L f©Ëáéüøùûô÷ÿöúÿúúÿøúþøøõì麜·A€CEa|MZIK @®ÅÇØÕèðñóôñîòòñóèìíÅÆKNLS=5;¥€ÊÖòóóûøùþúûþûûÿúúÿüýýõñýôóþôóýôòüóñþôôÿõôÿõôÿõôþôóþóóüóòüóòþôóýôòùîîåÙØ®£VRWJOVQnxzjXMPFC<FHPL¢µÃËÞéóñò÷ñó÷ðòõîíßÛÎKQLQLO?d¯Ž¯ÖÝæîñ÷óô÷óôøóóðîêœÉŸ[>T>FAk©ÆÕÜùóôþøùþùùþúúþùúýùùøõõïêæÅÀ·dEK?@?e©ªÅÛÚõóòúôöúôöøóõúô÷ôîîÖÊÏ¥NIT9FXµÖÑùööýøùýõùÿøúÿûýÿýüþûùôïìÅÔÈlLYQDEv¥£ÑÜÞü÷ùþøúü÷ùû÷ùüöùúöúýøüýúúúøøìéç°±K=@]@@xª Þèêý÷ùýøùÿøúÿûüÿúûþøøôêæœšTWAKFD~H [œÙÚèïøõöûö÷öòõöóõôïðÕÎÊp F=y: .AY£ÏÐñóóûøùþúûÿýüÿùúÿûüýóñýóñýôòýôòüôñÿõôþôôþôóÿôóþóóþóóþôôþôôýôóüóñøëëÜÍÏQZVQMTMU] XRAC>IB@:KT§sŒÇžÙßçêïõñòùòôúòô÷ìêÖÆœxN HQIU T`¡Í×ãêîöóôûôöùõõ÷òòòîêÆÒÀ`?B<>Ku³ÑÚåøñôÿøûÿúúÿùùþøøýø÷ûöõîéã¶¹©[X GDCItž»Óâäöóóúõ÷úõ÷ûöøûöøôïîÎÉÊlFO HJPl€ ÈÜÚúö÷üöøýõøÿøûÿüýÿýüý÷õðáá¶®ž] X[PCD{»·àèçùôöüøùþ÷úýøùý÷ùûöúþúýþûûüú÷äèáž±>-€ ?B?O®ëîîý÷úþøúÿùûÿúýÿúüýùøíê䊷©B9 B|CB}<FvœÀÍàéøó÷ýùùûöøûôöùôööòòäÞØ:L{K42PÇØïóóýøùÿúûþýûþüûÿûûýôñýôñýôñýóòþôòþõóþôóüóñþóòþôóýòóþõõþôõýóòüòñõëêÑÇÊsMZMTMOKK[QaOT;J:IC\«y¹ÅžÚæéîðôðò÷òóúóõüôõõìèÊŒŽdQ=L>YM±¶Ñâéõñôøóõûõ÷úööøòóíæä¹¿²ZF:;: Q}³Äßåîùô÷þ÷ùÿøùÿøùþøøûôõøòóæáÝ£€V_ISF^¹Äáéê÷óóý÷øýøúýøùü÷øñîë¿ÇœaMK2C Dz¡šÔÞàü÷øý÷ùýöùþ÷ûÿûýÿýüý÷ôëÝ×€M_BM;M¿ÁèíîûõùýøúÿùûþùúýøùýøúÿùûþøúüôòàÔÊ«L FJ5?E«ÇŸõôóûõøüõøÿùûþøûþöúüòóãÕΚY{~QtR3yI {:]¬Óßòòóùóöþúúýöøüö÷÷óô÷óòäÚÓG K5TF\ÆÔõö÷þúûÿüüþýûþùúÿúýþöóÿ÷ôþöóýóñýóñþôóýóòûòïýóñüóòúñòþóôþóóýóòûñññèæÄÆÅhO]JRCKGO]RaK\IL7Hš`®»ÀÒÀÝæìðñøòó÷ñó÷ðòøòôûóóðèä¶Ž¬VO=M7] Rª«ŠÏÑïðòúôö÷òôùóõúõöøóóçÞÛ¢¡P~S> BEXÅËíîòúô÷ûô÷ÿøùþøùü÷øúôöôóòÝàÛ§BMMQ@_ÂÓêîïøõõýöøþúúüö÷ùõõëëã®È®QNLB XL¢·Áâèìýøùý÷ùüôúü÷ûÿúüþüúûöñãâÒDYAT<Uš£ÌÖìïòüöùþøúþøûþøûýøúýøúÿûüþøù÷íëÒ¶Žk O:7/MSж³ÕÙúöøû÷ùü÷ùÿûýþûüþ÷ùùïðÔÌÎj©@H>3U}F œÒãîóüøøü÷øüöùýö÷üõööòõù÷öçéàªIY =T>S¡¢ ÆÝõõ÷ýùúÿýýþýüþúùÿúýþ÷óÿ÷ôÿøõþõòýôòþôóüôòüòñýóñüóñüóòþóôþôóýóòüñðìßݱ²µbRXKLAIQU\TVAFM¢PŠ€VޱvÀÍŠÔߨèîóóõûôôûóóøñòôïñôïñõîïæâà«PKCF?]o¶ÁÏâæøóöùóô÷òôøòóöòôöòñãàÝ QOCCK^¢ËÐóñóûô÷ûöøýøùþøùüöøûõ÷óíïÖÌÏr€>G?D A_«¡·ÒáõõôùõöúôöýøøùôõöîðãÒÏ¡\KDCVd§É×ðñôýøùü÷ùüôøüöùýöùþøøøõïÙàÊzEX{T}IJn¡¬žÒÞíðó÷ñöþøúþøúþùûþûúþúúÿûûþùøõð뿹®ZFBH4D]§žÄÛâú÷ùýøúþùûÿûüþúûýõøöïðÍÇÅb\E2)<\¢±Öèýúûþüüýùúü÷ùüö÷üô÷øôùúøöèêߪAA=ZvK m®ÄÛïïóúøùþýýýüûü÷ùþùûÿøôÿøõÿøôþõóþóóÿôóþõóþõóþôòýóòÿõôÿõõÿöõþõôûðïäÒÒŠ\UQMGIL¥ X±Ž]±a§°]Ž\¯ŒW±ÇW·ËqÁÍÍÕšÖÝÉãêåîðùöõþø÷þööýõõúóóöòòôðññéìÚÎÔ §¥MIIDM_¢ÂÔíïñûõöùòõúôöúõööóôòðîÛàÕ¢SEMFUkŸÑÖøôõþ÷ùý÷ùýøùþøùý÷ùüö÷òëëÌÄÉg©?@=BUq·§Ðãèüùøüö÷üö÷ýö÷ùôõóìîÚÐÉKV@JVt³×åõóøûõúüöùüõøûõøùôøü÷÷õíêÉÈœZQTX;Lk¶»Ëàèíîóóîôü÷úýøúþùüÿüûÿúûÿúúþúøðð髌ªZID7AN}¢ÂÛåíú÷ùýöùýöùÿûüþûüýùøòïë·Ç»_@£A ARds¬ÖèîþýýÿýýþûüþüüþúúýúùüøùøõôßáÙu¬C DGXG[·¬¹Úçïñôüùùþüüüúùú÷ùúöùÿøóÿ÷óþöòþôòþóòÿôóÿöõÿøõÿ÷ôÿõôÿõõÿõõÿõõþöõúïìÛÎÉNTKNN|byŒ³ÏÖÌÛÐÛÓÞ€Øâ°ÜéµÝéÄâìÛëîéïïôóôúôôýõôþ÷÷þööþ÷÷ýõõüöõùôôóëìÍÁÈmOBH>Ne¬€žÖàúööþøøüöøýøùýùøû÷öñïìÉÑÇcP:PFaw®§Õáàý÷øÿøúþøúþùúþùúüö÷úôôòì霶œ_G? CC KŽ«ãìíþûùþùøþùùýøøúöõñíîÍÐÊg;[7GBv³Íáìüùùü÷ùýùúýøúü÷øü÷ùýø÷óáß· §NQFR2V»Ãâíðîðôíìõ÷ó÷ý÷úþûüÿüüÿüýÿýýýøøêæá·€WGH7TN«ÁÔçëðøõöýöùþûüÿýýÿüýýööíáÝŠ¶«VLPA€C2š£~Áœóôôÿþþÿýýÿùûÿýýÿûûþûúþüû÷ïïÔŒŸi£G4¥7Q \t»®Ñéïûúûþüýþûûüúùýùúýøûÿ÷óÿöòþôñýôñýôñÿöôÿøõÿ÷õÿ÷õÿöôþõõþôóþóòýóó÷îèÑÐÀnEUOUT~oµÓÍçðïèñòèðòêòòíòòòóôôôô÷ööúööûöôü÷öýöõýõõþööþööÿö÷ÿ÷÷þø÷ýøöõíêÅŸºaWEJ 5PwªÚæèþùøÿùùÿ÷øÿùùþùùü÷õïäà·©ªZ_<KF` Áµéïëÿøúÿùúÿúûÿüüþûûý÷÷ûôóîíã°·°WOF<JOž¹óòñÿüùÿüùÿûúþúùûöôðîíŸÐÈ_;J >[T±Žãìïþüüþûüþüýþúüþúúþúúþùøðëé®8D>]:£eÆÇîòõðò÷íì÷÷óùý÷úÿüýÿýýÿýþÿþýüóðÛ¿ÇwQHC@G_¢¢±×Þóóõü÷øþùüÿûýÿüýÿüüýôóãÌÅ ¢P:§¢MLfW¡¥©ÐÌýúøÿýýÿûýÿúüÿüýÿûûÿûûþúûöðîÊÄÂS XMOII¢r»¶ãòôÿþýÿþýþûûþúúÿúúÿþýÿöóþõóþõóÿõóÿöóÿ÷õÿ÷öÿ÷öÿ÷öÿöôþôôýóòüññüòññéãÂÁ³\T\ YW[ y¡€ÓÞÛüöôýøöý÷öý÷öýø÷ý÷÷þööþùøþøøþ÷õÿøøþø÷þ÷÷þööþöõÿö÷ÿø÷ÿùøþøöóîæ¹À²[UXMAO޳åçèÿøøþùùþôøÿùùþùùü÷ôéãÚ€£Z\HNK]££ÊÊööóÿøúÿúûÿüüÿýüÿûúþùøüóòèÜ×®«XKE>RV£Š§ÆÊøôóÿûúÿýúÿýûþüúûöõíÞ⬪·RMM>YdÈÀóöôÿýýÿýýÿýþÿýýÿûüÿûûýúùèé犯2<GC<f ²ÎÓóô÷òóøöñùýùýþüýÿüýÿþþÿýýÿüúûõòÌËË\GWZVW£mŠŠÆàäýùøþùúÿúýÿýþÿüýÿüüý÷óÞÓÁlT@VNOa¡²ÂÛÜþûùÿýýÿýýÿüýÿýýÿýüÿüüþüûõî쌶»TZM7¡Qb»·ôöôÿþýÿþýÿÿýÿþüÿþüÿÿþÿ÷óþõóþõóÿõóÿõóÿöôÿ÷öÿ÷öÿ÷õþõóþôóýõóýôòýòðíãݯ«©L]`aK] ¹ºãéåþøöÿøöÿ÷öÿøöÿøöÿøøÿøøÿúùÿùøÿùöÿùøÿ÷öþøøþ÷÷þ÷öþ÷öþøøÿù÷ýöóíáØŠ³£[QbPOT€¡§ÉÅðïîþööþùùþ÷ùÿùøþ÷÷ùõòãæÖ©YQ[P KXš·ÐÚüù÷ÿùúÿùúÿüûÿûúÿúøþú÷ûòíÝËÁ©Y=W?M`©ŸÕÔüööÿûùÿûùÿýûþüûýøôçÝÙ£©KPL~LMh«ÒÇöôóÿûþÿþþÿþþÿýþÿýýÿüüü÷õÙÔÍ]¢£4D^GOjŽÈÞÚúøøýúúýùúÿþþÿýþÿýüÿýûÿýýþùùùõí¿ÇžgN¢OA€IV©ãêêþúùÿüüÿüýÿýýÿüûÿúúûôìÉÅV7£<3<Yµáéìÿýüÿþþÿþýÿýþÿþþÿþýÿüúþú÷òìãšÁžQYc b]UŽª¥ÒÎýüøÿÿýÿÿýÿÿýÿÿþÿÿþÿÿþÿõóÿöóÿ÷óþõóþõóÿõôÿöõÿöõÿ÷õþöôþöôÿ÷õÿöôýóñëâÜ ¢N` Vh MdÈÌîðîþ÷öÿ÷õÿøõÿøöÿøöÿøøÿøøÿùùÿùøÿù÷ÿøøÿ÷÷ÿúùÿúùÿù÷þø÷þúøÿù÷üóïäÍÆ¢[ObQ\f¯±ÅÝÚûøõþøøÿùúÿúùÿùøþ÷÷õñîØÝÒo©RLP>F`§²ÍÝçþùùÿøúÿøúÿúûÿûúþúøþ÷õûóíОm>2eJRp«ŸÖåæþøøÿûùÿûùÿüúÿúøýøóàáÔyKU< FBl¢¢ÅÚÕüøöÿüþÿþþÿþþÿýþÿûúþúùùìèëPC6LC\yޱáìêþýüÿýüÿüüÿþþÿýýÿýüÿýûÿúúþ÷øòïæ¡ÃµRCWKVD£šººíòïÿûúÿüýÿüýÿýüÿüúþùøõïçµÄ®XNV}1G9§ œÐïóóÿþýÿÿþÿþþÿýþÿÿþÿþýÿüûýóïæŸÁ ®\B€£EH§\b²œÈæçÿýúÿÿþÿÿþÿÿþÿÿýÿÿÿÿÿþÿôóÿöôÿ÷ôþõóþõóÿõôÿôôÿöõÿ÷öÿ÷õÿöõÿöõþõôüôñæâÝŠ§R_Rj_i¢šÍÙõóñýõõÿøöÿøöÿùøÿùøÿøøÿøøÿùøÿø÷ÿø÷ÿøøÿøøÿúøÿúùÿù÷ÿøøÿúøþù÷úñîØÊŸsPL\Ncz®»ÞééþúùÿùúÿùúÿùúÿúùýöõðçèÅ·Œ^ UUJ;Hw·»âëðÿùúÿùûÿùûÿúüÿüúþù÷ýöõùòêÀ¯[/CWPcªÅëðñÿúúÿüùþûùþùøý÷õùõíÕáÃd¢J REJPyª®Ùäãÿüùÿýýÿþýÿþþÿýþÿüüþûøøñ௱GPCTPb¿ÄõøöÿÿýÿþýÿýýÿþþÿþýÿþýÿýüÿûúýôòåÎÊ¡SBUB Pc ¥ÐÉùùöÿüûÿüýÿüýÿýüÿüûþøöìÕÔ¢¥^ D{A/NT §Ôáø÷ùÿýýÿÿþÿþþÿþþÿÿþÿþýÿýüüôëÒŪhRJiyNXm·ÌàðóÿÿýÿÿÿÿÿÿÿÿþÿÿýÿÿÿÿÿþÿöóÿöôÿøóþôòþõòÿõôÿôôÿöõÿöôÿöôÿõôÿöóþõòúðìØÑÎz ^[T`kv ÁÓÜ÷óñýõõÿù÷ÿø÷ÿø÷ÿú÷ÿùùÿùøÿù÷ÿø÷ÿø÷ÿøøÿø÷ÿù÷ÿùøÿù÷ÿùøÿúøþù÷÷òïÉÎÂhUSUS]¬Áíïðÿùùÿùùÿ÷øÿöøÿúùý÷õîçæ°®³Y£DRI>WÀÅïñóÿùúÿúüÿüüÿüüÿüûþ÷÷ýõõóêå§Œ¬L3R^Lc¢œÒöôöÿûüÿüùþüùþø÷ûôóõìåÅœ±T¡U^ TT P¡|œÌëððÿüúÿûýÿþýÿþþÿþþÿþýþýúðñß³VYBIKPªŠËÝýüùÿÿþÿþþÿýþÿÿþÿþþÿþýÿþýþúúûóðÜÎÄqA:PRMZ¢ŒŒÜäþüùÿýüÿýýÿýýÿýýÿüüýùøéàÛDJ MNVf¢¥³×äýúúÿýûÿþþÿÿþÿÿþÿÿþÿþüþûø÷æâµ·€YVMXšNW±£Ðáøúøÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿ÷ôÿ÷óÿöóþôòþõòÿõôÿõôÿõôþõóþôóþôóÿõóþõòöëäȹµfc[Z[hzšªÖâãúõóþøöÿøöÿø÷ÿøöÿù÷ÿøùÿøøÿùøÿùøÿùøÿøùÿø÷ÿù÷ÿùøÿùøÿùøÿø÷þøõôíêžÄŸf_XO_d¡ÀÏ÷ôõÿúùÿúùÿøøÿ÷ùÿúùþúøíêä²±P5RBRešÆÌ÷óôÿúúÿøúÿúúÿúúÿüûþúøýóòèÎÑ«I@Pb\g€ÎÝû÷ùÿûúÿüùÿüùþùøüôóñæÝ®€P `O¢VTbÇ×ùööÿüüÿüýÿýýÿýûÿþþÿþýýú÷çéÐ{µYO~^KLZ²°ÃßêÿýúÿþüÿýýÿûýÿÿÿÿþþÿþýÿþüþúúøóìÍÈ·iQND¥GNp¶ÖåëÿýüÿþûÿþþÿþýÿýýÿüüýøõÜØÕn? <<¡X~U~ÏãäþûûÿýûÿþþÿþþÿÿþÿÿþÿþüýöòäÉÈŽPX{VQ¥ntÀšÍèíÿýüÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿöóÿöóÿõóÿôóþõóþôôÿõôÿöôþõôþõóþôóÿõôþõòñæÜެ§W_U[Xe¿µæìéþøõÿø÷ÿù÷ÿùøÿùöÿúùÿøøÿöøÿø÷ÿùøÿùøÿúøÿøøÿøøÿøøÿúøÿúøÿø÷ýöôíÞÞ®] __YcnªµÕØýøøÿüûÿúùÿøøÿøùÿùùý÷ôçßÚ³¯R;O<Zm§šœÐÔûõõÿúúÿùûÿúûÿûûÿýûþüùüóðßÍÍtLK O^^n©£ÆÝäþøùÿüüÿýüÿüúþúùýøõðêà¥Oh\c>l¡²ÐâþøøÿýüÿýþÿýýÿýüÿýýþüüúðïÖº¹j^ CZH£Fn³œÔæíÿûùÿüüÿýýÿýýÿýýÿüüÿûûÿþüþûùõóí³ÎŒLFWJUFzšÄçîóÿüüÿûúÿýýÿýþÿþýþýûøóòÃÔÔQ>V<Y;£«r³°ßëêþúùÿüûÿûüÿýüÿþþÿýýþùöúëݰ¯ciJV:¥y² ÇËíôôÿüúÿþýÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿöóÿöôÿöòþôòþôóþôôÿôôÿöôÿöõÿ÷ôÿöôþ÷ôüôðëâÕªS]T\PdÆžîðêÿ÷õÿúøÿúøÿúøÿûøÿûùÿøøÿõ÷ÿ÷÷ÿùøÿúøÿúøÿùøÿøøÿ÷øÿúùÿûúÿùøý÷ôæÚÖWX]]`tªÎáÜÿøøÿûúÿùùÿøøÿøùÿøøüñíØŸ¿n¥€[VZKWtްÕááþøøÿûûÿûüÿûüÿûýÿýüþüúúôðÐËËk\£QMT]| £Ùæèÿúùÿýýÿþüÿýûÿüúþû÷ìíÞ§RcTdLt ÇÒãÿ÷öÿùøÿúúÿûùÿûúÿüüþûûúñíŶ³VSQXPR³ºåìîþùöÿüøÿýúÿýüÿýüÿüüÿûúÿüúþùøîßܬRS]KDI¡ÄÒôöùÿüüÿúøÿûýÿûýÿüüþúùïàݱ§±\(B ?JQ˯ô÷ðþúúÿüûÿûüÿùùÿøøþ÷öüÝØÞŒ¢AIB }T;g¹·ÞåýûúÿûúÿþýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿõóÿõóþöòþóñþõóþõôþôóÿõôÿöõÿöôþöôýöóúñíâÙ̬]^ZUWg®ÊÁõóîþöôÿù÷ÿùøÿùøÿúøÿúøþøøþ÷øÿùøÿùøÿú÷ÿûùÿúùÿùùÿøøÿûùÿüûþúùûöñÜÙÊuXNX`Y¢¢áèãÿøøÿùùÿúùÿùùÿùùþøøúïéÅŽ¬cQ^^WY·ŒæììÿúúÿúûÿûýÿúûÿùûÿüûþýúöôîžÊÁT[¢UJVe¯®ëïîÿûúÿüûÿþûÿþûÿýûýûøææÛ}S XZ_Ng§ÏÂÈþèÜþØÓÿîâÿ÷òÿúúÿùûþûú÷óñ»º¹\ _aH¢¡FI¬±ïêÚþñàÿõÚÿöêÿüúÿþýÿýýÿüýÿýüýúøèÖÕM¡WKbK^¢ ÑÛüùúÿýüÿýûÿþþÿýýÿüüþùøìäÚ¬¯?37ROS€Ë»úóìÿüúÿýüÿûûþøøýòìúèØåÕÄW¡U}HQGŠ£I©ªËÜìôôÿþüÿþûÿþýÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿþôòþôòþôòþóòÿ÷õþ÷ôþõôÿõôÿõôþôóþôóýôòøíêÕÇŸr£YSZS io€¡ÁÕÑùõòþöôÿø÷ÿùùÿùøÿù÷ÿù÷þøøþøøÿúøÿúøÿú÷ÿûúÿúúÿúúÿúùÿúùÿúúþùùùóìËÔŸcX VUkX °Žîîëÿùùÿúúÿûúÿúúÿúúþùøôí䯻§ZGVJR^ŸÌññòÿúúÿûüÿüýÿúûÿúúÿûúþú÷òå߀¶®PVPELZÈÀöõôÿûûÿûûÿûûÿþüÿþýýõòÜÉÊtš^R RGTRÝ̮۵€ÑÖÃðìçÿùøÿúüþúûöôò±ÈÃ`H[EUM|ÈÍ¢âħÙÐÛÃÅÿòóÿÿþÿþþÿþþÿþýýûøÞÜÛzZiS€bC§n£œÙÝþúúÿþýÿþýÿþþÿþþÿýýýúöãÛÈQ\ ?¢1E a²í·ŸþñâÿòóÿïñþÛß÷ØÇÛ§oC¡K3¡MG€£uµ·Éêîÿþûÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþôòþôñþôòþôóÿ÷öÿ÷öÿ÷õÿöôÿõôþôóþôóýôòôêçÄ»·aSNZYnsµ¶Óãàú÷ôÿø÷ÿùøÿúøÿúøÿù÷ÿùøþùøþøøÿúøÿúøÿúùÿûúÿúùÿúùÿúùÿûùÿùøþ÷öóçà·¶¬\\hYla£ ËÆöôñÿúúÿûúÿúúÿûûÿûûþ÷öëßÚ¹¡\JKBL^€£ŽÍÞúö÷ÿûûÿýüÿûûÿúúÿúúþúùýõóéÜÑ©€OXMKP e¡¥·×Óý÷÷ÿýüÿýüÿýüÿýüÿûûýôòÕÆÊjRM WZ`Dg~ ¡®³ÐÝ×ÿúøÿûüþúûóñð¥ÃÂa=fASFMg v©©¶ñíìÿÿþÿÿþÿþýÿüûüúöÎßÑkQš¡LNbQ¥£©ÖæëÿýþÿþýÿýüÿýýÿþýÿýüüùõÑÝÅdAXD S| 1PS¢ŠÉÀ·Û¹áœŒÍ€µ®šS¢ WEX>¢QQ¯Å ׿úýüÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿöóÿõóÿõóÿöôÿ÷õÿ÷õÿ÷ôÿöôÿöõÿ÷ôþöóýõòðé篎¶^PS^[m}žÀàééüùöÿùùÿùøÿúøÿúøÿûøÿûúÿúùÿúùÿúùÿùùÿúùÿúúÿûùÿûùÿûúÿúùÿù÷þ÷ôîâÚ€ _ad\bm¡®·ÙÚüøõÿúúÿüûÿüüÿýýþüüüõóâÑÐy®^PJPKkµ²ËÞêþùúÿüûÿýüÿûûÿúûÿúúþûùýõðÞÖÉn M¢`[RTr«ÎààÿúúÿþþÿþýÿþýÿýûþûúüóðÖÄÇjVHIcNNZY_hª§¹ÖËÿú÷ÿüüþûûôðî¥ÄÁaIaSgYcN£ST¢äÞßÿýýÿüýÿûüþúùøíè·ÃŽc^`]hN€ŠŸ³ìòòÿþÿÿþþÿýüÿûýÿþýþýüûìçÁ³p hWF30A^egn hQ£PU`kaK?¡¡Lº§ÏÝêöøÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöôÿöôÿöôÿöôÿöôÿ÷õÿ÷ôÿ÷öÿø÷ÿùöþøõýôòêÜߎ·fQ`QRf»Ííððýøöÿùøÿùøÿúùÿúøÿûøÿûùÿúùÿúùÿùùÿùùÿûùÿûúÿüúÿûùÿûúÿúùÿúøýøôèä×^£XYdbtµÎàèþúùÿûûÿýüÿýýÿýüþüûûôòÒÈÈq©W\OZVµžàìñÿúüÿýüÿýýÿüüÿüûÿûúþúùûöïÎØÀaU jbWQ {£ºâêíÿýýÿþþÿýýÿüúÿûúþúùüõñÝÖÓsG OJdTªM H¡PSlšÏÁÿúóÿýýþüüùõóµÁÁh c e¡^Y XTd`bs«šÒØÓÿúøÿüûÿûüþøõðÙÓ¡¥O£OC[`iŠÊÉúú÷ÿþþÿþýÿýýÿûýÿýþþüüôäß§£Yb K`KZQO9¢GG€M~N`C£NS«? ;gº ÎÝÝòõÿþýÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþöóÿöóÿöóÿöóÿöóÿöõÿ÷öÿøöÿù÷ÿøöþ÷õüòñàÏÖµfLhFQdšÄÖöóòý÷öÿù÷ÿùøÿûùÿûùÿûøÿûøÿùùÿùùÿùùÿûúÿûùÿúùÿüúÿûùÿúúÿúúÿüúýùöÚåØxZa[£ka¢}¥¿áêðÿüüÿüüÿþüÿýýÿýüþûûúöõÂÎÐnR[DTWŠš¿Âòõõÿûýÿýýÿþþÿýýÿûüÿüûþùù÷îé¶À¶a^TN \]¥ÀÒñõöÿþýÿýþÿýýÿüúÿýüÿýûýüøêçá£@ŠS@]X¡]N¥`UŠ¡g£Âœù÷óÿýýþüüüøõÉÖÐa°RHebiP€dI§Rf«²ÆÌÎÿú÷ÿýûÿüûþûöèáÒ~Q` @ bJšcš©ÐØýùøÿûûÿûúÿûýÿüýÿýýþúûîæáNi~NX?£[Xm~AM 5£OE§`PicŠW€I¹šÅØÝò÷ÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþõòÿöóÿ÷óÿöóÿöóÿöôÿöõÿøöÿùöÿ÷õþöõûóòÚÞâtœÉg«³U©±f©Sš\ªµmžŸÄÚäûöôÿù÷ÿúøÿúùÿüùÿûùÿûùÿûùÿúùÿùøÿúùÿúùÿúøÿúùÿýúÿüúÿûúÿûúÿüúýûøÔëäk±µ]£²m¥[®Žk²^·»ÈÖñõöÿüûÿýúÿýûÿýýÿýýþüüùùø¶ÖÝk ±V¬¶`š®TžœP³¹X»Â¥ÏÖûùøÿýýÿþýÿþþÿýýÿüüÿûúþúùôðì¥ÅÆ_޶NŽŽK¯·J©³]§°i¯°¥Õâûûúÿþýÿþþÿýýÿüûÿûúÿÿýþþúùôò¿ÖÛVºÇ_UgC¢MN\ai§žÍôõöÿþýÿýýýüûèïïÍÒWšE¡fO¢WI^I`^µÃœ×âÿúúÿþýÿýüþüùáèß|°D³P²³9žŽLš®N«¬o€ÀÆÜîþûúÿûûÿüúÿýýÿýýÿûüþùùäèâxOQ?g L`4ŠŽQ«<©šYUq Yb;Eµ§Cœ³sÊךàëéööÿþýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþôòÿöôÿøôÿöóÿöóÿöôÿöôÿøöÿøöÿøöþøöüöóèíî©×àÐØÐ×Ð×ÕÖ¢ÙÜÝßãìïý÷õþù÷ÿú÷ÿúøÿú÷ÿú÷ÿûøÿüùÿûùÿùøÿúùÿùøÿúøÿûúÿýùÿûøÿýûÿýûÿýûýüùçõð ÕÜÏÙ ÓÛ×ÝŠÜÞ¡ÜáÇçíûúúÿüúÿýúÿüúÿûúÿûûþûûûúùÔéíŠÐÛ×Þ€ÙÜ€ÞâÞâ€ÞäÓéîþûûÿþþÿþþÿÿþÿþþÿýüÿüûþûúúøöÏèè€ßáÝàÚÞÑÛ¡ÕÜšÙÞÓìðþýüÿþýÿþþÿþýÿýûÿýûÿþýÿþüýúùïö÷¯áæÁÈbŽŒXެE©²C²J©žc²¹n·ÂÉÕÅàìüûûÿþþÿþþþýýúúùÖíðÉÒX»ÂN®¹Uг[ ±Y£·]°µV·ÀtÀÇÔáßîõÿþýÿÿþÿþüþüùíöô§ØâÓÝÕÝÖàÖÝÑÝ¢ÓåçñøÿûûÿüüÿýûÿýýÿýýþûüüòòÕÆÐgO\JY¢AWµ©¢ØÚÎÒUŽÂjª©Qš«M·«@Œ±DºžG¿¿mÎÑ×âÎìóûÿýÿÿýÿÿýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþôòÿöôÿøôÿõóÿöóÿöôÿøõÿøöÿøöÿøöÿøöþøõûöôïòòíóñëòðêñðêóòíôòðöóùöõü÷öþøõþøõÿø÷ÿøöÿùöÿú÷ÿüùÿûùÿúøÿúøÿùøÿûùÿüúÿüùÿùøÿýúÿüúÿüúþüúûüøêóõèòóéôôêõöìõöíø÷öúùÿýüÿýûÿýûÿüúÿûúÿûûÿûüþüû÷ù÷ëõõêõõëõõì÷÷íùùîøø÷úùÿüûÿüüÿþþÿþþÿÿþÿþýÿþýÿþüþýûöûùìø÷ëø÷ì÷÷èôöëõöë÷÷õøùÿþýÿþþÿþþÿÿýÿþüÿþüÿþýÿþýþþüýýüñø÷Öíí»ãæšÞàÔßÒà ×ä·àèÊçíæòóöúúÿþýÿþþÿþþÿþþþþýùüûâñïÂçë®àèÓáÑá Øå¯àçÂéîØðïêööúüýÿÿþÿÿþÿþýþþýýþüóúùðøöêõõð÷øòù÷ïø÷óøøüüüÿüýÿýýÿýýÿýýÿýýþüüøê廣«F FH bRWuŒ²äðîëôóÌëð«áéÞèÚæØé¬ãíŸéñÚóöùýûÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöôÿ÷ôÿøôÿ÷ôÿ÷ôÿ÷ôÿøöÿøöÿøöÿøöÿøöÿù÷þøöþùõþùôýøõý÷ôþùöÿûöÿú÷ÿúøþú÷þøõþøôÿø÷ÿø÷ÿú÷ÿú÷ÿûøÿúøÿúøÿùøÿùøÿúøÿüúþüùþùøÿûúÿüúÿüúÿýûÿýúþûúþûúÿüûÿýüÿýüÿþüÿþýÿþýÿýûÿûùÿýüÿýüÿýüÿýþÿþýþþüþüûÿüúÿûúÿûüÿÿýÿþýÿýüÿüüÿûüÿþþÿþÿÿþþÿþþÿþþÿÿýÿÿýÿþýÿþüÿþýþþýþþüÿþýþýýþýýÿþýÿþþÿþþÿýýÿþüÿþüÿþþÿÿþÿÿþÿþýþüûûüúõøøðø÷êöøéöøî÷øóùúùûûýýüÿþüÿþýÿÿþÿÿþÿÿÿÿÿþþþþüýü÷üûôúúî÷øí÷øðùùôúúøûúûûúþþýÿþþÿÿþÿÿþÿÿþÿÿþÿÿþþþþþþþýþþþþþþýýþýýþþýÿþýÿýþÿþþÿþþÿþþÿþýþüüõí䥣£LozS]=¡T£ÄÆøù÷þýüýþýüþýûþýúþüúþüýþüþþýþþýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöôÿ÷ôÿùõÿøõÿøôÿøôÿùöÿøöÿøöÿùöÿùöÿù÷ÿù÷ÿûöÿûöÿû÷ÿú÷ÿûøÿüøÿûøÿú÷ÿú÷ÿú÷ÿøöÿù÷ÿúøÿú÷ÿùöÿù÷ÿùøÿùøÿùøÿùøÿû÷ÿûùþüùþúøÿúúÿýûÿýûÿýüÿþûÿýüÿýüÿþýÿÿýÿÿþÿþýÿþüÿþûÿýûÿüûÿþýÿþýÿþýÿþýÿÿýÿÿýÿþýÿýûÿüúÿüüÿÿþÿÿýÿþýÿýýÿýýÿþýÿþþÿþýÿþýÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿýÿÿþÿþýÿþþÿÿþÿþýÿþýÿýýÿþüÿþüÿþýÿýüÿþüÿþüÿýüÿþüÿýüÿþüÿþýÿþýÿþýÿþýÿþýÿþþÿþýÿþýÿþþÿýýÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿþýÿþþÿþýÿþýÿþýÿýüÿýüÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿþýÿþýÿþþÿþþÿþþÿþþþüúîçÐCVENSc£©Æ×þüúÿþüÿÿþÿÿþþÿþþÿþþÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷óÿ÷ôÿùõÿøõÿøõÿøöÿøöÿùöÿúöÿùöÿùöÿøöÿù÷ÿûøÿûøÿú÷ÿú÷ÿú÷ÿû÷ÿû÷ÿúøÿúøÿù÷ÿøöÿûùÿýùÿúøÿøõÿùöÿùøÿûùÿûùÿúøÿû÷ÿûùÿüúÿüúÿüúÿþûÿýüÿýûÿýûÿýûÿýûÿþûÿÿýÿÿþÿÿýÿþüÿþüÿýûÿþüÿþýÿþüÿþýÿþýÿþýÿÿýÿÿýÿþýÿþüÿþýÿÿþÿÿýÿÿþÿþþÿþýÿþýÿþþÿþýÿþýÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿþÿÿþÿþýÿþýÿþýÿþýÿÿýÿþþÿþýÿþýÿþýÿþýÿþýÿþýÿÿýÿÿþÿÿþÿþþÿþþÿÿýÿÿþÿÿþÿÿþÿþþÿþýÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿþÿþýÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿýþÿýþÿþþþþþýøóÞÛÃr] gVW¢YZ¶ÄËáíÿþýÿþýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷óþõóÿùôÿùõÿúöÿùöÿøöÿùöÿøõÿøõÿù÷ÿøõÿøõÿú÷ÿú÷ÿú÷ÿùöÿùöÿúöÿûöÿúøþúøþø÷ÿøöÿýúÿüùÿúøÿùöÿûøÿúùÿýûÿüúÿûùÿûøÿýúÿýûÿýûÿüûÿýûÿýüÿýûÿýûÿýûÿýûÿþüÿÿþÿÿþÿÿýÿÿýÿþýÿýûÿþüÿþüÿþüÿþüÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿÿþÿÿþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿýÿÿþÿÿþÿþýÿýûÿýûÿÿýÿÿýÿÿÿÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿþþÿþýþýýýïêС\^}S€L P€hlœÍáð÷ÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿýÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøóþõóÿøôÿøõÿùöÿùöÿùöÿøöÿ÷õÿøõÿø÷ÿ÷õÿ÷õÿúöÿú÷ÿú÷ÿû÷þøöþ÷ôÿùöÿùøþúøþø÷ÿúøÿûøÿú÷ÿúùÿúøÿúùÿúúÿüúÿûúÿûùÿûùÿýúÿýûÿýûÿüûÿýûÿþýÿþûÿþûÿþüÿýúÿþýÿÿþÿÿþÿÿþÿþýÿýüÿýüÿþüÿþüÿþûÿýûÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿýÿÿþÿÿþÿÿÿÿÿþÿþþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿýÿÿþÿÿþÿÿþÿÿþÿÿýÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿþþÿþýÿÿþÿþþÿýþÿþþÿþþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿþþÿýüÿýüÿÿýÿÿþÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿþýÿýüÿýüÿÿýÿÿýÿÿÿÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿþýÿþûþýýüõñ¹¶¯LjRnI¥£\~ÂÚòøúÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ôÿ÷óÿøôÿøôÿùöÿùöÿøöÿøöÿùöÿù÷ÿøöÿ÷õÿ÷õÿúöÿûøÿûøÿûöþøõþöóÿùõÿù÷þú÷þøøÿûøÿù÷ÿøöÿù÷þùöþøöÿûùÿúùÿúùÿúúÿýúÿýúÿýúÿýúÿýûÿýûÿþüÿþüÿþûÿþüÿýûÿýüÿÿýÿÿýÿÿýÿþüÿüúÿýúÿýûÿýüÿýûÿþüÿþýÿýüÿýüÿÿýÿÿýÿÿþÿÿþÿÿýÿÿýÿÿýÿþýÿþþÿÿþÿþþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿýÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿþýÿþýÿÿÿÿÿÿÿþþÿþýÿÿþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿþÿÿþÿþþÿþÿÿÿÿÿþþÿýüÿþüÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿþþÿþýÿÿýÿÿþÿÿþÿÿÿÿÿþÿÿþÿþþÿþþÿÿÿÿÿÿÿþþÿüýÿüüÿþüþýüõòî§ŠŠKcO¥U I¡j¡¿Öüüüÿÿýÿÿýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþöóÿöòÿøóÿøôÿùöÿù÷ÿøöÿøöÿú÷ÿúöÿúöÿøöÿøöÿúöÿû÷ÿû÷ÿúöþù÷þøôÿøôþù÷þùöþø÷ÿúøÿúøÿù÷ÿøöþøõþ÷õÿøøþùøþùøÿúùÿüùÿüùÿýúÿüúÿûùÿûùÿüúÿýüÿýúÿýúÿýûÿýûÿÿüÿþûÿþüÿþüÿýûÿüúÿûúÿýüÿûúÿþýÿþüÿýûÿýûÿþûÿþûÿþýÿþþÿÿþÿþýÿýûÿþýÿþþÿÿþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿýÿþþÿýýÿüýÿÿþÿÿýÿÿüÿþüÿþüÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿþÿþýÿýüÿþþÿÿÿÿÿþÿþþÿþþÿÿÿÿþþÿþþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿýÿÿþÿÿþÿÿþÿþþÿýýÿýýÿþþÿþþÿÿþÿþýÿüüÿýüÿþýþýüìîêx°¬SKW ZY¡Zª »Øãþýýÿÿýÿÿýÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþöòþõòÿ÷òÿøõÿùöÿú÷ÿú÷ÿùöÿùöÿùõÿúöÿú÷ÿùöÿùöÿú÷ÿú÷ÿú÷ÿûøÿùõþöôþø÷þù÷þù÷ÿúøÿûùÿûùÿúùÿù÷þ÷õþ÷÷þùøþøøþøøÿúøÿúøÿüùÿýúÿûúÿûùÿùøÿûúÿýúÿþûÿþüÿþüÿþüÿþüÿþüÿþüÿþýÿýüÿûûÿþüÿüûÿýüÿþýÿþüÿýúÿýúÿýûÿýüÿþýÿþþÿÿýÿýüÿþýÿþþÿþþÿþýÿþýÿýýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿÿýÿÿþÿÿýÿÿýÿþþÿþýÿþýÿÿüÿÿüÿÿüÿþüÿþþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿýþÿþþÿÿþÿþýÿýýÿþþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿûûÿþýÿÿþÿÿþÿÿþÿÿþÿþþÿýýÿýýÿþþÿþþÿûûÿüüÿýýÿþýÿöòÛ²ÁecB€RJ£ _fŽ¡×êçþüüÿþþÿÿþÿÿþÿÿþÿþþÿþþÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøóþöóÿøóÿùôÿùöÿúøÿú÷ÿùöÿøöÿøôÿù÷ÿûùÿúøÿùõÿû÷ÿùøÿúøÿúøÿúöþùöþùøÿúùÿúøÿúøÿúùÿûøÿúùÿù÷þú÷þùøþøøþøøþøøÿùøÿúøÿúùÿüúÿýûÿýúÿúùÿüúÿþûÿþüÿþüÿþüÿþýÿþýÿþüÿþüÿþüÿþüÿýûÿýûÿýüÿþýÿþþÿýûÿûùÿüûÿýüÿýýÿþþÿþþÿüúÿýüÿþýÿþþÿþþÿþýÿþýÿýýÿýýÿþþÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿýÿþýÿþýÿÿýÿÿýÿþýÿüýÿþýÿÿüÿÿüÿÿýÿûûÿûûÿþýÿÿþÿÿýÿÿýÿÿþÿþþÿþþÿÿÿÿÿþÿþþÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿþÿþýÿþýÿþþÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿþýÿþýÿÿþÿÿÿÿþþÿþþÿþþÿÿýþøðÁ³¶E¢ŠPFf[¡iqž¹ìòòþýüÿþþÿÿüÿøóÿúùÿþýÿÿþÿÿÿÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷óÿøôÿøôÿ÷óÿøôÿù÷ÿú÷ÿùöÿøöÿøöÿù÷ÿûøÿúøÿùõÿúöÿ÷õÿùöÿù÷ÿù÷ÿú÷ÿú÷ÿúøþù÷þù÷ÿù÷ÿøöÿùøÿúøÿûùÿùùþøøýøøþøøÿùøÿùøÿúøÿüùÿüúÿüúÿûúÿûúÿüùÿýúÿýúÿýûÿþüÿþýÿþüÿþüÿþüÿþüÿûûÿüûÿýüÿþýÿþýÿýúÿúùÿüûÿûüÿþýÿüüÿüüÿüúÿþüÿþýÿþþÿüýÿþýÿþþÿþýÿþýÿþþÿÿþÿÿþÿÿþÿÿýÿÿýÿýüÿýüÿýýÿþýÿÿþÿÿþÿýýÿýýÿþýÿþûÿþýÿÿüÿýûÿýüÿþýÿþûÿþûÿÿüÿþýÿþþÿþÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿþûÿüúÿüúÿþýÿÿþÿÿþÿÿþÿþþÿþýÿýýÿýýÿþýÿþþÿþþÿþþÿÿÿÿýýÿýýÿþûùùê°±£il?ª¡;®©WžUž±ÉÎúø÷þþýÿÿþÿýùùëæýóõþþýÿÿþÿÿÿÿþþÿþþÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷óÿøôÿøóþõóþ÷óÿùöÿùöÿùöÿùöÿùõÿùõÿú÷ÿúøÿú÷ÿùöþõóþøõÿùöÿùöÿúöÿú÷ÿú÷þùöþùöÿùöÿ÷öÿø÷ÿù÷ÿù÷ÿùøþøøþ÷øþøøÿù÷ÿù÷ÿùøÿúøÿúùÿûúÿûúÿûúÿüùÿüùÿýûÿýüÿýüÿýûÿýûÿýüÿýüÿþúÿûúÿüûÿüúÿüûÿýûÿüúÿúùÿüúÿûúÿýüýùùþúùÿþüÿÿýÿþýÿýýÿüýÿþþÿýþÿýüÿýüÿþþÿÿÿÿÿþÿÿüÿþûÿþýÿþýÿþýÿþýÿþþÿÿþÿþýÿûûÿüûÿýûÿýûÿþüÿþûÿýûÿþýÿÿýÿþûÿþüÿÿüÿþýÿþþÿþÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýÿþûÿþüÿþýÿþýÿÿþÿÿþÿÿþÿþþÿþýÿýýÿýýÿþýÿþýÿþýÿþþÿþýÿûûÿüûÿýúóùéĵQ¶»TœÊUÅÖcÇÚÕÜÚâÑêñýûùþþýÿÿþÿýùþøóþø÷þþýÿÿþÿÿþÿÿýÿÿþÿÿþÿÿýÿÿýÿþþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿøóÿøôÿøóþõóþøôÿøõÿøõÿùöÿøõÿøôÿøõÿùöÿù÷ÿù÷ÿúöþøõþú÷ÿúøÿù÷ÿú÷ÿú÷þù÷þøöþù÷ÿùøÿù÷ÿù÷ÿøöþ÷öþööþõ÷þø÷þúøÿù÷ÿù÷ÿúøÿùøÿúùÿûúÿüûÿüûÿýúÿüúÿýûÿýûÿüûÿûûÿýûÿýüÿýüÿýúÿûúÿûúÿüúÿüúÿýûÿüûÿüûÿýûÿýûÿýüþûúþûúÿþýÿÿþÿþýÿýýÿýýÿþþÿþþÿýüÿýüÿþþÿÿþÿÿþÿÿýÿþýÿþýÿÿþÿÿþÿÿþÿÿþÿÿþÿþýÿýýÿýüÿýûÿýüÿþüÿþüÿþýÿþýÿÿþÿÿýÿÿýÿÿýÿþýÿþþÿÿÿÿÿÿÿþýÿþþÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿýûÿúúÿýüÿþýÿÿþÿýþÿþþÿÿþÿþþÿþýÿÿýÿÿýÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþýÿýýÿýýÿûúÿýüÿþýÿþþÿþýÿýýÿýýÿýúóúôØà¢ÞçŠàé»äðÙïõëööòøöûüûþýüÿþþÿþþÿýýÿþüÿýüÿþþÿÿÿÿÿþÿþýÿþýÿüûÿûûÿýýÿþþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿøôÿøõÿøóÿöóÿøôÿöõÿøõÿùöÿøôÿøôÿùõÿùöÿøöÿùöÿúöÿúöÿùöÿù÷ÿùöÿùöÿø÷þø÷ý÷öþ÷öþø÷ÿø÷ÿù÷ÿø÷þ÷öþõöþö÷þùøÿúùÿú÷ÿúøÿúøÿúøÿûùÿýúÿýúÿýûÿûùÿûùÿûúÿüûÿüûÿúúÿýúÿýûÿüûÿüúÿúùÿúùÿüúÿýûÿûûÿýüÿþýÿþýÿýüÿþýÿþüÿýüÿþûÿýüÿüüÿýýÿýüÿþüÿþýÿþýÿþýÿþþÿþüÿþýÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿþþÿþûÿþýÿÿþÿþþÿþýÿþûÿýûÿþýÿÿþÿÿþÿÿþÿÿþÿÿýÿÿýÿþýÿþþÿÿÿÿÿþÿþýÿþþÿýýÿýýÿýýÿþýÿÿþÿÿþÿýüÿüùÿýüÿþýÿúúÿúúÿýýÿþýÿþýÿþþÿÿþÿÿþÿÿþÿÿÿÿÿþÿþýÿþþÿÿþÿþýÿþýÿûûÿúúÿýüÿýüÿýýÿþþÿþþÿþþÿþýýþýïùúòøøðõöôö÷ûûúýüûþýüþýüÿþýÿþþÿûüÿþýÿÿýÿþýÿþýÿþýÿþþÿþþÿþýÿýûÿýýÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ \ No newline at end of file -- 1.5.6.5
participants (1)
-
Guillaume Lazzara