ImagePathWML: added BW() (black and white) function

Partial merge of PR #394
This commit is contained in:
Elvish_Hunter 2015-05-03 11:20:43 +02:00
parent d4b52e1022
commit 56329ac839
5 changed files with 86 additions and 0 deletions

View file

@ -12,6 +12,8 @@ Version 1.13.0+dev:
* Fixed the Shuja not having the default AMLA.
* WML engine:
* Added support for [object] duration=turn end
* New image path functions:
* ~BW(): converts an image to black and white
* Miscellaneous and bug fixes:
* Removed abandoned libana network API implementation.
* Fixed bug#23201 Toggle icons display error in replay.

View file

@ -200,6 +200,11 @@ surface gs_modification::operator()(const surface& src) const
return greyscale_image(src);
}
surface bw_modification::operator()(const surface& src) const
{
return monochrome_image(src, threshold_);
}
surface sepia_modification::operator()(const surface &src) const
{
return sepia_image(src);
@ -750,6 +755,32 @@ REGISTER_MOD_PARSER(GS, )
return new gs_modification;
}
// Black and white
REGISTER_MOD_PARSER(BW, args)
{
const std::vector<std::string>& params = utils::split(args, ',');
if (params.size() == 1) {
try {
int threshold = lexical_cast<int>(params[0]);
if (threshold < 0 || threshold > 255) {
ERR_DP << "~BW() argument out of range 0 - 255" << std::endl;
return NULL;
}
else {
return new bw_modification(threshold);
}
}
catch (bad_lexical_cast) {
ERR_DP << "unsupported argument in ~BW() function" << std::endl;
return NULL;
}
}
else {
ERR_DP << "~BW() requires exactly one argument" << std::endl;
return NULL;
}
}
// Sepia
REGISTER_MOD_PARSER(SEPIA, )
{

View file

@ -221,6 +221,18 @@ public:
virtual surface operator()(const surface& src) const;
};
/**
* Black and white (BW) modification.
*/
class bw_modification : public modification
{
public:
bw_modification(int threshold): threshold_(threshold) {}
virtual surface operator()(const surface& src) const;
private:
int threshold_;
};
/**
* Give to the image a sepia tint (SEPIA)
*/

View file

@ -989,6 +989,46 @@ surface greyscale_image(const surface &surf, bool optimize)
return optimize ? create_optimized_surface(nsurf) : nsurf;
}
surface monochrome_image(const surface &surf, const int threshold, 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, result;
r = (*beg) >> 16;
g = (*beg) >> 8;
b = (*beg);
// first convert the pixel to grayscale
// if the resulting value is above the threshold make it black
// else make it white
result = static_cast<Uint8>(0.299 * r + 0.587 * g + 0.114 * b) > threshold ? 255 : 0;
*beg = (alpha << 24) | (result << 16) | (result << 8) | result;
}
++beg;
}
}
return optimize ? create_optimized_surface(nsurf) : nsurf;
}
surface sepia_image(const surface &surf, bool optimize)
{
if(surf == NULL)

View file

@ -246,6 +246,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 monochrome_image(const surface &surf, const int threshold, 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);