start implementing hsla image-filter
This commit is contained in:
parent
70940088d7
commit
f5d5502bc4
3 changed files with 179 additions and 0 deletions
|
@ -26,6 +26,7 @@
|
|||
|
||||
//mapnik
|
||||
#include <mapnik/image_filter_types.hpp>
|
||||
#include <mapnik/util/hsl.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
@ -403,6 +404,69 @@ void apply_filter(Src & src, agg_stack_blur const& op)
|
|||
agg::stack_blur_rgba32(pixf,op.rx,op.ry);
|
||||
}
|
||||
|
||||
template <typename Src>
|
||||
void apply_filter(Src & src, hsla const& op)
|
||||
{
|
||||
using namespace boost::gil;
|
||||
Tinter tint;
|
||||
tint.h0 = .1;
|
||||
tint.s0 = .3;
|
||||
tint.l1 = .9;
|
||||
bool tinting = !tint.is_identity();
|
||||
bool set_alpha = !tint.is_alpha_identity();
|
||||
// todo - should filters be able to report if they should be run?
|
||||
if (tinting || set_alpha)
|
||||
{
|
||||
rgba8_view_t src_view = rgba8_view(src);
|
||||
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 & a = get_color(src_it[x], alpha_t());
|
||||
uint8_t a_original = a;
|
||||
if (set_alpha)
|
||||
{
|
||||
double a2 = tint.a0 + (a/255.0 * (tint.a1 - tint.a0));
|
||||
if (a2 > 1) a2 = 1;
|
||||
if (a2 < 0) a2 = 0;
|
||||
a = static_cast<unsigned>(std::floor(a2 * 255.0));
|
||||
}
|
||||
if (a > 1 && tinting)
|
||||
{
|
||||
double h;
|
||||
double s;
|
||||
double l;
|
||||
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());
|
||||
// demultiply
|
||||
r /= a_original;
|
||||
g /= a_original;
|
||||
b /= a_original;
|
||||
rgb2hsl(r,g,b,h,s,l);
|
||||
double h2 = tint.h0 + (h * (tint.h1 - tint.h0));
|
||||
double s2 = tint.s0 + (s * (tint.s1 - tint.s0));
|
||||
double l2 = tint.l0 + (l * (tint.l1 - tint.l0));
|
||||
if (h2 > 1) h2 = 1;
|
||||
if (h2 < 0) h2 = 0;
|
||||
if (s2 > 1) s2 = 1;
|
||||
if (s2 < 0) s2 = 0;
|
||||
if (l2 > 1) l2 = 1;
|
||||
if (l2 < 0) l2 = 0;
|
||||
hsl2rgb(h2,s2,l2,r,g,b);
|
||||
// premultiply
|
||||
// we only work with premultiplied source,
|
||||
// thus all color values must be <= alpha
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Src>
|
||||
void apply_filter(Src & src, gray const& op)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,13 @@ struct agg_stack_blur
|
|||
unsigned ry;
|
||||
};
|
||||
|
||||
struct hsla
|
||||
{
|
||||
hsla(std::string const& tinter)
|
||||
: tinter_(tinter) {}
|
||||
std::string tinter_;
|
||||
};
|
||||
|
||||
typedef boost::variant<filter::blur,
|
||||
filter::gray,
|
||||
filter::agg_stack_blur,
|
||||
|
|
108
include/mapnik/util/hsl.hpp
Normal file
108
include/mapnik/util/hsl.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAPNIK_HSL_HPP
|
||||
#define MAPNIK_HSL_HPP
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
struct Tinter {
|
||||
double h0;
|
||||
double h1;
|
||||
double s0;
|
||||
double s1;
|
||||
double l0;
|
||||
double l1;
|
||||
double a0;
|
||||
double a1;
|
||||
|
||||
Tinter() :
|
||||
h0(0),
|
||||
h1(1),
|
||||
s0(0),
|
||||
s1(1),
|
||||
l0(0),
|
||||
l1(1),
|
||||
a0(0),
|
||||
a1(1) { }
|
||||
|
||||
bool is_identity() {
|
||||
return (h0 == 0 &&
|
||||
h1 == 1 &&
|
||||
s0 == 0 &&
|
||||
s1 == 1 &&
|
||||
l0 == 0 &&
|
||||
l1 == 1);
|
||||
}
|
||||
|
||||
bool is_alpha_identity() {
|
||||
return (a0 == 0 &&
|
||||
a1 == 1);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void rgb2hsl(unsigned char red, unsigned char green, unsigned char blue,
|
||||
double & h, double & s, double & l) {
|
||||
double r = red/255.0;
|
||||
double g = green/255.0;
|
||||
double b = blue/255.0;
|
||||
double max = std::max(r,std::max(g,b));
|
||||
double min = std::min(r,std::min(g,b));
|
||||
double delta = max - min;
|
||||
double gamma = max + min;
|
||||
h = s = l = gamma / 2.0;
|
||||
if (delta > 0.0) {
|
||||
s = l > 0.5 ? delta / (2.0 - gamma) : delta / gamma;
|
||||
if (max == r && max != g) h = (g - b) / delta + (g < b ? 6.0 : 0.0);
|
||||
else if (max == g && max != b) h = (b - r) / delta + 2.0;
|
||||
else if (max == b && max != r) h = (r - g) / delta + 4.0;
|
||||
h /= 6.0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double hueToRGB(double m1, double m2, double h) {
|
||||
// poor mans fmod
|
||||
if(h < 0) h += 1;
|
||||
if(h > 1) h -= 1;
|
||||
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
|
||||
if (h * 2 < 1) return m2;
|
||||
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
|
||||
return m1;
|
||||
}
|
||||
|
||||
static inline void hsl2rgb(double h, double s, double l,
|
||||
unsigned char & r, unsigned char & g, unsigned char & b) {
|
||||
if (!s) {
|
||||
r = g = b = static_cast<unsigned char>(l * 255);
|
||||
}
|
||||
double m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
|
||||
double m1 = l * 2 - m2;
|
||||
r = static_cast<unsigned char>(hueToRGB(m1, m2, h + 0.33333) * 255);
|
||||
g = static_cast<unsigned char>(hueToRGB(m1, m2, h) * 255);
|
||||
b = static_cast<unsigned char>(hueToRGB(m1, m2, h - 0.33333) * 255);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end MAPNIK_HSL_HPP
|
Loading…
Reference in a new issue