*Exactly* changing the color of a spirte

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

*Exactly* changing the color of a spirte

Post by Hexenhammer »

I have symbols in pure white (255,255,255) I want to display in various colors. I used modulate color mode but that doesn't do what I want. The symbols end up having a color *near* the color I actually set e.g. I set the color (33,40,33) but the symbol is drawn in (36,41,36). And yes I pretty clearly noticed the difference (I am picky about color). Is there a way to do exact color changes in LÖVE?
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: *Exactly* changing the color of a spirte

Post by Nixola »

You can just use the default color mode to do that, I think
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
User avatar
slime
Solid Snayke
Posts: 3131
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: *Exactly* changing the color of a spirte

Post by slime »

setColor with the modulate (default) color mode should do what you want. If not, it's a bug. How are you determining what the rgb value of the final output color is? Can you upload a .love file and screenshot demonstrating the problem?
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: *Exactly* changing the color of a spirte

Post by Hexenhammer »

slime wrote:setColor with the modulate (default) color mode should do what you want.
I looked up the color modes in the wiki after my problems and the description of "modulate" certainly doesn't sound like straight color replacement.
Images (etc) will be affected by the current color.

'modulate' works like a filter that absorbs colors that differ from the current color (possibly to a point where a color channel is entirely absorbed
Also now that I thought about it some more, that wouldn't even work in my case. I mean in straight SDL I just write "replace white with set color". I mean the symbols are loaded from a bitmap, pure white (0xffffff) symbols on a pure black background (0x000000). If modulate changed all colors of the image to the set color I would only get solid blocks of said color. I actually only want to change everything that's white in my source image to the set color..
How are you determining what the rgb value of the final output color is?
Yes, I took a screenshot to confirm my perception of difference and then compared the set color to the color that was actually displayed. The RGB values did not match. As I said, set color was (33,40,33), output color was (36,41,36)
Can you upload a .love file and screenshot demonstrating the problem?
Yes, but I would need to isolate the relevant code from the rest of the program and that would take a while. And as I said I think I actually did the wrong thing to begin with. I guess my brain somehow considered black "not a color" at that moment :?

So before I upload an example I ask, what is the correct way to change a specific color in an image? If that is even possible.
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: *Exactly* changing the color of a spirte

Post by Hexenhammer »

Here is code which demonstrates that "modulate" does indeed not replace colors with the set color but somehow mixes whatever colors are in the image with the set color.

Code: Select all

function love.load()

  -- Input.png is nothing but a square of (0xcc, 0x00, 0x1f)
  Input = love.graphics.newImage("Input.png")
  ExpectedOutput = love.graphics.newImage("ExpectedOutput.png")

end


function love.draw()

  -- Displays a square with the color (0x29, 0x00, 0x06)
  -- NOT (0x33, 0x40, 0x33)
  love.graphics.setColorMode("modulate")
  love.graphics.setColor({0x33, 0x40, 0x33})
  love.graphics.draw(Input, 10, 10)

  -- Expection was a square of (0x33, 0x40, 0x33)
  love.graphics.setColorMode("replace")
  love.graphics.draw(ExpectedOutput, 300, 300)

end
As I said I want to change one color to another. Not mix colors.
Attachments
Issue.love
Demo code
(1.17 KiB) Downloaded 92 times
User avatar
slime
Solid Snayke
Posts: 3131
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: *Exactly* changing the color of a spirte

Post by slime »

The modulate color mode is not straight color replacement - except when the color of a pixel in an image is 255,255,255. In that case, it goes something like this:

Code: Select all

(33, 40, 33) * (255, 255, 255) = ((33*255)/255, (40*255)/255, (33*255)/255) == (33*1, 40*1, 33*1) == (33, 40, 33).
There is no straight color replacement ColorMode in LÖVE, and there probably never will be. I don't think fixed-function OpenGL can even do that without some enormous kludge. There aren't many reasons to do it in the first place if you have access to the original image.

You can use a shader (PixelEffect) to do image color replacement, if you really want. It might look something like this:

Code: Select all

effect = love.graphics.newPixelEffect[[
const vec3 replaceinput = vec3(1.0, 1.0, 1.0);
const vec3 replaceoutput = vec3(33.0/255.0, 40.0/255.0, 33.0/255.0);

vec4 effect(vec4 color, Image texture, vec2 texcoord, vec2 pixcoord)
{
    vec4 texcolor = Texel(texture, texcoord);

    if (all(equal(texcolor.rgb, replaceinput)))
        texcolor.rgb = replaceoutput;

    // or less clear but maybe more performant
    // texcolor.rgb = mix(texcolor.rgb, replaceoutput, float(all(equal(texcolor.rgb, replaceinput))))

    return texcolor;
}
]]
Or you could load the image as ImageData and change it in Lua:

Code: Select all

local replaceinput = {255, 255, 255}
local replaceoutput = {33, 40, 33}

local imagedata = love.image.newImageData(myfile)

local function map(x,y,r,g,b,a)
    if r == replaceinput[1] and g == replaceinput[2] and b == replaceinput[3] then
        r, g, b = unpack(replaceoutput)
    end
    return r, g, b, a
end

imagedata:mapPixel(map)
image = love.graphics.newImage(imagedata)
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: *Exactly* changing the color of a spirte

Post by Hexenhammer »

slime wrote:The modulate color mode is not straight color replacement - except when the color of a pixel in an image is 255,255,255.
Strange. I changed the color of the Input.png square to 255,255,255 and it did indeed work. However, my symbol bitmap is also 255,255,255 and the output is all wrong. I cannot reproduce this problem in an isolated example. I guess there must be an issue somewhere else..
There is no straight color replacement ColorMode in LÖVE, and there probably never will be. I don't think fixed-function OpenGL can even do that without some enormous kludge.
Okay, thanks for the explanation!
You can use a shader (PixelEffect) to do image color replacement, if you really want. It might look something like this:

Code: Select all

effect = love.graphics.newPixelEffect[[
const vec3 replaceinput = vec3(1.0, 1.0, 1.0);
const vec3 replaceoutput = vec3(33.0/255.0, 40.0/255.0, 33.0/255.0);

vec4 effect(vec4 color, Image texture, vec2 texcoord, vec2 pixcoord)
{
    vec4 texcolor = Texel(texture, texcoord);

    if (all(equal(texcolor.rgb, replaceinput)))
        texcolor.rgb = replaceoutput;

    // or less clear but maybe more performant
    // texcolor.rgb = mix(texcolor.rgb, replaceoutput, float(all(equal(texcolor.rgb, replaceinput))))

    return texcolor;
}
]]
I see, thanks again.
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: *Exactly* changing the color of a spirte

Post by Hexenhammer »

Hexenhammer wrote: Strange. I changed the color of the Input.png square to 255,255,255 and it did indeed work. However, my symbol bitmap is also 255,255,255 and the output is all wrong. I cannot reproduce this problem in an isolated example. I guess there must be an issue somewhere else..
Found it. Had nothing to do with LÖVE. One of the numbers in my code was off by 1, that caused all the problems.
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: *Exactly* changing the color of a spirte

Post by Taehl »

In my humble opinion, you should give your image font an appropriate alpha layer (ie., alpha -> from brightness), fill the image with white (unless you want outlines or something), and use normal alpha blending mode. Using modulate blend mode just to get rid of a black background is not how to do it. To use alpha, you'll need to make your image a .png.
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: *Exactly* changing the color of a spirte

Post by Hexenhammer »

Taehl wrote:In my humble opinion, you should give your image font an appropriate alpha layer (ie., alpha -> from brightness), fill the image with white (unless you want outlines or something), and use normal alpha blending mode. Using modulate blend mode just to get rid of a black background is not how to do it. To use alpha, you'll need to make your image a .png.
You misunderstood what I want to do here. I don't want to get rid of the black background, the symbols are drawn on black, I just want to draw them in various colors. And my original method actually worked fine, as I said just one of the numbers was off by 1 which caused the selection of the wrong color.

What I am doing here is emulating a glorified textmode for a roguelike which allows me to use custom colors and symbols. The end result looks like this:

Image

I do this by first creating a "symbol atlas" containing all symbols in all colors and then I quad from there into a sprite batch which eventually gets draw. This is nicely efficient. I get about 1000 FPS drawing >8000 differently colored symbols.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 2 guests