← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/remove_player_color into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/remove_player_color into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/remove_player_color/+merge/243896

- Renamed GrayBlitProgram to MonochromeBlitProgram and changed its API to be easier to understand.
- Removed all uses of ImageTransformation::player_colored(). Sadly, due to design constraints we loose player color in the building_window background and in the BuildGrid. They can be brought back with some design changes in those classes.
- Removes image_transformation.[h|cc].



-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/remove_player_color into lp:widelands.
=== modified file 'src/graphic/CMakeLists.txt'
--- src/graphic/CMakeLists.txt	2014-12-05 07:54:43 +0000
+++ src/graphic/CMakeLists.txt	2014-12-06 16:21:16 +0000
@@ -157,8 +157,6 @@
     font_handler1.h
     graphic.cc
     graphic.h
-    image_transformations.cc
-    image_transformations.h
     in_memory_image.cc
     in_memory_image.h
     rendertarget.cc

=== modified file 'src/graphic/animation.cc'
--- src/graphic/animation.cc	2014-12-04 09:00:20 +0000
+++ src/graphic/animation.cc	2014-12-06 16:21:16 +0000
@@ -38,7 +38,6 @@
 #include "graphic/graphic.h"
 #include "graphic/image.h"
 #include "graphic/image_cache.h"
-#include "graphic/image_transformations.h"
 #include "graphic/surface.h"
 #include "graphic/texture_cache.h"
 #include "io/filesystem/layered_filesystem.h"
@@ -127,7 +126,6 @@
 	uint16_t nr_frames() const override;
 	uint32_t frametime() const override;
 	const Point& hotspot() const override;
-	const Image& representative_image(const RGBColor& clr) const override;
 	const Image& representative_image_from_disk() const override;
 	virtual void blit(uint32_t time, const Point&, const Rect& srcrc, const RGBColor* clr, Surface*)
 	   const override;
@@ -135,12 +133,12 @@
 
 
 private:
+	// Loads the graphics if they are not yet loaded.
+	void ensure_graphics_are_loaded() const;
+
 	// Load the needed graphics from disk.
 	void load_graphics();
 
-	// Returns the given frame image with the given clr (if not NULL).
-	const Image& get_frame(uint32_t time, const RGBColor* playercolor = NULL) const;
-
 	uint32_t frametime_;
 	Point hotspot_;
 	bool hasplrclrs_;
@@ -231,6 +229,12 @@
 	}
 }
 
+void NonPackedAnimation::ensure_graphics_are_loaded() const {
+	if (frames_.empty()) {
+		const_cast<NonPackedAnimation*>(this)->load_graphics();
+	}
+}
+
 void NonPackedAnimation::load_graphics() {
 	if (image_files_.empty())
 		throw wexception("animation without pictures.");
@@ -271,23 +275,17 @@
 }
 
 uint16_t NonPackedAnimation::width() const {
-	if (frames_.empty()) {
-		const_cast<NonPackedAnimation*>(this)->load_graphics();
-	}
+	ensure_graphics_are_loaded();
 	return frames_[0]->width();
 }
 
 uint16_t NonPackedAnimation::height() const {
-	if (frames_.empty()) {
-		const_cast<NonPackedAnimation*>(this)->load_graphics();
-	}
+	ensure_graphics_are_loaded();
 	return frames_[0]->height();
 }
 
 uint16_t NonPackedAnimation::nr_frames() const {
-	if (frames_.empty()) {
-		const_cast<NonPackedAnimation*>(this)->load_graphics();
-	}
+	ensure_graphics_are_loaded();
 	return frames_.size();
 }
 
@@ -299,12 +297,9 @@
 	return hotspot_;
 }
 
-const Image& NonPackedAnimation::representative_image(const RGBColor& clr) const {
-	return get_frame(0, &clr);
-}
-
 const Image& NonPackedAnimation::representative_image_from_disk() const {
-	return get_frame(0, nullptr);
+	ensure_graphics_are_loaded();
+	return *frames_[0];
 }
 
 void NonPackedAnimation::trigger_soundfx(uint32_t time, uint32_t stereo_position) const {
@@ -322,24 +317,22 @@
 {
 	assert(target);
 
-	const Image& frame = get_frame(time, clr);
-	target->blit(
-	   Rect(dst.x, dst.y, srcrc.w, srcrc.h), frame.texture(), srcrc, 1., BlendMode::UseAlpha);
-}
+	const int idx = time / frametime_ % nr_frames();
+	assert(idx < nr_frames());
 
-const Image& NonPackedAnimation::get_frame(uint32_t time, const RGBColor* playercolor) const {
-	if (frames_.empty()) {
-		const_cast<NonPackedAnimation*>(this)->load_graphics();
+	if (!hasplrclrs_ || clr == nullptr) {
+		target->blit(Rect(dst.x, dst.y, srcrc.w, srcrc.h),
+		             frames_.at(idx)->texture(),
+		             srcrc,
+		             1.,
+		             BlendMode::UseAlpha);
+	} else {
+		target->blit_blended(Rect(dst.x, dst.y, srcrc.w, srcrc.h),
+		                     frames_.at(idx)->texture(),
+		                     pcmasks_.at(idx)->texture(),
+		                     srcrc,
+		                     *clr);
 	}
-	const uint32_t framenumber = time / frametime_ % nr_frames();
-	assert(framenumber < nr_frames());
-	const Image* original = frames_[framenumber];
-
-	if (!hasplrclrs_ || !playercolor)
-		return *original;
-
-	assert(frames_.size() == pcmasks_.size());
-	return *ImageTransformations::player_colored(*playercolor, original, pcmasks_[framenumber]);
 }
 
 }  // namespace

=== modified file 'src/graphic/animation.h'
--- src/graphic/animation.h	2014-07-14 19:48:07 +0000
+++ src/graphic/animation.h	2014-12-06 16:21:16 +0000
@@ -68,11 +68,6 @@
 	/// so the caller has to adjust for the hotspot himself.
 	virtual const Point& hotspot() const = 0;
 
-	// An image frame that shows the first animation frame, colored using the
-	// 'player_clr'. This can be used in the UI (e.g. buildingwindow) to
-	// represent this image.
-	virtual const Image& representative_image(const RGBColor& player_clr) const = 0;
-
 	// An image frame that is guaranteed to be a path to a file on disc. This is
 	// a clutch needed to make sure that messages can always be displayed, even
 	// no image processing has taken place before.

=== modified file 'src/graphic/gl/blit_program.cc'
--- src/graphic/gl/blit_program.cc	2014-12-04 09:00:20 +0000
+++ src/graphic/gl/blit_program.cc	2014-12-06 16:21:16 +0000
@@ -58,21 +58,44 @@
 }
 )";
 
-const char kGrayBlitFragmentShader[] = R"(
-#version 120
-
-uniform float u_luminosity_factor;
-uniform float u_opacity;
-uniform sampler2D u_texture;
-
-varying vec2 out_texture_coordinate;
-
-void main() {
-	vec4 texture_color = texture2D(u_texture, out_texture_coordinate);
-	// See http://en.wikipedia.org/wiki/YUV.
-	float luminance = dot(vec3(0.299, 0.587, 0.114), texture_color.rgb) * u_luminosity_factor;
-
-	gl_FragColor = vec4(vec3(luminance), u_opacity * texture_color.a);
+const char kMonochromeBlitFragmentShader[] = R"(
+#version 120
+
+uniform float u_opacity;
+uniform sampler2D u_texture;
+uniform vec3 u_blend;
+
+varying vec2 out_texture_coordinate;
+
+void main() {
+	vec4 texture_color = texture2D(u_texture, out_texture_coordinate);
+
+	// See http://en.wikipedia.org/wiki/YUV.
+	float luminance = dot(vec3(0.299, 0.587, 0.114), texture_color.rgb);
+
+	gl_FragColor = vec4(vec3(luminance) * u_blend, u_opacity * texture_color.a);
+}
+)";
+
+const char kBlendedBlitFragmentShader[] = R"(
+#version 120
+
+uniform float u_opacity;
+uniform sampler2D u_texture;
+uniform sampler2D u_mask;
+uniform vec3 u_blend;
+
+varying vec2 out_texture_coordinate;
+
+void main() {
+	vec4 texture_color = texture2D(u_texture, out_texture_coordinate);
+	vec4 mask_color = texture2D(u_mask, out_texture_coordinate);
+
+	// See http://en.wikipedia.org/wiki/YUV.
+	float luminance = dot(vec3(0.299, 0.587, 0.114), texture_color.rgb);
+	float blend_influence = mask_color.r * mask_color.a;
+	gl_FragColor = vec4(
+	   mix(texture_color.rgb, u_blend * luminance, blend_influence), u_opacity * texture_color.a);
 }
 )";
 
@@ -215,28 +238,64 @@
 }
 
 // static
-GrayBlitProgram& GrayBlitProgram::instance() {
-	static GrayBlitProgram blit_program;
+MonochromeBlitProgram& MonochromeBlitProgram::instance() {
+	static MonochromeBlitProgram blit_program;
 	return blit_program;
 }
 
-GrayBlitProgram::~GrayBlitProgram() {
-}
-
-GrayBlitProgram::GrayBlitProgram() {
-	blit_program_.reset(new BlitProgram(kGrayBlitFragmentShader));
-
-	u_luminosity_factor_ = glGetUniformLocation(blit_program_->program_object(), "u_luminosity_factor");
-}
-
-void GrayBlitProgram::draw(const FloatRect& gl_dest_rect,
+MonochromeBlitProgram::~MonochromeBlitProgram() {
+}
+
+MonochromeBlitProgram::MonochromeBlitProgram() {
+	blit_program_.reset(new BlitProgram(kMonochromeBlitFragmentShader));
+
+	u_blend_ = glGetUniformLocation(blit_program_->program_object(), "u_blend");
+}
+
+void MonochromeBlitProgram::draw(const FloatRect& gl_dest_rect,
                        const FloatRect& gl_src_rect,
                        const GLuint gl_texture,
-							  const float opacity,
-                       const float luminosity_factor) {
-	blit_program_->activate(gl_dest_rect, gl_src_rect, gl_texture, opacity, BlendMode::UseAlpha);
-
-	glUniform1f(u_luminosity_factor_, luminosity_factor);
-
-	blit_program_->draw_and_deactivate(BlendMode::UseAlpha);
+							  const RGBAColor& blend) {
+	blit_program_->activate(gl_dest_rect, gl_src_rect, gl_texture, blend.a / 255., BlendMode::UseAlpha);
+
+	glUniform3f(u_blend_, blend.r / 255., blend.g / 255., blend.b / 255.);
+
+	blit_program_->draw_and_deactivate(BlendMode::UseAlpha);
+}
+
+// static
+BlendedBlitProgram& BlendedBlitProgram::instance() {
+	static BlendedBlitProgram blit_program;
+	return blit_program;
+}
+
+BlendedBlitProgram::~BlendedBlitProgram() {
+}
+
+BlendedBlitProgram::BlendedBlitProgram() {
+	blit_program_.reset(new BlitProgram(kBlendedBlitFragmentShader));
+	u_blend_ = glGetUniformLocation(blit_program_->program_object(), "u_blend");
+	u_mask_ = glGetUniformLocation(blit_program_->program_object(), "u_mask");
+}
+
+void BlendedBlitProgram::draw(const FloatRect& gl_dest_rect,
+                       const FloatRect& gl_src_rect,
+                       const GLuint gl_texture_image,
+							  const GLuint gl_texture_mask,
+							  const RGBAColor& blend) {
+	blit_program_->activate(gl_dest_rect, gl_src_rect, gl_texture_image, blend.a / 255., BlendMode::UseAlpha);
+
+	glActiveTexture(GL_TEXTURE1);
+	glBindTexture(GL_TEXTURE_2D, gl_texture_mask);
+	glUniform1i(u_mask_, 1);
+
+	glUniform3f(u_blend_, blend.r / 255., blend.g / 255., blend.b / 255.);
+
+	blit_program_->draw_and_deactivate(BlendMode::UseAlpha);
+
+	glActiveTexture(GL_TEXTURE1);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D, 0);
 }

=== modified file 'src/graphic/gl/blit_program.h'
--- src/graphic/gl/blit_program.h	2014-12-04 09:00:20 +0000
+++ src/graphic/gl/blit_program.h	2014-12-06 16:21:16 +0000
@@ -55,32 +55,58 @@
 	DISALLOW_COPY_AND_ASSIGN(VanillaBlitProgram);
 };
 
-class GrayBlitProgram {
+class MonochromeBlitProgram {
 public:
 	// Returns the (singleton) instance of this class.
-	static GrayBlitProgram& instance();
-	~GrayBlitProgram();
+	static MonochromeBlitProgram& instance();
+	~MonochromeBlitProgram();
 
 	// Draws the rectangle 'gl_src_rect' from the texture with the name
 	// 'gl_texture' to 'gl_dest_rect' in the currently bound framebuffer. All
-	// coordinates are in the OpenGL frame. The 'blend_mode' defines if the
-	// values are copied or if alpha values are used.
-	// The image is converted to grayscale during blit.
+	// coordinates are in the OpenGL frame. The image is first converted to
+	// luminance, then all values are multiplied with blend.
 	void draw(const FloatRect& gl_dest_rect,
 	          const FloatRect& gl_src_rect,
 	          const GLuint gl_texture,
-				 float opacity,
-	          float luminosity_factor);
-
-private:
-	GrayBlitProgram();
-
-	std::unique_ptr<BlitProgram> blit_program_;
-
-	// Uniforms.
-	GLint u_luminosity_factor_;
-
-	DISALLOW_COPY_AND_ASSIGN(GrayBlitProgram);
+				 const RGBAColor& blend);
+
+private:
+	MonochromeBlitProgram();
+
+	std::unique_ptr<BlitProgram> blit_program_;
+
+	// Uniforms.
+	GLint u_blend_;
+
+	DISALLOW_COPY_AND_ASSIGN(MonochromeBlitProgram);
+};
+
+class BlendedBlitProgram {
+public:
+	// Returns the (singleton) instance of this class.
+	static BlendedBlitProgram& instance();
+	~BlendedBlitProgram();
+
+	// Draws the rectangle 'gl_src_rect' from the texture with the name
+	// 'gl_texture_image' to 'gl_dest_rect' in the currently bound framebuffer. All
+	// coordinates are in the OpenGL frame. The 'gl_texture_mask' is used to selectively apply
+	// the 'blend'. This is used for blitting player colored images.
+	void draw(const FloatRect& gl_dest_rect,
+	          const FloatRect& gl_src_rect,
+	          const GLuint gl_texture_image,
+	          const GLuint gl_texture_mask,
+				 const RGBAColor& blend);
+
+private:
+	BlendedBlitProgram();
+
+	std::unique_ptr<BlitProgram> blit_program_;
+
+	// Uniforms.
+	GLint u_blend_;
+	GLint u_mask_;
+
+	DISALLOW_COPY_AND_ASSIGN(BlendedBlitProgram);
 };
 
 #endif  // end of include guard: WL_GRAPHIC_GL_DRAW_RECT_PROGRAM_H

=== modified file 'src/graphic/graphic.cc'
--- src/graphic/graphic.cc	2014-12-01 21:28:21 +0000
+++ src/graphic/graphic.cc	2014-12-06 16:21:16 +0000
@@ -27,7 +27,6 @@
 #include "graphic/gl/system_headers.h"
 #include "graphic/image.h"
 #include "graphic/image_io.h"
-#include "graphic/image_transformations.h"
 #include "graphic/rendertarget.h"
 #include "graphic/screen.h"
 #include "graphic/texture.h"
@@ -71,8 +70,6 @@
      image_cache_(new ImageCache(texture_cache_.get())),
      animation_manager_(new AnimationManager())
 {
-	ImageTransformations::initialize();
-
 	// Request an OpenGL 2 context with double buffering.
 	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);

=== removed file 'src/graphic/image_transformations.cc'
--- src/graphic/image_transformations.cc	2014-12-04 09:18:03 +0000
+++ src/graphic/image_transformations.cc	1970-01-01 00:00:00 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2006-2013 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include "graphic/image_transformations.h"
-
-#include <string>
-
-#include <SDL.h>
-#include <boost/format.hpp>
-
-#include "base/macros.h"
-#include "graphic/color.h"
-#include "graphic/graphic.h"
-#include "graphic/texture.h"
-#include "graphic/texture_cache.h"
-
-using namespace std;
-
-namespace {
-
-// This table is used to transform colors.
-uint32_t luminance_table_r[0x100];
-uint32_t luminance_table_g[0x100];
-uint32_t luminance_table_b[0x100];
-
-// Encodes the given Image into the corresponding image for player color.
-// Takes the neutral set of images and the player color mask.
-Texture* make_playerclr_texture(Texture& original_texture,
-                                         Texture& pcmask_texture,
-                                         const RGBColor& color) {
-	Texture* new_texture = new Texture(original_texture.width(), original_texture.height());
-
-	const SDL_PixelFormat & fmt = original_texture.format();
-	const SDL_PixelFormat & fmt_pc = pcmask_texture.format();
-	const SDL_PixelFormat & destfmt = new_texture->format();
-
-	original_texture.lock(Surface::Lock_Normal);
-	pcmask_texture.lock(Surface::Lock_Normal);
-	new_texture->lock(Surface::Lock_Discard);
-	// This could be done significantly faster, but since we
-	// cache the result, let's keep it simple for now.
-	for (uint32_t y = 0; y < original_texture.height(); ++y) {
-		for (uint32_t x = 0; x < original_texture.width(); ++x) {
-			RGBAColor source;
-			RGBAColor mask;
-			RGBAColor product;
-
-			source.set(fmt, original_texture.get_pixel(x, y));
-			mask.set(fmt_pc, pcmask_texture.get_pixel(x, y));
-
-			if
-				(uint32_t const influence =
-				 static_cast<uint32_t>(mask.r) * mask.a)
-				{
-					uint32_t const intensity =
-						(luminance_table_r[source.r] +
-						 luminance_table_g[source.g] +
-						 luminance_table_b[source.b] +
-						 8388608U) //  compensate for truncation:  .5 * 2^24
-						>> 24;
-					RGBAColor plrclr;
-
-					plrclr.r = (color.r * intensity) >> 8;
-					plrclr.g = (color.g * intensity) >> 8;
-					plrclr.b = (color.b * intensity) >> 8;
-
-					product.r =
-						(plrclr.r * influence + source.r * (65536 - influence)) >> 16;
-					product.g =
-						(plrclr.g * influence + source.g * (65536 - influence)) >> 16;
-					product.b =
-						(plrclr.b * influence + source.b * (65536 - influence)) >> 16;
-					product.a = source.a;
-				} else {
-					product = source;
-				}
-
-			new_texture->set_pixel(x, y, product.map(destfmt));
-		}
-	}
-	original_texture.unlock(Surface::Unlock_NoChange);
-	pcmask_texture.unlock(Surface::Unlock_NoChange);
-	new_texture->unlock(Surface::Unlock_Update);
-
-	return new_texture;
-}
-
-// An Image implementation that is the transformation of another Image. Uses
-// the TextureCache to avoid recalculating the transformation too often. No
-// ownerships are taken.
-class TransformedImage : public Image {
-public:
-	TransformedImage(const string& ghash, const Image& original, TextureCache* texture_cache) :
-		hash_(ghash), original_(original), texture_cache_(texture_cache) {}
-	virtual ~TransformedImage() {}
-
-	// Implements Image.
-	uint16_t width() const override {return original_.width();}
-	uint16_t height() const override {return original_.height();}
-	const string& hash() const override {return hash_;}
-	Texture* texture() const override {
-		Texture* texture = texture_cache_->get(hash_);
-		if (texture)
-			return texture;
-
-		texture = recalculate_texture();
-		texture_cache_->insert(hash_, texture, true);
-		return texture;
-	}
-
-	virtual Texture* recalculate_texture() const = 0;
-
-protected:
-	const string hash_;
-	const Image& original_;
-	TextureCache* const texture_cache_;  // not owned
-};
-
-// A copy with applied player colors. Also needs a mask - ownership is not
-// taken.
-class PlayerColoredImage : public TransformedImage {
-public:
-	PlayerColoredImage
-		(const string& ghash, const Image& original,
-		 TextureCache* texture_cache, const RGBColor& color, const Image& mask)
-		: TransformedImage(ghash, original, texture_cache), color_(color), mask_(mask)
-		{}
-	virtual ~PlayerColoredImage() {}
-
-	// Implements TransformedImage.
-	Texture* recalculate_texture() const override {
-		return make_playerclr_texture(*original_.texture(), *mask_.texture(), color_);
-	}
-
-private:
-	const RGBColor& color_;
-	const Image& mask_;
-};
-
-}
-
-namespace ImageTransformations {
-
-void initialize() {
-	// Initialize the table used to create grayed image
-	for
-		(uint32_t i = 0, r = 0, g = 0, b = 0;
-		 i < 0x100;
-		 ++i, r += 5016388U, g += 9848226U, b += 1912603U)
-		{
-			luminance_table_r[i] = r;
-			luminance_table_g[i] = g;
-			luminance_table_b[i] = b;
-		}
-}
-
-const Image* player_colored(const RGBColor& clr, const Image* original, const Image* mask) {
-	const string new_hash =
-		(boost::format("%s:%02x%02x%02x") % original->hash() % static_cast<int>(clr.r) %
-		 static_cast<int>(clr.g) % static_cast<int>(clr.b))
-			.str();
-	if (g_gr->images().has(new_hash))
-		return g_gr->images().get(new_hash);
-	return
-		g_gr->images().insert
-			(new PlayerColoredImage(new_hash, *original, &g_gr->textures(), clr, *mask));
-}
-
-}  // namespace ImageTransformations

=== removed file 'src/graphic/image_transformations.h'
--- src/graphic/image_transformations.h	2014-12-04 09:18:03 +0000
+++ src/graphic/image_transformations.h	1970-01-01 00:00:00 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006-2013 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef WL_GRAPHIC_IMAGE_TRANSFORMATIONS_H
-#define WL_GRAPHIC_IMAGE_TRANSFORMATIONS_H
-
-#include <stdint.h>
-
-struct RGBColor;
-class Image;
-
-// A set of image transformations used in Widelands.
-namespace ImageTransformations {
-
-// This must be called once before any of the functions below are called. This
-// is done when the graphics system is initialized.
-void initialize();
-
-// All of the functions below take an original image, transform it, cache the
-// newly created image in the global ImageCache and return it. It is therefore
-// safe to call the methods with the same arguments multiple times without
-// construction cost.
-
-// Encodes the given Image into the corresponding image with a player color.
-// Takes the image and the player color mask and the new color the image should
-// be tainted in.
-const Image* player_colored(const RGBColor& clr, const Image* original, const Image* mask);
-}
-
-
-#endif  // end of include guard: WL_GRAPHIC_IMAGE_TRANSFORMATIONS_H

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2014-12-04 21:02:35 +0000
+++ src/graphic/rendertarget.cc	2014-12-06 16:21:16 +0000
@@ -221,20 +221,18 @@
 	}
 }
 
-void RenderTarget::blitrect_scale_gray(const Rect& destination_rect,
+void RenderTarget::blitrect_scale_monochrome(const Rect& destination_rect,
                                        const Image* image,
                                        const Rect& source_rect,
-                                       float opacity,
-                                       float luminosity_factor) {
+													const RGBAColor& blend) {
 	Point destination_point(destination_rect.x, destination_rect.y);
 	Rect srcrect(source_rect);
 	if (to_surface_geometry(&destination_point, &srcrect)) {
-		m_surface->blit_gray(
+		m_surface->blit_monochrome(
 		   Rect(destination_point.x, destination_point.y, destination_rect.w, destination_rect.h),
 		   image->texture(),
 		   source_rect,
-		   opacity,
-		   luminosity_factor);
+		   blend);
 	}
 }
 

=== modified file 'src/graphic/rendertarget.h'
--- src/graphic/rendertarget.h	2014-12-04 09:00:20 +0000
+++ src/graphic/rendertarget.h	2014-12-06 16:21:16 +0000
@@ -87,15 +87,11 @@
 	                    float opacity,
 	                    BlendMode blend_mode);
 
-	// Like blitrect_scale, but the image is converted to grayscale
-	// and all grayscale values are multiplied with
-	// 'luminosity_factor' to make the image brighter or darker. Alpha
-	// is always used on blending.
-	void blitrect_scale_gray(const Rect& destination_rect,
-	                    const Image* image,
-	                    const Rect& source_rect,
-	                    float opacity,
-							  float luminosity_factor);
+	// Like blitrect_scale. See MonochromeBlitProgram for details.
+	void blitrect_scale_monochrome(const Rect& destination_rect,
+	                               const Image* image,
+	                               const Rect& source_rect,
+	                               const RGBAColor& blend);
 
 	void tile(const Rect&,
 	          const Image* image,

=== modified file 'src/graphic/surface.cc'
--- src/graphic/surface.cc	2014-12-04 09:00:20 +0000
+++ src/graphic/surface.cc	2014-12-06 16:21:16 +0000
@@ -200,16 +200,27 @@
 	   gl_dst_rect, gl_src_rect, texture->get_gl_texture(), opacity, blend_mode);
 }
 
-void Surface::blit_gray(const Rect& dst_rect,
-	                  const Texture* texture,
-	                  const Rect& src_rect,
-							const float opacity,
-	                  float opacity_factor) {
+void Surface::blit_monochrome(const Rect& dst_rect,
+                             const Texture* texture,
+                             const Rect& src_rect,
+                             const RGBAColor& blend) {
 	glViewport(0, 0, width(), height());
 
 	FloatRect gl_dst_rect, gl_src_rect;
 	src_and_dst_rect_to_gl(texture, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect);
 
-	GrayBlitProgram::instance().draw(
-	   gl_dst_rect, gl_src_rect, texture->get_gl_texture(), opacity, opacity_factor);
+	MonochromeBlitProgram::instance().draw(
+	   gl_dst_rect, gl_src_rect, texture->get_gl_texture(), blend);
+}
+
+void Surface::blit_blended(const Rect& dst_rect,
+                           const Texture* texture,
+                           const Texture* mask,
+                           const Rect& src_rect,
+                           const RGBColor& blend) {
+	FloatRect gl_dst_rect, gl_src_rect;
+	src_and_dst_rect_to_gl(texture, dst_rect, src_rect, &gl_dst_rect, &gl_src_rect);
+
+	BlendedBlitProgram::instance().draw(
+	   gl_dst_rect, gl_src_rect, texture->get_gl_texture(), mask->get_gl_texture(), blend);
 }

=== modified file 'src/graphic/surface.h'
--- src/graphic/surface.h	2014-12-04 09:00:20 +0000
+++ src/graphic/surface.h	2014-12-06 16:21:16 +0000
@@ -49,12 +49,18 @@
 							const float opacity,
 	                  BlendMode blend_mode);
 
-	/// This draws a grayed out version.
-	virtual void blit_gray(const Rect& dst,
+	/// This draws a grayed out version. See MonochromeBlitProgram.
+	virtual void blit_monochrome(const Rect& dst,
 	                  const Texture*,
 	                  const Rect& srcrc,
-							const float opacity,
-	                  float opacity_factor);
+	                  const RGBAColor& multiplier);
+
+	/// This draws a playercolor blended image. See BlendedBlitProgram.
+	virtual void blit_blended(const Rect& dst,
+	                  const Texture* image,
+							const Texture* mask,
+	                  const Rect& srcrc,
+	                  const RGBColor& blend);
 
 	/// Draws a filled rect to the surface. No blending takes place, the values
 	// in the target are just replaced (i.e. / BlendMode would be BlendMode::Copy).

=== modified file 'src/graphic/texture.cc'
--- src/graphic/texture.cc	2014-12-04 09:00:20 +0000
+++ src/graphic/texture.cc	2014-12-06 16:21:16 +0000
@@ -276,16 +276,29 @@
 	reset_gl();
 }
 
-void Texture::blit_gray(const Rect& dst,
+void Texture::blit_monochrome(const Rect& dst,
                         const Texture* src,
                         const Rect& srcrc,
-                        float opacity,
-                        const float opacity_factor) {
-	if (m_w <= 0 || m_h <= 0) {
-		return;
-	}
-
-	setup_gl(m_texture);
-	Surface::blit_gray(dst, src, srcrc, opacity, opacity_factor);
+                        const RGBAColor& blend) {
+	if (m_w <= 0 || m_h <= 0) {
+		return;
+	}
+
+	setup_gl(m_texture);
+	Surface::blit_monochrome(dst, src, srcrc, blend);
+	reset_gl();
+}
+
+void Texture::blit_blended(const Rect& dst,
+                           const Texture* image,
+                           const Texture* mask,
+                           const Rect& srcrc,
+                           const RGBColor& blend) {
+	if (m_w <= 0 || m_h <= 0) {
+		return;
+	}
+
+	setup_gl(m_texture);
+	Surface::blit_blended(dst, image, mask, srcrc, blend);
 	reset_gl();
 }

=== modified file 'src/graphic/texture.h'
--- src/graphic/texture.h	2014-12-04 09:00:20 +0000
+++ src/graphic/texture.h	2014-12-06 16:21:16 +0000
@@ -63,11 +63,13 @@
 	          const Rect& srcrc,
 				 float opacity,
 	          BlendMode blend_mode) override;
-	void blit_gray(const Rect& dst,
-	               const Texture*,
-	               const Rect& srcrc,
-	               const float opacity,
-	               float opacity_factor) override;
+	void
+	blit_monochrome(const Rect& dst, const Texture*, const Rect& srcrc, const RGBAColor& blend) override;
+	void blit_blended(const Rect& dst,
+	                  const Texture* image,
+	                  const Texture* mask,
+	                  const Rect& srcrc,
+	                  const RGBColor& blend) override;
 
 	GLuint get_gl_texture() const {return m_texture;}
 

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2014-12-04 09:18:03 +0000
+++ src/ui_basic/button.cc	2014-12-06 16:21:16 +0000
@@ -185,12 +185,11 @@
 		   1.,
 		   BlendMode::UseAlpha);
 		} else {
-			dst.blitrect_scale_gray(
+			dst.blitrect_scale_monochrome(
 			   Rect((get_w() - blit_width) / 2, (get_h() - blit_height) / 2, blit_width, blit_height),
 			   m_pic_custom,
 			   Rect(0, 0, m_pic_custom->width(), m_pic_custom->height()),
-			   0.5 /* opacity */,
-			   1. /* luminosity_factor */);
+			   RGBAColor(255, 255, 255, 127));
 		}
 
 	} else if (m_title.length()) {

=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc	2014-12-04 09:18:03 +0000
+++ src/wui/buildingwindow.cc	2014-12-06 16:21:16 +0000
@@ -114,16 +114,15 @@
 {
 	UI::Window::draw(dst);
 
+	// TODO(sirver): chang this to directly blit the animation. This needs support for or removal of
+	// RenderTarget.
 	const Animation& anim = g_gr->animations().get_animation(building().get_ui_anim());
-
-	const Image* image =
-	   &anim.representative_image(building().owner().get_playercolor());
-
+	const Image* image = &anim.representative_image_from_disk();
 	dst.blitrect_scale(Rect((get_inner_w() - image->width()) / 2,
 	                        (get_inner_h() - image->height()) / 2,
 	                        image->width(),
 	                        image->height()),
-	                   image,
+	                   &anim.representative_image_from_disk(),
 	                   Rect(0, 0, image->width(), image->height()),
 	                   0.5,
 	                   BlendMode::UseAlpha);

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2014-12-04 09:18:03 +0000
+++ src/wui/fieldaction.cc	2014-12-06 16:21:16 +0000
@@ -56,7 +56,6 @@
 // The BuildGrid presents a selection of buildable buildings
 struct BuildGrid : public UI::IconGrid {
 	BuildGrid(UI::Panel* parent,
-	          const RGBColor& player_color,
 	          const Widelands::TribeDescr& tribe,
 	          int32_t x,
 	          int32_t y,
@@ -74,15 +73,13 @@
 	void mousein_slot(int32_t idx);
 
 private:
-	const RGBColor player_color_;
 	const Widelands::TribeDescr& tribe_;
 };
 
 BuildGrid::BuildGrid(
-		UI::Panel* parent, const RGBColor& player_color, const Widelands::TribeDescr& tribe,
+		UI::Panel* parent, const Widelands::TribeDescr& tribe,
 		int32_t x, int32_t y, int32_t cols) :
 	UI::IconGrid(parent, x, y, kBuildGridCellSize, kBuildGridCellSize, cols),
-	player_color_(player_color),
 	tribe_(tribe)
 {
 	clicked.connect(boost::bind(&BuildGrid::click_slot, this, _1));
@@ -99,13 +96,16 @@
 {
 	const Widelands::BuildingDescr & descr =
 		*tribe_.get_building_descr(Widelands::BuildingIndex(id));
-	UI::IconGrid::add(
-	   descr.name(),
-	   &g_gr->animations().get_animation(descr.get_animation("idle")).representative_image(
-	      player_color_),
-	   reinterpret_cast<void*>(id),
-	   descr.descname() + "<br><font size=11>" + _("Construction costs:") + "</font><br>" +
-	      waremap_to_richtext(tribe_, descr.buildcost()));
+	// TODO(sirver): change this to take a Button subclass instead of
+	// parameters. This will allow overriding the way it is rendered
+	// to bring back player colors.
+	UI::IconGrid::add(descr.name(),
+	                  &g_gr->animations()
+	                      .get_animation(descr.get_animation("idle"))
+	                      .representative_image_from_disk(),
+	                  reinterpret_cast<void*>(id),
+	                  descr.descname() + "<br><font size=11>" + _("Construction costs:") +
+	                     "</font><br>" + waremap_to_richtext(tribe_, descr.buildcost()));
 }
 
 
@@ -175,7 +175,7 @@
 
 	void init();
 	void add_buttons_auto();
-	void add_buttons_build(int32_t buildcaps, const RGBColor& player_color);
+	void add_buttons_build(int32_t buildcaps);
 	void add_buttons_road(bool flag);
 	void add_buttons_attack();
 
@@ -392,7 +392,7 @@
 			if ((buildcaps & Widelands::BUILDCAPS_SIZEMASK) ||
 			    (buildcaps & Widelands::BUILDCAPS_MINE)) {
 				assert(igbase->get_player());
-				add_buttons_build(buildcaps, igbase->get_player()->get_playercolor());
+				add_buttons_build(buildcaps);
 			}
 
 			// Add build actions
@@ -488,7 +488,7 @@
 Add buttons for house building.
 ===============
 */
-void FieldActionWindow::add_buttons_build(int32_t buildcaps, const RGBColor& player_color)
+void FieldActionWindow::add_buttons_build(int32_t buildcaps)
 {
 	if (!m_plr)
 		return;
@@ -538,7 +538,7 @@
 
 		// Allocate the tab's grid if necessary
 		if (!*ppgrid) {
-			*ppgrid = new BuildGrid(&m_tabpanel, player_color, tribe, 0, 0, 5);
+			*ppgrid = new BuildGrid(&m_tabpanel, tribe, 0, 0, 5);
 			(*ppgrid)->buildclicked.connect(boost::bind(&FieldActionWindow::act_build, this, _1));
 			(*ppgrid)->buildmouseout.connect
 				(boost::bind(&FieldActionWindow::building_icon_mouse_out, this, _1));

=== modified file 'src/wui/waresqueuedisplay.cc'
--- src/wui/waresqueuedisplay.cc	2014-12-04 09:18:03 +0000
+++ src/wui/waresqueuedisplay.cc	2014-12-06 16:21:16 +0000
@@ -150,12 +150,10 @@
 				BlendMode::UseAlpha);
 	}
 	for (; nr_empty_to_draw; --nr_empty_to_draw, point.x += CellWidth + CellSpacing) {
-		dst.blitrect_scale_gray(
-				Rect(point.x, point.y, m_icon->width(), m_icon->height()),
-				m_icon,
-				Rect(0, 0, m_icon->width(), m_icon->height()),
-				0.5,
-				0.65);
+		dst.blitrect_scale_monochrome(Rect(point.x, point.y, m_icon->width(), m_icon->height()),
+		                              m_icon,
+		                              Rect(0, 0, m_icon->width(), m_icon->height()),
+		                              RGBAColor(166, 166, 166, 127));
 	}
 
 	if (!m_show_only) {


Follow ups