+ 'direct' image filter support: apply filter on main rendering buffer

(TODO: better user-friendly names)
+ allow empty string e.g image-filters="" (why not?)
This commit is contained in:
Artem Pavlenko 2012-04-25 10:53:34 +01:00
parent c26ad5706e
commit f57d2c28f0
4 changed files with 58 additions and 11 deletions

View file

@ -55,6 +55,7 @@ private:
filter_mode_e filter_mode_;
// image_filters
std::vector<filter::filter_type> filters_;
std::vector<filter::filter_type> direct_filters_;
// comp-op
boost::optional<composite_mode_e> comp_op_;
// The rule_ptrs vectors are only valid for the scale_denom_validity_.
@ -76,14 +77,16 @@ public:
rule_ptrs const& get_else_rules(double scale_denom);
rule_ptrs const& get_also_rules(double scale_denom);
rules &get_rules_nonconst();
rules& get_rules_nonconst();
void set_filter_mode(filter_mode_e mode);
filter_mode_e get_filter_mode() const;
// filters
std::vector<filter::filter_type> const& image_filters() const;
std::vector<filter::filter_type> & image_filters();
std::vector<filter::filter_type> & image_filters();
std::vector<filter::filter_type> const& direct_image_filters() const;
std::vector<filter::filter_type> & direct_image_filters();
// compositing
void set_comp_op(composite_mode_e comp_op);
boost::optional<composite_mode_e> comp_op() const;

View file

@ -252,6 +252,14 @@ void agg_renderer<T>::end_style_processing(feature_type_style const& st)
{
composite(pixmap_.data(),current_buffer_->data(), src_over,false,false);
}
// apply any 'direct' image filters
mapnik::filter::filter_visitor<image_32> visitor(pixmap_);
BOOST_FOREACH(mapnik::filter::filter_type filter_tag, st.direct_image_filters())
{
boost::apply_visitor(visitor, filter_tag);
}
#ifdef MAPNIK_DEBUG
std::clog << "end style processing\n";
#endif

View file

@ -37,12 +37,14 @@ IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings )
feature_type_style::feature_type_style()
: filter_mode_(FILTER_ALL),
filters_(),
direct_filters_(),
scale_denom_validity_(-1)
{}
feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy)
: filter_mode_(rhs.filter_mode_),
filters_(rhs.filters_),
direct_filters_(rhs.direct_filters_),
comp_op_(rhs.comp_op_),
scale_denom_validity_(-1)
{
@ -62,6 +64,7 @@ feature_type_style& feature_type_style::operator=(feature_type_style const& rhs)
if (this == &rhs) return *this;
rules_=rhs.rules_;
filters_ = rhs.filters_;
direct_filters_ = rhs.direct_filters_;
comp_op_ = rhs.comp_op_;
scale_denom_validity_ = -1;
return *this;
@ -78,7 +81,7 @@ rules const& feature_type_style::get_rules() const
return rules_;
}
rules &feature_type_style::get_rules_nonconst()
rules& feature_type_style::get_rules_nonconst()
{
return rules_;
}
@ -103,6 +106,16 @@ std::vector<filter::filter_type> const& feature_type_style::image_filters() con
return filters_;
}
std::vector<filter::filter_type>& feature_type_style::direct_image_filters()
{
return direct_filters_;
}
std::vector<filter::filter_type> const& feature_type_style::direct_image_filters() const
{
return direct_filters_;
}
void feature_type_style::set_comp_op(composite_mode_e comp_op)
{
comp_op_ = comp_op;

View file

@ -430,22 +430,45 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
}
// image filters
mapnik::image_filter_grammar<std::string::const_iterator,
std::vector<mapnik::filter::filter_type> > filter_grammar;
optional<std::string> filters = sty.get_opt_attr<std::string>("image-filters");
if (filters)
{
std::string filter_mode = *filters;
if (filter_mode.empty())
{
throw config_error("failed to parse empty image-filter");
}
std::string::const_iterator itr = filter_mode.begin();
std::string::const_iterator end = filter_mode.end();
mapnik::image_filter_grammar<std::string::const_iterator,std::vector<mapnik::filter::filter_type> > g;
bool result = boost::spirit::qi::phrase_parse(itr,end, g, boost::spirit::qi::ascii::space, style.image_filters());
bool result = boost::spirit::qi::phrase_parse(itr,end,
filter_grammar,
boost::spirit::qi::ascii::space,
style.image_filters());
if (!result || itr!=end)
{
throw config_error("failed to parse image-filter: '" + std::string(itr,end) + "'");
throw config_error("failed to parse image-filters: '" + std::string(itr,end) + "'");
}
}
// direct image filters (applied directly on main image buffer
// TODO : consider creating a separate XML node e.g
// <ImageFilter name="myfilter" op="blur emboss"/>
//
optional<std::string> direct_filters = sty.get_opt_attr<std::string>("direct-image-filters");
if (direct_filters)
{
std::string filter_mode = *direct_filters;
std::string::const_iterator itr = filter_mode.begin();
std::string::const_iterator end = filter_mode.end();
bool result = boost::spirit::qi::phrase_parse(itr,end,
filter_grammar,
boost::spirit::qi::ascii::space,
style.direct_image_filters());
if (!result || itr!=end)
{
throw config_error("failed to parse direct-image-filters: '" + std::string(itr,end) + "'");
}
}