diff --git a/src/image_modifications.cpp b/src/image_modifications.cpp index 6c4759d0dbc4..eb93d080347d 100644 --- a/src/image_modifications.cpp +++ b/src/image_modifications.cpp @@ -205,6 +205,11 @@ surface sepia_modification::operator()(const surface &src) const return sepia_image(src); } +surface negative_modification::operator()(const surface &src) const +{ + return negative_image(src); +} + surface plot_alpha_modification::operator()(const surface& src) const { return alpha_to_greyscale(src); @@ -755,6 +760,12 @@ REGISTER_MOD_PARSER(SEPIA, ) return new sepia_modification; } +// Negative +REGISTER_MOD_PARSER(NEG, ) +{ + return new negative_modification; +} + // Plot Alpha REGISTER_MOD_PARSER(PLOT_ALPHA, ) { diff --git a/src/image_modifications.hpp b/src/image_modifications.hpp index 96f8ed41e6b5..75f2f759d2f4 100644 --- a/src/image_modifications.hpp +++ b/src/image_modifications.hpp @@ -229,6 +229,14 @@ struct sepia_modification : modification virtual surface operator()(const surface &src) const; }; +/** + * Make an image negative (NEG) + */ +struct negative_modification : modification +{ + virtual surface operator()(const surface &src) const; +}; + /** * Plot Alpha (Alpha) modification */ diff --git a/src/sdl/utils.cpp b/src/sdl/utils.cpp index f19f946dedae..dde98a067e37 100644 --- a/src/sdl/utils.cpp +++ b/src/sdl/utils.cpp @@ -1031,6 +1031,43 @@ surface sepia_image(const surface &surf, bool optimize) return optimize ? create_optimized_surface(nsurf) : nsurf; } +surface negative_image(const surface &surf, bool optimize) +{ + if(surf == NULL) + return NULL; + + surface nsurf(make_neutral_surface(surf)); + if(nsurf == NULL) { + std::cerr << "failed to make neutral surface\n"; + return NULL; + } + + { + surface_lock lock(nsurf); + Uint32* beg = lock.pixels(); + Uint32* end = beg + nsurf->w*surf->h; + + while(beg != end) { + Uint8 alpha = (*beg) >> 24; + + if(alpha) { + Uint8 r, g, b; + r = (*beg) >> 16; + g = (*beg) >> 8; + b = (*beg); + + // basically, to get a channel's negative it's enough + // to subtract its value from 255 + *beg = (alpha << 24) | ((255 - r) << 16) | ((255 - g) << 8) | (255 - b); + } + + ++beg; + } + } + + return optimize ? create_optimized_surface(nsurf) : nsurf; +} + surface alpha_to_greyscale(const surface &surf, bool optimize) { if(surf == NULL) diff --git a/src/sdl/utils.hpp b/src/sdl/utils.hpp index 00e80ad9649a..0c070f4b2953 100644 --- a/src/sdl/utils.hpp +++ b/src/sdl/utils.hpp @@ -247,6 +247,7 @@ surface tile_surface(const surface &surf, int w, int h, bool optimize=true); surface adjust_surface_color(const surface &surf, int r, int g, int b, bool optimize=true); surface greyscale_image(const surface &surf, bool optimize=true); surface sepia_image(const surface &surf, bool optimize=true); +surface negative_image(const surface &surf, bool optimize=true); surface alpha_to_greyscale(const surface & surf, bool optimize=true); surface wipe_alpha(const surface & surf, bool optimize=true); /** create an heavy shadow of the image, by blurring, increasing alpha and darkening */