add support for PNG filters (http://www.libpng.org/pub/png/libpng-manual.txt) ref #3479
This commit is contained in:
parent
2ede054e93
commit
d053bddb43
4 changed files with 74 additions and 7 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue