add color-to-alpha image-filter - closes #2023

This commit is contained in:
Dane Springmeyer 2013-09-26 16:14:40 -07:00
parent 843fdc0871
commit 68ff3ceead
26 changed files with 900 additions and 4 deletions

View file

@ -14,6 +14,8 @@ Released ...
Summary: TODO 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 - Added Async support to PostGIS plugin - https://github.com/mapnik/mapnik/wiki/PostGIS-Async
- Fixed alpha handling bug with `comp-op:dst-over` (#1995) - 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) - 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 - 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 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 cannot possibly be projected into the map srs or the user wishes to control map bounds without
modifying the extents of each layer. 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) - Print warning if invalid XML property names are used (#110)

View file

@ -406,6 +406,77 @@ void apply_filter(Src & src, agg_stack_blur const& op)
agg::stack_blur_rgba32(pixf,op.rx,op.ry); 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<uint8_t>(std::floor((source*255.0)+.5));
}
template <typename Src>
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<double>(op.color.red())/255.0;
double cg = static_cast<double>(op.color.green())/255.0;
double cb = static_cast<double>(op.color.blue())/255.0;
for (int y=0; y<src_view.height(); ++y)
{
rgba8_view_t::x_iterator src_it = src_view.row_begin(y);
for (int x=0; x<src_view.width(); ++x)
{
uint8_t & r = get_color(src_it[x], red_t());
uint8_t & g = get_color(src_it[x], green_t());
uint8_t & b = get_color(src_it[x], blue_t());
uint8_t & a = get_color(src_it[x], alpha_t());
double sr = static_cast<double>(r)/255.0;
double sg = static_cast<double>(g)/255.0;
double sb = static_cast<double>(b)/255.0;
double sa = static_cast<double>(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<uint8_t>(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 <typename Src> template <typename Src>
void apply_filter(Src & src, colorize_alpha const& op) void apply_filter(Src & src, colorize_alpha const& op)
{ {

View file

@ -75,6 +75,7 @@ struct image_filter_grammar :
css_color_grammar<Iterator> css_color_; css_color_grammar<Iterator> css_color_;
qi::rule<Iterator,void(mapnik::filter::color_stop &),qi::ascii::space_type> color_stop_offset; qi::rule<Iterator,void(mapnik::filter::color_stop &),qi::ascii::space_type> color_stop_offset;
phoenix::function<percent_offset_impl> percent_offset; phoenix::function<percent_offset_impl> percent_offset;
qi::rule<Iterator, qi::locals<color>, void(ContType&), qi::ascii::space_type> color_to_alpha_filter;
}; };
} }

View file

@ -59,6 +59,13 @@ struct agg_stack_blur
unsigned ry; unsigned ry;
}; };
struct color_to_alpha
{
color_to_alpha(mapnik::color const& c)
: color(c) {}
mapnik::color color;
};
struct scale_hsla struct scale_hsla
{ {
scale_hsla(double _h0, double _h1, scale_hsla(double _h0, double _h1,
@ -132,7 +139,8 @@ typedef boost::variant<filter::blur,
filter::y_gradient, filter::y_gradient,
filter::invert, filter::invert,
filter::scale_hsla, filter::scale_hsla,
filter::colorize_alpha> filter_type; filter::colorize_alpha,
filter::color_to_alpha> filter_type;
inline std::ostream& operator<< (std::ostream& os, blur) 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; 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) inline std::ostream& operator<< (std::ostream& os, scale_hsla const& filter)
{ {
os << "hsla-transform(" << filter.h0 << 'x' << filter.h1 << ':' os << "hsla-transform(" << filter.h0 << 'x' << filter.h1 << ':'

View file

@ -91,6 +91,8 @@ image_filter_grammar<Iterator,ContType>::image_filter_grammar()
scale_hsla_filter(_val) scale_hsla_filter(_val)
| |
colorize_alpha_filter(_val) colorize_alpha_filter(_val)
|
color_to_alpha_filter(_val)
; ;
agg_blur_filter = lit("agg-stack-blur")[_a = 1, _b = 1] agg_blur_filter = lit("agg-stack-blur")[_a = 1, _b = 1]
@ -122,6 +124,14 @@ image_filter_grammar<Iterator,ContType>::image_filter_grammar()
| |
double_[at_c<1>(_r1) = _1] double_[at_c<1>(_r1) = _1]
; ;
color_to_alpha_filter = lit("color-to-alpha")
>> lit('(')
>> css_color_[_a = _1]
>> lit(')')
[push_back(_r1,construct<mapnik::filter::color_to_alpha>(_a))]
;
no_args = -(lit('(') >> lit(')')); no_args = -(lit('(') >> lit(')'));
} }

View file

@ -0,0 +1,136 @@
{
"keys": [
""
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,136 @@
{
"keys": [
""
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,136 @@
{
"keys": [
""
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,136 @@
{
"keys": [
""
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,136 @@
{
"keys": [
""
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -0,0 +1,19 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
>
<Style name="style" image-filters="color-to-alpha(#00BDFF)">
<Rule>
<RasterSymbolizer opacity="1"/>
</Rule>
</Style>
<Layer name="raster"
srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<!-- https://github.com/mapnik/mapnik/issues/1471 -->
<Parameter name="file">../../data/raster/nodata-edge.tif</Parameter>
<Parameter name="type">gdal</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,20 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
background-color="steelblue"
>
<Style name="style" image-filters="color-to-alpha(#BCDAF5)">
<Rule>
<RasterSymbolizer opacity="1" scaling="quadric"/>
</Rule>
</Style>
<Layer name="raster"
srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<!-- https://github.com/mapnik/mapnik/issues/1471 -->
<Parameter name="file">../../data/raster/river_merc.tiff</Parameter>
<Parameter name="type">gdal</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,20 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
background-color="steelblue"
>
<Style name="style" image-filters="color-to-alpha(black)">
<Rule>
<RasterSymbolizer opacity="1" scaling="quadric"/>
</Rule>
</Style>
<Layer name="raster"
srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>style</StyleName>
<Datasource>
<!-- https://github.com/mapnik/mapnik/issues/1471 -->
<Parameter name="file">../../data/raster/transp.tiff</Parameter>
<Parameter name="type">gdal</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,27 @@
<Map background-color="white" srs="+init=epsg:32630" minimum-version="0.7.2">
<Style name="DISCRETE RAINBOW" direct-image-filters="color-to-alpha(white)" image-filters="color-to-alpha(yellow),color-to-alpha(blue)">
<Rule>
<RasterSymbolizer>
<RasterColorizer default-mode="discrete" default-color="white">
<stop color="red" value="0"/>
<stop color="orange" value="5"/>
<stop color="yellow" value="10"/>
<stop color="green" value="15"/>
<stop color="blue" value="20"/>
<stop color="indigo" value="25"/>
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
<Layer name="dataraster" srs="+init=epsg:32630">
<StyleName>DISCRETE RAINBOW</StyleName>
<Datasource>
<Parameter name="file">../../data/raster/dataraster.tif</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,27 @@
<Map background-color="white" srs="+init=epsg:32630" minimum-version="0.7.2">
<Style name="DISCRETE RAINBOW" image-filters="color-to-alpha(black)">
<Rule>
<RasterSymbolizer>
<RasterColorizer default-mode="discrete" default-color="white">
<stop color="red" value="0"/>
<stop color="orange" value="5"/>
<stop color="yellow" value="10"/>
<stop color="green" value="15"/>
<stop color="blue" value="20"/>
<stop color="indigo" value="25"/>
</RasterColorizer>
</RasterSymbolizer>
</Rule>
</Style>
<Layer name="dataraster" srs="+init=epsg:32630">
<StyleName>DISCRETE RAINBOW</StyleName>
<Datasource>
<Parameter name="file">../../data/raster/dataraster.tif</Parameter>
<Parameter name="type">gdal</Parameter>
<Parameter name="band">1</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -179,6 +179,11 @@ files = {
'vrt_colortable':{'sizes':[(256,256)]}, 'vrt_colortable':{'sizes':[(256,256)]},
'raster_colorizer':{'sizes':[(512,512)]}, 'raster_colorizer':{'sizes':[(512,512)]},
'raster_symbolizer':{'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: class Reporting: