This commit is contained in:
artemp 2017-01-26 15:45:08 +01:00
parent 2ede054e93
commit d053bddb43
4 changed files with 74 additions and 7 deletions

View file

@ -38,6 +38,10 @@ using image_options_map = std::map<std::string, boost::optional<std::string> >;
inline std::string to_string(boost::optional<std::string> const& val) { return val ? *val : "<unitialised>";}
image_options_map parse_image_options(std::string const& options);
#if defined(HAVE_PNG)
int parse_png_filters(std::string const& str);
#endif
}
#endif // MAPNIK_IMAGE_OPTIONS_HPP

View file

@ -48,14 +48,17 @@ namespace mapnik {
struct png_options {
int colors;
int filters;
int compression;
int strategy;
int trans_mode;
double gamma;
bool paletted;
bool use_hextree;
png_options() :
colors(256),
filters(PNG_FILTER_NONE),
compression(Z_DEFAULT_COMPRESSION),
strategy(Z_DEFAULT_STRATEGY),
trans_mode(-1),
@ -97,7 +100,7 @@ void save_as_png(T1 & file,
mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
png_set_asm_flags(png_ptr, flags | mask);
#endif
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, opts.filters);
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
@ -271,7 +274,7 @@ void save_as_png(T & file, std::vector<mapnik::rgb> const& palette,
mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
png_set_asm_flags(png_ptr, flags | mask);
#endif
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, opts.filters);
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{

View file

@ -42,7 +42,7 @@ x3::rule<class key, std::string> const key("key");
x3::rule<class value, std::string> const value("value");
auto const key_def = char_("a-zA-Z_") > *char_("a-zA-Z_0-9\\.\\-");
auto const value_def = +char_("a-zA-Z_0-9\\.\\-");
auto const value_def = +char_("a-zA-Z_0-9\\.\\-|");
auto const key_value_def = key > -('=' > value);
auto const image_options_def = key_value % lit(':');
@ -55,17 +55,64 @@ BOOST_SPIRIT_DEFINE(image_options);
image_options_map parse_image_options(std::string const& str)
{
auto const begin = str.begin();
auto begin = str.begin();
auto const end = str.end();
using boost::spirit::x3::space;
using mapnik::grammar::image_options;
image_options_map options;
try
{
bool success = boost::spirit::x3::phrase_parse(begin, end, image_options, space, options);
if (!success)
if (!success || begin != end)
{
throw std::runtime_error("Can't parse image options: " + str);
}
}
catch (boost::spirit::x3::expectation_failure<std::string> const& ex)
{
throw std::runtime_error("Can't parse image options: " + str + " " + ex.what());
}
return options; // RVO
}
#if defined(HAVE_PNG)
extern "C"
{
#include <png.h>
}
int parse_png_filters(std::string const& str)
{
auto begin = str.begin();
auto const end = str.end();
using boost::spirit::x3::space;
using boost::spirit::x3::symbols;
symbols<int> filter;
filter.add
("none", PNG_FILTER_NONE)
("sub", PNG_FILTER_SUB)
("up", PNG_FILTER_UP)
("avg", PNG_FILTER_AVG)
("paeth", PNG_FILTER_PAETH)
;
std::vector<int> opts;
try
{
bool success = boost::spirit::x3::phrase_parse(begin, end, filter % "|" , space , opts);
if (!success || begin != end)
{
throw std::runtime_error("Can't parse PNG filters: " + str);
}
}
catch (boost::spirit::x3::expectation_failure<std::string> const& ex)
{
throw std::runtime_error("Can't parse PNG filters: " + str + " " + ex.what());
}
int filters = 0;
std::for_each(opts.begin(), opts.end(), [&filters] (int f) { filters |= f;});
return filters;
}
#endif
} // ns mapnik

View file

@ -154,6 +154,19 @@ void handle_png_options(std::string const& type,
throw image_writer_exception("invalid compression strategy parameter: " + *val);
}
}
else if (key == "f")
{
// filters = PNG_NO_FILTERS;
// filters = PNG_ALL_FILTERS;
// filters = PNG_FAST_FILTERS;
// filters = PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG | PNG_FILTER_PAETH;
if (!val) throw image_writer_exception("invalid filters parameter: <uninitialised>");
if (*val == "no") opts.filters = PNG_NO_FILTERS;
else if (*val == "all") opts.filters = PNG_ALL_FILTERS;
else if (*val == "fast") opts.filters = PNG_FAST_FILTERS;
else opts.filters = parse_png_filters(*val); // none | sub | up | avg | paeth
}
else
{
throw image_writer_exception("unhandled png option: " + key);