+ '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:
parent
c26ad5706e
commit
f57d2c28f0
4 changed files with 58 additions and 11 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue