
* scribo/fun/v2v/highlight.hh, * scribo/io/img/internal/debug_img_visitor.hh, * scribo/io/img/internal/draw_edges.hh, * scribo/io/img/internal/full_img_visitor.hh, * scribo/io/img/internal/non_text_img_visitor.hh, * scribo/io/img/internal/text_img_visitor.hh, * scribo/io/img/save.hh: New. --- scribo/ChangeLog | 12 + .../serializable.hh => fun/v2v/highlight.hh} | 57 +++-- scribo/scribo/io/img/internal/debug_img_visitor.hh | 263 ++++++++++++++++++++ .../internal/draw_edges.hh} | 62 +++--- scribo/scribo/io/img/internal/full_img_visitor.hh | 194 ++++++++++++++ .../scribo/io/img/internal/non_text_img_visitor.hh | 162 ++++++++++++ scribo/scribo/io/img/internal/text_img_visitor.hh | 164 ++++++++++++ scribo/scribo/io/img/save.hh | 242 ++++++++++++++++++ 8 files changed, 1104 insertions(+), 52 deletions(-) copy scribo/scribo/{core/concept/serializable.hh => fun/v2v/highlight.hh} (66%) create mode 100644 scribo/scribo/io/img/internal/debug_img_visitor.hh copy scribo/scribo/io/{xml/internal/print_box_coords.hh => img/internal/draw_edges.hh} (56%) create mode 100644 scribo/scribo/io/img/internal/full_img_visitor.hh create mode 100644 scribo/scribo/io/img/internal/non_text_img_visitor.hh create mode 100644 scribo/scribo/io/img/internal/text_img_visitor.hh create mode 100644 scribo/scribo/io/img/save.hh diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 5b96508..43041fe 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,17 @@ 2011-03-14 Guillaume Lazzara <z@lrde.epita.fr> + Introduce result image output. + + * scribo/fun/v2v/highlight.hh, + * scribo/io/img/internal/debug_img_visitor.hh, + * scribo/io/img/internal/draw_edges.hh, + * scribo/io/img/internal/full_img_visitor.hh, + * scribo/io/img/internal/non_text_img_visitor.hh, + * scribo/io/img/internal/text_img_visitor.hh, + * scribo/io/img/save.hh: New. + +2011-03-14 Guillaume Lazzara <z@lrde.epita.fr> + Save image edge coordinates in XML output. * scribo/io/xml/internal/extended_page_xml_visitor.hh: Here. diff --git a/scribo/scribo/core/concept/serializable.hh b/scribo/scribo/fun/v2v/highlight.hh similarity index 66% copy from scribo/scribo/core/concept/serializable.hh copy to scribo/scribo/fun/v2v/highlight.hh index 6e661a6..835be59 100644 --- a/scribo/scribo/core/concept/serializable.hh +++ b/scribo/scribo/fun/v2v/highlight.hh @@ -23,42 +23,55 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License. -#ifndef SCRIBO_CORE_CONCEPT_SERIALIZABLE_HH -# define SCRIBO_CORE_CONCEPT_SERIALIZABLE_HH +#ifndef SCRIBO_FUN_V2V_HIGHLIGHT_HH +# define SCRIBO_FUN_V2V_HIGHLIGHT_HH -/// \file -/// -/// Concept for serializer visitors. +/// \brief Function increasing values to highlight areas. -# include <mln/core/concept/object.hh> -# include <scribo/core/concept/serialize_visitor.hh> +# include <mln/core/concept/function.hh> namespace scribo { - /// \brief Link functor concept. - template <typename E> - class Serializable : public mln::Object<E> + namespace fun { - public: - template <typename E2> - void accept(const SerializeVisitor<E2>& visitor) const; - }; + + namespace v2v + { + + template <typename R> + struct highlight + : mln::Function_v2v<highlight<R> > + { + typedef R result; + + highlight(); + result operator()(const result& v) const; + }; # ifndef MLN_INCLUDE_ONLY - template <typename E> - template <typename E2> - void - Serializable<E>::accept(const SerializeVisitor<E2>& visitor) const - { - exact(visitor).visit(exact(*this)); - } + + template <typename R> + highlight<R>::highlight() + { + } + + + template <typename R> + typename highlight<R>::result + highlight<R>::operator()(const result& v) const + { + return v + v / 2; + } # endif // ! MLN_INCLUDE_ONLY + } // end of namespace scribo::fun::v2v + + } // end of namespace scribo::fun } // end of namespace scribo -#endif // SCRIBO_CORE_CONCEPT_SERIALIZABLE_HH +#endif // ! SCRIBO_FUN_V2V_HIGHLIGHT_HH diff --git a/scribo/scribo/io/img/internal/debug_img_visitor.hh b/scribo/scribo/io/img/internal/debug_img_visitor.hh new file mode 100644 index 0000000..f1c689d --- /dev/null +++ b/scribo/scribo/io/img/internal/debug_img_visitor.hh @@ -0,0 +1,263 @@ +// 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_IO_IMG_INTERNAL_DEBUG_IMG_VISITOR_HH +# define SCRIBO_IO_IMG_INTERNAL_DEBUG_IMG_VISITOR_HH + +/// \file +/// +/// Save document image analysis to a small image. + +# include <fstream> + +# include <mln/core/image/image2d.hh> +# include <mln/value/rgb8.hh> +# include <mln/draw/box.hh> +# include <mln/subsampling/antialiased.hh> +# include <mln/morpho/elementary/gradient_external.hh> + +# include <scribo/core/internal/doc_serializer.hh> +# include <scribo/core/document.hh> +# include <scribo/core/paragraph_set.hh> +# include <scribo/core/line_info.hh> + +# include <scribo/io/img/internal/draw_edges.hh> + +namespace scribo +{ + + namespace io + { + + namespace img + { + + namespace internal + { + + + class debug_img_visitor : public doc_serializer<debug_img_visitor> + { + public: + // Constructor + debug_img_visitor(mln::image2d<value::rgb8>& out, + unsigned output_ratio); + + // Visit overloads + template <typename L> + void visit(const document<L>& doc) const; + + void visit(const component_info& info) const; + + template <typename L> + void visit(const paragraph_set<L>& parset) const; + + template <typename L> + void visit(const line_info<L>& line) const; + + private: // Attributes + mln::image2d<value::rgb8>& output; + unsigned output_ratio; + + mutable image2d<scribo::def::lbl_type> elt_edge; + + + private: // Methods + box2d compute_bbox(const box2d& b) const; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + + inline + box2d + debug_img_visitor::compute_bbox(const box2d& b) const + { + point2d + pmin = b.pmin() / output_ratio, + pmax = b.pmax() / output_ratio; + + return box2d(pmin, pmax); + } + + + inline + debug_img_visitor::debug_img_visitor(mln::image2d<value::rgb8>& out, + unsigned output_ratio) + : output(out), output_ratio(output_ratio) + { + mln_assertion(output.is_valid()); + } + + + /// Document + // + template <typename L> + void + debug_img_visitor::visit(const document<L>& doc) const + { + // Text + if (doc.has_text()) + doc.paragraphs().accept(*this); + + // Page elements (Pictures, ...) + if (doc.has_elements()) + { + // Prepare element edges + + // FIXME: UGLY! Too slow! + scribo::def::lbl_type nlabels; + component_set<L> elts = primitive::extract::components( + data::convert(bool(), mln::subsampling::antialiased(doc.elements().labeled_image(), + output_ratio)), + c8(), + nlabels); + + // Preserving elements tags + if (doc.elements().nelements() != elts.nelements()) + { + std::cerr << "Warnig: could not preserve element type in " + << "img debug output." << std::endl; + std::cerr << "The number of non text element has changed while " + << "subsampling images : " + << doc.elements().nelements() << " vs " + << elts.nelements() << std::endl; + } + else + for_all_comps(c, doc.elements()) + elts(c).update_type(doc.elements()(c).type()); + + elt_edge = morpho::elementary::gradient_external(elts.labeled_image(), c8()); + +// const component_set<L>& elts = doc.elements(); + for_all_comps(e, elts) + if (elts(e).is_valid()) + elts(e).accept(*this); + } + + + // line seraparators + if (doc.has_vline_seps()) + for_all_comps(c, doc.vline_seps_comps()) + doc.vline_seps_comps()(c).accept(*this); + if (doc.has_hline_seps()) + for_all_comps(c, doc.hline_seps_comps()) + doc.hline_seps_comps()(c).accept(*this); + + } + + + /// Component_info + // + inline + void + debug_img_visitor::visit(const component_info& info) const + { + switch (info.type()) + { + case component::LineSeparator: + { + mln::draw::box(output, compute_bbox(info.bbox()), + literal::cyan); + } + break; + + + default: + case component::Image: + { + // The bbox does not need to be reajusted to the + // subsampled domain since it has been recomputed while + // computing the edge image. + // + // However, the bbox must be enlarged since only the + // _external_ edge is computed. + box2d b = info.bbox(); + b.enlarge(1); + b.crop_wrt(output.domain()); + data::fill(((output | b).rw() + | (pw::value(elt_edge) + == pw::cst((scribo::def::lbl_type)info.id().to_equiv()))).rw(), + literal::orange); + } + break; + } + } + + /// Paragraph Set + // + template <typename L> + void + debug_img_visitor::visit(const paragraph_set<L>& parset) const + { + const line_set<L>& lines = parset.lines(); + + 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); + lines(l).accept(*this); + } + + box2d b = compute_bbox(parset(p).bbox()); + b.enlarge(1); + b.crop_wrt(output.domain()); + mln::draw::box(output, b, literal::blue); + } + } + + + template <typename L> + void + debug_img_visitor::visit(const line_info<L>& line) const + { + point2d + pmin = line.bbox().pmin(), + pmax = line.bbox().pmax(); + pmax.row() = line.baseline(); + pmin.row() = line.baseline(); + + pmin = pmin / output_ratio; + pmax = pmax / output_ratio; + + mln::draw::line(output, pmin, pmax, literal::red); + } + +#endif // MLN_INCLUDE_ONLY + + } // end of namespace scribo::io::img::internal + + } // end of namespace scribo::io::img + + } // end of namespace scribo::io + +} // end of namespace scribo + +#endif // SCRIBO_IO_IMG_INTERNAL_DEBUG_IMG_VISITOR_HH diff --git a/scribo/scribo/io/xml/internal/print_box_coords.hh b/scribo/scribo/io/img/internal/draw_edges.hh similarity index 56% copy from scribo/scribo/io/xml/internal/print_box_coords.hh copy to scribo/scribo/io/img/internal/draw_edges.hh index ad84709..664a352 100644 --- a/scribo/scribo/io/xml/internal/print_box_coords.hh +++ b/scribo/scribo/io/img/internal/draw_edges.hh @@ -23,15 +23,26 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License. -#ifndef SCRIBO_IO_XML_INTERNAL_PRINT_BOX_COORDS_HH -# define SCRIBO_IO_XML_INTERNAL_PRINT_BOX_COORDS_HH +#ifndef SCRIBO_IO_IMG_INTERNAL_DRAW_EDGES_HH +# define SCRIBO_IO_IMG_INTERNAL_DRAW_EDGES_HH /// \file /// -/// \brief Prints box2d coordinates to XML data. +/// \brief Draw object edges. # include <fstream> -# include <mln/core/alias/box2d.hh> +# include <mln/core/image/image2d.hh> +# include <mln/core/image/dmorph/image_if.hh> +# include <mln/pw/all.hh> +# include <mln/data/fill.hh> +# include <mln/data/convert.hh> +# include <mln/literal/colors.hh> +# include <mln/value/rgb8.hh> +# include <mln/morpho/elementary/gradient_external.hh> + +# include <scribo/core/component_info.hh> +# include <scribo/core/def/lbl_type.hh> + namespace scribo { @@ -39,7 +50,7 @@ namespace scribo namespace io { - namespace xml + namespace img { namespace internal @@ -47,11 +58,12 @@ namespace scribo using namespace mln; - /*! \brief Prints box2d coordinates to XML data. + /*! \brief Draw component edges. */ void - print_box_coords(std::ofstream& ostr, const box2d& b, - const char *space); + draw_edges(const component_info& info, + image2d<value::rgb8>& output, const value::rgb8& value, + const image2d<scribo::def::lbl_type>& edges); # ifndef MLN_INCLUDE_ONLY @@ -59,37 +71,27 @@ namespace scribo inline void - print_box_coords(std::ofstream& ostr, const box2d& b, - const char *space) + draw_edges(const component_info& info, + image2d<value::rgb8>& output, const value::rgb8& value, + const image2d<scribo::def::lbl_type>& edges) { - std::string sc = space; - std::string sp = sc + " "; - ostr << sc << "<coords>" << std::endl - << sp << "<point x=\"" << b.pmin().col() - << "\" y=\"" << b.pmin().row() << "\"/>" - << std::endl - << sp << "<point x=\"" << b.pmax().col() - << "\" y=\"" << b.pmin().row() << "\"/>" - << std::endl - << sp << "<point x=\"" << b.pmax().col() - << "\" y=\"" << b.pmax().row() << "\"/>" - << std::endl - << sp << "<point x=\"" << b.pmin().col() - << "\" y=\"" << b.pmax().row() << "\"/>" - << std::endl - << sc << "</coords>" << std::endl; - + box2d b = info.bbox(); + b.enlarge(1); + data::fill(((output | b).rw() + | (pw::value(edges) + == pw::cst((scribo::def::lbl_type)info.id().to_equiv()))).rw(), + value); } # endif // ! MLN_INCLUDE_ONLY - } // end of namespace scribo::io::xml::internal + } // end of namespace scribo::io::img::internal - } // end of namespace scribo::io::xml + } // end of namespace scribo::io::img } // end of namespace scribo::io } // end of namespace scribo -#endif // ! SCRIBO_IO_XML_INTERNAL_PRINT_BOX_COORDS_HH +#endif // ! SCRIBO_IO_IMG_INTERNAL_DRAW_EDGES_HH diff --git a/scribo/scribo/io/img/internal/full_img_visitor.hh b/scribo/scribo/io/img/internal/full_img_visitor.hh new file mode 100644 index 0000000..30987db --- /dev/null +++ b/scribo/scribo/io/img/internal/full_img_visitor.hh @@ -0,0 +1,194 @@ +// 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_IO_IMG_INTERNAL_FULL_IMG_VISITOR_HH +# define SCRIBO_IO_IMG_INTERNAL_FULL_IMG_VISITOR_HH + +/// \file +/// +/// Save document image analysis to an image. + +# include <fstream> + +# include <mln/core/image/image2d.hh> +# include <mln/value/rgb8.hh> +# include <mln/draw/box.hh> + +# include <scribo/core/internal/doc_serializer.hh> +# include <scribo/core/document.hh> +# include <scribo/core/paragraph_set.hh> +# include <scribo/core/line_info.hh> + +# include <scribo/io/img/internal/draw_edges.hh> + +namespace scribo +{ + + namespace io + { + + namespace img + { + + namespace internal + { + + + class full_img_visitor : public doc_serializer<full_img_visitor> + { + public: + // Constructor + full_img_visitor(mln::image2d<value::rgb8>& out); + + // Visit overloads + template <typename L> + void visit(const document<L>& doc) const; + + void visit(const component_info& info) const; + + template <typename L> + void visit(const paragraph_set<L>& parset) const; + + template <typename L> + void visit(const line_info<L>& line) const; + + private: // Attributes + mln::image2d<value::rgb8>& output; + + mutable image2d<scribo::def::lbl_type> elt_edge; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + + inline + full_img_visitor::full_img_visitor(mln::image2d<value::rgb8>& out) + : output(out) + { + mln_assertion(output.is_valid()); + } + + + /// Document + // + template <typename L> + void + full_img_visitor::visit(const document<L>& doc) const + { + // Text + if (doc.has_text()) + doc.paragraphs().accept(*this); + + // Page elements (Pictures, ...) + if (doc.has_elements()) + { + // Prepare element edges + elt_edge = morpho::elementary::gradient_external(doc.elements().labeled_image(), c8()); + + const component_set<L>& elts = doc.elements(); + for_all_comps(e, elts) + if (elts(e).is_valid()) + elts(e).accept(*this); + } + + + // line seraparators + if (doc.has_vline_seps()) + for_all_comps(c, doc.vline_seps_comps()) + doc.vline_seps_comps()(c).accept(*this); + if (doc.has_hline_seps()) + for_all_comps(c, doc.hline_seps_comps()) + doc.hline_seps_comps()(c).accept(*this); + + } + + + /// Component_info + // + inline + void + full_img_visitor::visit(const component_info& info) const + { + switch (info.type()) + { + case component::LineSeparator: + { + mln::draw::box(output, info.bbox(), literal::cyan); + } + break; + + + default: + case component::Image: + { + draw_edges(info, output, literal::orange, elt_edge); + } + break; + } + } + + /// Paragraph Set + // + template <typename L> + void + full_img_visitor::visit(const paragraph_set<L>& parset) const + { + const line_set<L>& lines = parset.lines(); + + 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); + lines(l).accept(*this); + } + + mln::draw::box(output, parset(p).bbox(), literal::blue); + } + } + + + template <typename L> + void + full_img_visitor::visit(const line_info<L>& line) const + { + mln::draw::box(output, line.bbox(), literal::red); + } + +#endif // MLN_INCLUDE_ONLY + + } // end of namespace scribo::io::img::internal + + } // end of namespace scribo::io::img + + } // end of namespace scribo::io + +} // end of namespace scribo + +#endif // SCRIBO_IO_IMG_INTERNAL_FULL_IMG_VISITOR_HH diff --git a/scribo/scribo/io/img/internal/non_text_img_visitor.hh b/scribo/scribo/io/img/internal/non_text_img_visitor.hh new file mode 100644 index 0000000..24b027e --- /dev/null +++ b/scribo/scribo/io/img/internal/non_text_img_visitor.hh @@ -0,0 +1,162 @@ +// 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_IO_IMG_INTERNAL_NON_TEXT_IMG_VISITOR_HH +# define SCRIBO_IO_IMG_INTERNAL_NON_TEXT_IMG_VISITOR_HH + +/// \file +/// +/// \brief Save non-text information as an image. + +# include <fstream> + + +# include <mln/core/image/image2d.hh> +# include <mln/value/rgb8.hh> +# include <mln/draw/box.hh> + +# include <scribo/core/internal/doc_serializer.hh> +# include <scribo/io/img/internal/draw_edges.hh> + +namespace scribo +{ + + namespace io + { + + namespace img + { + + namespace internal + { + + /*! \brief Save non-text information as an image. + */ + class non_text_img_visitor : public doc_serializer<non_text_img_visitor> + { + public: + // Constructor + non_text_img_visitor(mln::image2d<value::rgb8>& out); + + // Visit overloads + template <typename L> + void visit(const document<L>& doc) const; + + template <typename L> + void visit(const component_set<L>& comp_set) const; + + void visit(const component_info& info) const; + + private: // Attributes + mln::image2d<value::rgb8>& output; + + mutable image2d<scribo::def::lbl_type> elt_edge; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + + inline + non_text_img_visitor::non_text_img_visitor(mln::image2d<value::rgb8>& out) + : output(out) + { + mln_assertion(output.is_valid()); + } + + + + /// Document + // + template <typename L> + void + non_text_img_visitor::visit(const document<L>& doc) const + { + // Page elements (Pictures, ...) + if (doc.has_elements()) + { + // Prepare element edges + elt_edge = morpho::elementary::gradient_external(doc.elements().labeled_image(), c8()); + + doc.elements().accept(*this); + } + + // line seraparators + if (doc.has_hline_seps()) + doc.hline_seps_comps().accept(*this); + if (doc.has_vline_seps()) + doc.vline_seps_comps().accept(*this); + } + + + /// Component Set + // + template <typename L> + void + non_text_img_visitor::visit(const component_set<L>& comp_set) const + { + for_all_comps(c, comp_set) + if (comp_set(c).is_valid()) + comp_set(c).accept(*this); + } + + + /// Component_info + // + inline + void + non_text_img_visitor::visit(const component_info& info) const + { + switch (info.type()) + { + case component::LineSeparator: + { + mln::draw::box(output, info.bbox(), literal::cyan); + } + break; + + + default: + case component::Image: + { + draw_edges(info, output, literal::orange, elt_edge); + } + break; + } + } + + +#endif // MLN_INCLUDE_ONLY + + } // end of namespace scribo::io::img::internal + + } // end of namespace scribo::io::img + + } // end of namespace scribo::io + +} // end of namespace scribo + +#endif // SCRIBO_IO_IMG_INTERNAL_NON_TEXT_IMG_VISITOR_HH diff --git a/scribo/scribo/io/img/internal/text_img_visitor.hh b/scribo/scribo/io/img/internal/text_img_visitor.hh new file mode 100644 index 0000000..7629bf7 --- /dev/null +++ b/scribo/scribo/io/img/internal/text_img_visitor.hh @@ -0,0 +1,164 @@ +// 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_IO_IMG_INTERNAL_TEXT_IMG_VISITOR_HH +# define SCRIBO_IO_IMG_INTERNAL_TEXT_IMG_VISITOR_HH + +/// \file +/// +/// Image output with text related information. + +# include <fstream> + +# include <mln/core/image/image2d.hh> +# include <mln/value/rgb8.hh> +# include <mln/draw/box.hh> +# include <mln/literal/colors.hh> + +# include <scribo/core/internal/doc_serializer.hh> +# include <scribo/core/document.hh> +# include <scribo/core/component_set.hh> +# include <scribo/core/paragraph_set.hh> +# include <scribo/core/line_info.hh> + +namespace scribo +{ + + namespace io + { + + namespace img + { + + namespace internal + { + + + class text_img_visitor : public doc_serializer<text_img_visitor> + { + public: + // Constructor + text_img_visitor(mln::image2d<value::rgb8>&); + + // Visit overloads + template <typename L> + void visit(const document<L>& doc) const; + + template <typename L> + void visit(const component_set<L>& comp_set) const; + + template <typename L> + void visit(const paragraph_set<L>& parset) const; + + template <typename L> + void visit(const line_info<L>& line) const; + + private: // Attributes + mln::image2d<value::rgb8>& output; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + inline + text_img_visitor::text_img_visitor(mln::image2d<value::rgb8>& out) + : output(out) + { + mln_assertion(output.is_valid()); + } + + + + /// Document + // + template <typename L> + void + text_img_visitor::visit(const document<L>& doc) const + { + mln_precondition(doc.is_open()); + + // Prepare output image. + output = duplicate(doc.image()); + + + // Text + if (doc.has_text()) + doc.paragraphs().accept(*this); + } + + /// Component Set + // + template <typename L> + void + text_img_visitor::visit(const component_set<L>& comp_set) const + { + for_all_comps(c, comp_set) + if (comp_set(c).is_valid()) + comp_set(c).accept(*this); + } + + + /// Paragraph Set + // + template <typename L> + void + text_img_visitor::visit(const paragraph_set<L>& parset) const + { + const line_set<L>& lines = parset.lines(); + + 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); + lines(l).accept(*this); + } + + mln::draw::box(output, parset(p).bbox(), literal::blue); + } + } + + + template <typename L> + void + text_img_visitor::visit(const line_info<L>& line) const + { + mln::draw::box(output, line.bbox(), literal::red); + } + +#endif // MLN_INCLUDE_ONLY + + } // end of namespace scribo::io::img::internal + + } // end of namespace scribo::io::img + + } // end of namespace scribo::io + +} // end of namespace scribo + +#endif // SCRIBO_IO_IMG_INTERNAL_TEXT_IMG_VISITOR_HH diff --git a/scribo/scribo/io/img/save.hh b/scribo/scribo/io/img/save.hh new file mode 100644 index 0000000..56300d6 --- /dev/null +++ b/scribo/scribo/io/img/save.hh @@ -0,0 +1,242 @@ +// 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_IO_IMG_SAVE_HH +# define SCRIBO_IO_IMG_SAVE_HH + +/// \file +/// +/// \brief Save document information as an image. + +# include <libgen.h> +# include <fstream> +# include <sstream> + +# include <map> + +# include <mln/core/image/image2d.hh> +# include <mln/value/rgb8.hh> +# include <mln/io/magick/save.hh> +# include <mln/subsampling/antialiased.hh> +# include <mln/data/transform_inplace.hh> + +# include <scribo/core/document.hh> + +# include <scribo/io/img/internal/text_img_visitor.hh> +# include <scribo/io/img/internal/non_text_img_visitor.hh> +# include <scribo/io/img/internal/full_img_visitor.hh> +# include <scribo/io/img/internal/debug_img_visitor.hh> + + +namespace scribo +{ + + namespace io + { + + namespace img + { + + /*! \brief Supported image formats + + Text : Display text regions. + + NonText : Display non-text regions. + + Full : Text and non-text regions. + */ + enum Format + { + Text, + NonText, + Full, + DebugWoImage, + DebugWithImage, + }; + + + /*! \brief Save document information as an image + + */ + template <typename L> + void + save(const document<L>& doc, const std::string& output_name, + Format format); + + +# ifndef MLN_INCLUDE_ONLY + + + namespace internal + { + + struct highlight_mask + : Function_v2v<highlight_mask> + { + typedef value::rgb8 result; + + highlight_mask(float ratio) + : ratio(ratio) + { + } + + result operator()(const result& v) const + { + result out = v; + out.red() = std::min(out.red() * ratio, 255.f); + out.green() = std::min(out.green() * ratio, 255.f); + out.blue() = std::min(out.blue() * ratio, 255.f); + return out; + } + + float ratio; + }; + + + template <typename L> + mln::image2d<value::rgb8> + save_text(const document<L>& doc) + { + mln_precondition(doc.is_valid()); + mln::image2d<value::rgb8> output = duplicate(doc.image()); + scribo::io::img::internal::text_img_visitor f(output); + doc.accept(f); + return output; + } + + template <typename L> + mln::image2d<value::rgb8> + save_non_text(const document<L>& doc) + { + mln_precondition(doc.is_valid()); + mln::image2d<value::rgb8> output = duplicate(doc.image()); + scribo::io::img::internal::non_text_img_visitor f(output); + doc.accept(f); + return output; + } + + template <typename L> + mln::image2d<value::rgb8> + save_full(const document<L>& doc) + { + mln_precondition(doc.is_valid()); + mln::image2d<value::rgb8> output = duplicate(doc.image()); + scribo::io::img::internal::full_img_visitor f(output); + doc.accept(f); + return output; + } + + template <typename L> + mln::image2d<value::rgb8> + save_debug_without_image(const document<L>& doc) + { + mln_precondition(doc.is_valid()); + mln::image2d<value::rgb8> + output(box2d(doc.image().domain().pmin() / 4, + doc.image().domain().pmax() / 4)); + data::fill(output, literal::black); + scribo::io::img::internal::debug_img_visitor f(output, 4); + doc.accept(f); + return output; + } + + template <typename L> + mln::image2d<value::rgb8> + save_debug_with_image(const document<L>& doc) + { + mln_precondition(doc.is_valid()); + mln::image2d<value::rgb8> + output = mln::subsampling::antialiased(doc.image(), 4); + internal::highlight_mask highlight(0.5f); + data::transform_inplace(output, highlight); + scribo::io::img::internal::debug_img_visitor f(output, 4); + doc.accept(f); + return output; + } + + } // end of namespace scribo::io::img::internal + + + + // FACADE + + template <typename L> + void + save(const document<L>& doc, + const std::string& output_name, + Format format) + { + trace::entering("scribo::io::img::save"); + + mln_precondition(doc.is_open()); + + mln::image2d<value::rgb8> output; + + // Choose saving method. + switch (format) + { + case Text: + output = internal::save_text(doc); + break; + + case NonText: + output = internal::save_non_text(doc); + break; + + case Full: + output = internal::save_full(doc); + break; + + case DebugWoImage: + output = internal::save_debug_without_image(doc); + break; + + case DebugWithImage: + output = internal::save_debug_with_image(doc); + break; + + default: + trace::warning("scribo::io::img::save - " + "Invalid image format! Skip saving..."); + trace::exiting("scribo::io::img::save"); + return; + } + + mln::io::magick::save(output, output_name.c_str()); + + trace::exiting("scribo::io::img::save"); + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::io::img + + } // end of namespace scribo::io + +} // end of namespace scribo + + +#endif // ! SCRIBO_IO_IMG_SAVE_HH -- 1.5.6.5