mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
Added compare utility to python bindings and image_util, modified set_grayscale_to_alpha to take a color optionally.
This commit is contained in:
parent
d94f5a0cee
commit
b090882902
@ -116,11 +116,6 @@ mapnik::image_view_any get_view(mapnik::image_any const& data,unsigned x,unsigne
|
||||
return mapnik::create_view(data,x,y,w,h);
|
||||
}
|
||||
|
||||
bool painted(mapnik::image_any const& im)
|
||||
{
|
||||
return im.painted();
|
||||
}
|
||||
|
||||
bool is_solid(mapnik::image_any const& im)
|
||||
{
|
||||
return mapnik::is_solid(im);
|
||||
@ -131,6 +126,11 @@ void background(mapnik::image_any & im, mapnik::color const& c)
|
||||
mapnik::fill(im, c);
|
||||
}
|
||||
|
||||
void compare(mapnik::image_any const& im1, mapnik::image_any const& im2, double threshold, bool alpha)
|
||||
{
|
||||
mapnik::compare(im1, im2, threshold, alpha);
|
||||
}
|
||||
|
||||
uint32_t get_pixel(mapnik::image_any const& im, unsigned x, unsigned y)
|
||||
{
|
||||
if (x < static_cast<unsigned>(im.width()) && y < static_cast<unsigned>(im.height()))
|
||||
@ -209,6 +209,11 @@ void set_grayscale_to_alpha(image_any & im)
|
||||
mapnik::set_grayscale_to_alpha(im);
|
||||
}
|
||||
|
||||
void set_grayscale_to_alpha_c(image_any & im, mapnik::color const& c)
|
||||
{
|
||||
mapnik::set_grayscale_to_alpha(im, c);
|
||||
}
|
||||
|
||||
void set_color_to_alpha(image_any & im, mapnik::color const& c)
|
||||
{
|
||||
mapnik::set_color_to_alpha(im, c);
|
||||
@ -322,10 +327,11 @@ void export_image()
|
||||
.def("width",&image_any::width)
|
||||
.def("height",&image_any::height)
|
||||
.def("view",&get_view)
|
||||
.def("painted",&painted)
|
||||
.def("painted",&image_any::painted)
|
||||
.def("is_solid",&is_solid)
|
||||
.def("background",&background, "Set the background color of the image.")
|
||||
.def("set_grayscale_to_alpha",&set_grayscale_to_alpha, "Set the grayscale values to the alpha channel of the Image")
|
||||
.def("set_grayscale_to_alpha",&set_grayscale_to_alpha_c, "Set the grayscale values to the alpha channel of the Image")
|
||||
.def("set_color_to_alpha",&set_color_to_alpha, "Set a given color to the alpha channel of the Image")
|
||||
.def("set_alpha",&set_alpha, "Set the overall alpha channel of the Image")
|
||||
.def("composite",&composite,
|
||||
@ -336,6 +342,12 @@ void export_image()
|
||||
arg("dx")=0,
|
||||
arg("dy")=0
|
||||
))
|
||||
.def("compare",&compare,
|
||||
( arg("self"),
|
||||
arg("image"),
|
||||
arg("threshold")=0.0,
|
||||
arg("alpha")=true
|
||||
))
|
||||
.def("premultiplied",&premultiplied)
|
||||
.def("premultiply",&premultiply)
|
||||
.def("demultiply",&demultiply)
|
||||
|
||||
@ -128,6 +128,9 @@ MAPNIK_DECL void set_alpha (T & image, float opacity);
|
||||
template <typename T>
|
||||
MAPNIK_DECL void set_grayscale_to_alpha (T & image);
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void set_grayscale_to_alpha (T & image, color const& c);
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL void set_color_to_alpha (T & image, color const& c);
|
||||
|
||||
@ -156,6 +159,9 @@ MAPNIK_DECL void view_to_string (image_view_any const& view, std::ostringstream
|
||||
|
||||
MAPNIK_DECL image_view_any create_view (image_any const& data, unsigned x, unsigned y, unsigned w, unsigned h);
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL unsigned compare(T const& im1, T const& im2, double threshold = 0, bool alpha = true);
|
||||
|
||||
inline bool is_png(std::string const& filename)
|
||||
{
|
||||
return boost::algorithm::iends_with(filename,std::string(".png"));
|
||||
|
||||
@ -468,9 +468,9 @@ namespace detail {
|
||||
struct premultiply_visitor
|
||||
{
|
||||
template <typename T>
|
||||
bool operator() (T & data)
|
||||
bool operator() (T &)
|
||||
{
|
||||
throw std::runtime_error("Error: Premultiply with " + std::string(typeid(data).name()) + " is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
@ -492,9 +492,9 @@ bool premultiply_visitor::operator()<image_rgba8> (image_rgba8 & data)
|
||||
struct demultiply_visitor
|
||||
{
|
||||
template <typename T>
|
||||
bool operator() (T & data)
|
||||
bool operator() (T &)
|
||||
{
|
||||
throw std::runtime_error("Error: Premultiply with " + std::string(typeid(data).name()) + " is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
@ -654,7 +654,7 @@ struct visitor_set_grayscale_to_alpha
|
||||
template <typename T>
|
||||
void operator() (T & data)
|
||||
{
|
||||
throw std::runtime_error("Error: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported");
|
||||
std::clog << "Warning: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported, image was not modified" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
@ -680,6 +680,43 @@ void visitor_set_grayscale_to_alpha::operator()<image_rgba8> (image_rgba8 & data
|
||||
}
|
||||
}
|
||||
|
||||
struct visitor_set_grayscale_to_alpha_c
|
||||
{
|
||||
visitor_set_grayscale_to_alpha_c(color const& c)
|
||||
: c_(c) {}
|
||||
|
||||
template <typename T>
|
||||
void operator() (T & data)
|
||||
{
|
||||
std::clog << "Warning: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported, image was not modified" << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
color const& c_;
|
||||
};
|
||||
|
||||
template <>
|
||||
void visitor_set_grayscale_to_alpha_c::operator()<image_rgba8> (image_rgba8 & data)
|
||||
{
|
||||
using pixel_type = typename image_rgba8::pixel_type;
|
||||
for (unsigned int y = 0; y < data.height(); ++y)
|
||||
{
|
||||
pixel_type* row_from = data.getRow(y);
|
||||
for (unsigned int x = 0; x < data.width(); ++x)
|
||||
{
|
||||
pixel_type rgba = row_from[x];
|
||||
pixel_type r = rgba & 0xff;
|
||||
pixel_type g = (rgba >> 8 ) & 0xff;
|
||||
pixel_type b = (rgba >> 16) & 0xff;
|
||||
|
||||
// magic numbers for grayscale
|
||||
pixel_type a = static_cast<pixel_type>(std::ceil((r * .3) + (g * .59) + (b * .11)));
|
||||
|
||||
row_from[x] = (a << 24)| (c_.blue() << 16) | (c_.green() << 8) | (c_.red()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end detail ns
|
||||
|
||||
template<>
|
||||
@ -694,7 +731,6 @@ MAPNIK_DECL void set_grayscale_to_alpha<image_any> (image_any & data)
|
||||
}
|
||||
}
|
||||
|
||||
// TEMPORARY can be removed once image_any is only way it is being passed.
|
||||
template<>
|
||||
MAPNIK_DECL void set_grayscale_to_alpha<image_rgba8> (image_rgba8 & data)
|
||||
{
|
||||
@ -708,6 +744,31 @@ MAPNIK_DECL void set_grayscale_to_alpha<image_rgba8> (image_rgba8 & data)
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
MAPNIK_DECL void set_grayscale_to_alpha<image_any> (image_any & data, color const& c)
|
||||
{
|
||||
// Prior to calling the data must not be premultiplied
|
||||
bool remultiply = mapnik::demultiply_alpha(data);
|
||||
util::apply_visitor(detail::visitor_set_grayscale_to_alpha_c(c), data);
|
||||
if (remultiply)
|
||||
{
|
||||
mapnik::premultiply_alpha(data);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
MAPNIK_DECL void set_grayscale_to_alpha<image_rgba8> (image_rgba8 & data, color const& c)
|
||||
{
|
||||
// Prior to calling the data must not be premultiplied
|
||||
bool remultiply = mapnik::demultiply_alpha(data);
|
||||
detail::visitor_set_grayscale_to_alpha_c visit(c);
|
||||
visit(data);
|
||||
if (remultiply)
|
||||
{
|
||||
mapnik::premultiply_alpha(data);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct visitor_set_color_to_alpha
|
||||
@ -1282,4 +1343,116 @@ MAPNIK_DECL image_view_any create_view(image_any const& data,unsigned x,unsigned
|
||||
return util::apply_visitor(detail::visitor_create_view(x,y,w,h), data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MAPNIK_DECL unsigned compare(T const& im1, T const& im2, double threshold, bool)
|
||||
{
|
||||
using pixel_type = typename T::pixel_type;
|
||||
if (im1.width() != im2.width() || im1.height() != im2.height())
|
||||
{
|
||||
std::clog << "Warning the two images compared are not the same sizes." << std::endl;
|
||||
return im1.width() * im1.height();
|
||||
}
|
||||
unsigned difference = 0;
|
||||
for (unsigned int y = 0; y < im1.height(); ++y)
|
||||
{
|
||||
const pixel_type * row_from = im1.getRow(y);
|
||||
const pixel_type * row_from2 = im2.getRow(y);
|
||||
for (unsigned int x = 0; x < im1.width(); ++x)
|
||||
{
|
||||
double d = std::abs(static_cast<double>(row_from[x]) - static_cast<double>(row_from2[x]));
|
||||
if (d > threshold)
|
||||
{
|
||||
++difference;
|
||||
}
|
||||
}
|
||||
}
|
||||
return difference;
|
||||
}
|
||||
|
||||
template MAPNIK_DECL unsigned compare(image_gray8 const&, image_gray8 const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray16 const&, image_gray16 const&, double, bool);
|
||||
template MAPNIK_DECL unsigned compare(image_gray32f const&, image_gray32f const&, double, bool);
|
||||
|
||||
template <>
|
||||
MAPNIK_DECL unsigned compare<image_null>(image_null const&, image_null const&, double, bool)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
MAPNIK_DECL unsigned compare<image_rgba8>(image_rgba8 const& im1, image_rgba8 const& im2, double threshold, bool alpha)
|
||||
{
|
||||
using pixel_type = image_rgba8::pixel_type;
|
||||
if (im1.width() != im2.width() || im1.height() != im2.height())
|
||||
{
|
||||
std::clog << "Warning: The two images compared are not the same sizes." << std::endl;
|
||||
return im1.width() * im1.height();
|
||||
}
|
||||
unsigned difference = 0;
|
||||
for (unsigned int y = 0; y < im1.height(); ++y)
|
||||
{
|
||||
const pixel_type * row_from = im1.getRow(y);
|
||||
const pixel_type * row_from2 = im2.getRow(y);
|
||||
for (unsigned int x = 0; x < im1.width(); ++x)
|
||||
{
|
||||
unsigned rgba = row_from[x];
|
||||
unsigned rgba2 = row_from2[x];
|
||||
unsigned r = rgba & 0xff;
|
||||
unsigned g = (rgba >> 8 ) & 0xff;
|
||||
unsigned b = (rgba >> 16) & 0xff;
|
||||
unsigned r2 = rgba2 & 0xff;
|
||||
unsigned g2 = (rgba2 >> 8 ) & 0xff;
|
||||
unsigned b2 = (rgba2 >> 16) & 0xff;
|
||||
if (std::abs(static_cast<int>(r - r2)) > static_cast<int>(threshold) ||
|
||||
std::abs(static_cast<int>(g - g2)) > static_cast<int>(threshold) ||
|
||||
std::abs(static_cast<int>(b - b2)) > static_cast<int>(threshold)) {
|
||||
++difference;
|
||||
continue;
|
||||
}
|
||||
if (alpha) {
|
||||
unsigned a = (rgba >> 24) & 0xff;
|
||||
unsigned a2 = (rgba2 >> 24) & 0xff;
|
||||
if (std::abs(static_cast<int>(a - a2)) > static_cast<int>(threshold)) {
|
||||
++difference;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return difference;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct visitor_compare
|
||||
{
|
||||
visitor_compare(image_any const& im2, double threshold, bool alpha)
|
||||
: im2_(im2), threshold_(threshold), alpha_(alpha) {}
|
||||
|
||||
template <typename T>
|
||||
unsigned operator() (T const & im1)
|
||||
{
|
||||
if (!im2_.is<T>())
|
||||
{
|
||||
std::clog << "Warning: Comparing different image types." << std::endl;
|
||||
return im1.width() * im1.height();
|
||||
}
|
||||
return mapnik::compare<T>(im1, util::get<T>(im2_), threshold_, alpha_);
|
||||
}
|
||||
|
||||
private:
|
||||
image_any const& im2_;
|
||||
double threshold_;
|
||||
bool alpha_;
|
||||
};
|
||||
|
||||
} // end detail ns
|
||||
|
||||
template <>
|
||||
MAPNIK_DECL unsigned compare<image_any>(image_any const& im1, image_any const& im2, double threshold, bool alpha)
|
||||
{
|
||||
util::apply_visitor(detail::visitor_compare(im2, threshold, alpha), im1);
|
||||
}
|
||||
|
||||
} // end ns
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user