diff --git a/CHANGELOG.md b/CHANGELOG.md index 561fe41c2..2d5a9a91e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Released ... Summary: TODO +- Added `color-to-alpha` `image-filter` to allow for applying alpha in proportion to color similiarity (#2023) + - Added Async support to PostGIS plugin - https://github.com/mapnik/mapnik/wiki/PostGIS-Async - Fixed alpha handling bug with `comp-op:dst-over` (#1995) @@ -307,9 +309,9 @@ Released Aug 23, 2012 - Improved logging/debugging system with release logs and file redirection (https://github.com/mapnik/mapnik/wiki/Runtime-Logging) (#937 and partially #986, #467) -- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161) +- GDAL: allow setting `nodata` value on the fly (will override value if `nodata` is set in data) (#1161) -- GDAL: respect nodata for paletted/colormapped images (#1160) +- GDAL: respect `nodata` for paletted/colormapped images (#1160) - PostGIS: Added a new option called `autodetect_key_field` (by default false) that if true will trigger autodetection of the table primary key allowing for feature.id() to represent @@ -446,7 +448,7 @@ Released September 26, 2011 cannot possibly be projected into the map srs or the user wishes to control map bounds without modifying the extents of each layer. -- Support for NODATA values with grey and rgb images in GDAL plugin (#727) +- Support for `nodata` values with grey and rgb images in GDAL plugin (#727) - Print warning if invalid XML property names are used (#110) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 4d41ea4a6..b871f8c10 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -406,6 +406,77 @@ void apply_filter(Src & src, agg_stack_blur const& op) agg::stack_blur_rgba32(pixf,op.rx,op.ry); } +inline double channel_delta(double source, double match) +{ + if (source > match) return (source - match) / (1.0 - match); + if (source < match) return (match - source) / match; + return (source - match); +} + +inline uint8_t apply_alpha_shift(double source, double match, double alpha) +{ + source = (((source - match) / alpha) + match) * alpha; + return static_cast(std::floor((source*255.0)+.5)); +} + +template +void apply_filter(Src & src, color_to_alpha const& op) +{ + using namespace boost::gil; + rgba8_view_t src_view = rgba8_view(src); + double cr = static_cast(op.color.red())/255.0; + double cg = static_cast(op.color.green())/255.0; + double cb = static_cast(op.color.blue())/255.0; + for (int y=0; y(r)/255.0; + double sg = static_cast(g)/255.0; + double sb = static_cast(b)/255.0; + double sa = static_cast(a)/255.0; + // demultiply + if (sa <= 0.0) + { + r = g = b = 0; + continue; + } + else + { + sr /= sa; + sg /= sa; + sb /= sa; + } + // get that maximum color difference + double xa = std::max(channel_delta(sr,cr),std::max(channel_delta(sg,cg),channel_delta(sb,cb))); + if (xa > 0) + { + // apply difference to each channel, returning premultiplied + // TODO - experiment with difference in hsl color space + r = apply_alpha_shift(sr,cr,xa); + g = apply_alpha_shift(sg,cg,xa); + b = apply_alpha_shift(sb,cb,xa); + // combine new alpha with original + xa *= sa; + a = static_cast(std::floor((xa*255.0)+.5)); + // all color values must be <= alpha + if (r>a) r=a; + if (g>a) g=a; + if (b>a) b=a; + } + else + { + r = g = b = a = 0; + } + } + } +} + template void apply_filter(Src & src, colorize_alpha const& op) { diff --git a/include/mapnik/image_filter_grammar.hpp b/include/mapnik/image_filter_grammar.hpp index 26156fbf1..18aa765f4 100644 --- a/include/mapnik/image_filter_grammar.hpp +++ b/include/mapnik/image_filter_grammar.hpp @@ -75,6 +75,7 @@ struct image_filter_grammar : css_color_grammar css_color_; qi::rule color_stop_offset; phoenix::function percent_offset; + qi::rule, void(ContType&), qi::ascii::space_type> color_to_alpha_filter; }; } diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index c3f0d54e9..9ff5ab516 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -59,6 +59,13 @@ struct agg_stack_blur unsigned ry; }; +struct color_to_alpha +{ + color_to_alpha(mapnik::color const& c) + : color(c) {} + mapnik::color color; +}; + struct scale_hsla { scale_hsla(double _h0, double _h1, @@ -132,7 +139,8 @@ typedef boost::variant filter_type; + filter::colorize_alpha, + filter::color_to_alpha> filter_type; inline std::ostream& operator<< (std::ostream& os, blur) { @@ -152,6 +160,12 @@ inline std::ostream& operator<< (std::ostream& os, agg_stack_blur const& filter) return os; } +inline std::ostream& operator<< (std::ostream& os, color_to_alpha const& filter) +{ + os << "color-to-alpha(" << filter.color << ')'; + return os; +} + inline std::ostream& operator<< (std::ostream& os, scale_hsla const& filter) { os << "hsla-transform(" << filter.h0 << 'x' << filter.h1 << ':' diff --git a/src/image_filter_grammar.cpp b/src/image_filter_grammar.cpp index a17191d14..033dc96d6 100644 --- a/src/image_filter_grammar.cpp +++ b/src/image_filter_grammar.cpp @@ -91,6 +91,8 @@ image_filter_grammar::image_filter_grammar() scale_hsla_filter(_val) | colorize_alpha_filter(_val) + | + color_to_alpha_filter(_val) ; agg_blur_filter = lit("agg-stack-blur")[_a = 1, _b = 1] @@ -122,6 +124,14 @@ image_filter_grammar::image_filter_grammar() | double_[at_c<1>(_r1) = _1] ; + + color_to_alpha_filter = lit("color-to-alpha") + >> lit('(') + >> css_color_[_a = _1] + >> lit(')') + [push_back(_r1,construct(_a))] + ; + no_args = -(lit('(') >> lit(')')); } diff --git a/tests/visual_tests/grids/raster-color-to-alpha1-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha1-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha1-512-512-1.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha2-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha2-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha2-512-512-1.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha3-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha3-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha3-512-512-1.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha4-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha4-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha4-512-512-1.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha5-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha5-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha5-512-512-1.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/images/raster-color-to-alpha1-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha1-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..1a0e0ac35 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha1-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha1-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha1-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..1a0e0ac35 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha1-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha2-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha2-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..c14a73108 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha2-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha2-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha2-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..c14a73108 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha2-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha3-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha3-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..c750b1f83 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha3-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha3-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha3-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..c750b1f83 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha3-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha4-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha4-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..1ec158dbc Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha4-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha4-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha4-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..1ec158dbc Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha4-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha5-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha5-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..b75988967 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha5-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha5-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha5-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..b75988967 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha5-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/styles/raster-color-to-alpha1.xml b/tests/visual_tests/styles/raster-color-to-alpha1.xml new file mode 100644 index 000000000..5a66751ef --- /dev/null +++ b/tests/visual_tests/styles/raster-color-to-alpha1.xml @@ -0,0 +1,19 @@ + + + + + style + + + ../../data/raster/nodata-edge.tif + gdal + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/raster-color-to-alpha2.xml b/tests/visual_tests/styles/raster-color-to-alpha2.xml new file mode 100644 index 000000000..cd0206ef4 --- /dev/null +++ b/tests/visual_tests/styles/raster-color-to-alpha2.xml @@ -0,0 +1,20 @@ + + + + + style + + + ../../data/raster/river_merc.tiff + gdal + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/raster-color-to-alpha3.xml b/tests/visual_tests/styles/raster-color-to-alpha3.xml new file mode 100644 index 000000000..393e50669 --- /dev/null +++ b/tests/visual_tests/styles/raster-color-to-alpha3.xml @@ -0,0 +1,20 @@ + + + + + style + + + ../../data/raster/transp.tiff + gdal + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/raster-color-to-alpha4.xml b/tests/visual_tests/styles/raster-color-to-alpha4.xml new file mode 100644 index 000000000..40fbdc08a --- /dev/null +++ b/tests/visual_tests/styles/raster-color-to-alpha4.xml @@ -0,0 +1,27 @@ + + + + + + DISCRETE RAINBOW + + ../../data/raster/dataraster.tif + gdal + 1 + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/raster-color-to-alpha5.xml b/tests/visual_tests/styles/raster-color-to-alpha5.xml new file mode 100644 index 000000000..6a2f4add6 --- /dev/null +++ b/tests/visual_tests/styles/raster-color-to-alpha5.xml @@ -0,0 +1,27 @@ + + + + + + DISCRETE RAINBOW + + ../../data/raster/dataraster.tif + gdal + 1 + + + + \ No newline at end of file diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 7140900d0..3346826fe 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -179,6 +179,11 @@ files = { 'vrt_colortable':{'sizes':[(256,256)]}, 'raster_colorizer':{'sizes':[(512,512)]}, 'raster_symbolizer':{'sizes':[(512,512)]}, + 'raster-color-to-alpha1':{'sizes':[(512,512)]}, + 'raster-color-to-alpha2':{'sizes':[(512,512)]}, + 'raster-color-to-alpha3':{'sizes':[(512,512)]}, + 'raster-color-to-alpha4':{'sizes':[(512,512)]}, + 'raster-color-to-alpha5':{'sizes':[(512,512)]} } class Reporting: