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
- 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)

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);
}
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>
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_;
qi::rule<Iterator,void(mapnik::filter::color_stop &),qi::ascii::space_type> color_stop_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;
};
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::blur,
filter::y_gradient,
filter::invert,
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)
{
@ -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 << ':'

View file

@ -91,6 +91,8 @@ image_filter_grammar<Iterator,ContType>::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<Iterator,ContType>::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<mapnik::filter::color_to_alpha>(_a))]
;
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)]},
'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: