Changing image color

Hi guys, I’m learning to code with Codea by doing simple projects. Now I’m doing super easy DVD screen saver, if you remember… :smile:

I’m trying to change a color of the sprite. The source is PNG file with alpha, but could not find anything in Codea documentation about colors of the image. Thanks for help!

@romanmastalir As far as I know, there’s not an easy way to change the individual colors of a sprite. There’s the tint command, but that changes the tint of the whole sprite. I’ll look around an see if I can find something.

If it’s this you are after:

https://youtu.be/5mGuCdlCcNM

Then it should be straightforward using the tint command as @dave1707 says - assuming your input sprite image is black and white.

Here you go:


-- DVD Screen
displayMode(FULLSCREEN)
-- Use this function to perform your initial setup
function setup()    
    pos=vec2(WIDTH/2,HEIGHT/2)
    col=color(math.random(255),math.random(255),math.random(255))
    xspd=2
    yspd=2
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color
    background(40, 40, 50)
    tint(col)
    sprite(asset.builtin.Cargo_Bot.Menu_Button,pos.x,pos.y)
    pos.x = pos.x + xspd
    pos.y = pos.y + yspd
    if pos.x>WIDTH-90 or pos.x<90 then
        xspd = xspd * -1
        col=color(math.random(255),math.random(255),math.random(255))
    end
    if pos.y>HEIGHT-25 or pos.y<25 then
        yspd = yspd * -1
        col=color(math.random(255),math.random(255),math.random(255))
    end
end

I just threw this together. It’s probably not what you want but it looked interesting. Maybe someone can use it for something.

function setup()
    r1,g1,b1,a1=0,0,0,0
    parameter.integer("r1",0,255,recolor)
    parameter.integer("g1",0,255,recolor)
    parameter.integer("b1",0,255,recolor)    
end

function draw()
    background(0)
    sprite(img1,WIDTH/2,HEIGHT/2,200)
end

function recolor()
    img1=readImage(asset.builtin.Small_World.Tower)    
    iw=img1.width
    ih=img1.height
    for x=1,iw do
        for y=1,ih do
            r,g,b,a=img1:get(x,y)
            r=r-r1
            g=g-g1
            b=b-b1
            img1:set(x,y,r,g,b,a)
        end
    end    
end

Thank you guys! It works now. The image has to be white to tint it, but works well. One additional small question. How to change size of the sprite? The original image is too big, scale function just scaled everything. Is that possible?

@romanmastalir In the sprite command, after the x,y values, you can put a value that scales the sprite itself. Try different values to get the size you want.

PS. If you put the width and height of the sprite, then it’s the original size. If you double the sizes, then the sprite is twice the width and height.

To properly change colours of a sprite you should use a shader. Going through pixels one by one is incredibly slow compared to how shaders work - they essentially do all pixels in one go.

I could throw together a simple colour-changing shader if that would be of interest to anyone as an example.

yes please

Okay, here is one. The shader is part of the file, so it’s a single program. Scroll to the end for the shader stuff.

-- FragmentShader

function setup()
    local s = "Cargo Bot:Codea Icon"
    local w,h = spriteSize(s)
    m = mesh()
    m:addRect(WIDTH/2,HEIGHT/2,w,h)
    m.texture = s
    m.shader = getShader()
end

function draw()
    background(40,40,50)
    m:draw()
end

function getShader()
    return shader([[
//
// A basic vertex shader
//

//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;

//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;

//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    //Pass the mesh color to the fragment shader
    vColor = color;
    vTexCoord = texCoord;
    
    //Multiply the vertex position by our combined transform
    gl_Position = modelViewProjection * position;
}

]],[[
//
// A basic fragment shader
//

//Default precision qualifier
precision highp float;

//This represents the current texture on the mesh
uniform lowp sampler2D texture;

//The interpolated vertex color for this fragment
varying lowp vec4 vColor;

//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
{
    //Sample the texture at the interpolated coordinate
    lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
    //Set the output color to the texture color
    
    //Here's where we can mess around with the sprite's colours
    // uncomment one of the following to see what it does
    // <- is how to do comments
    
    // swapsies
    //col.rgb = col.gbr;
    
    // all grey
    //col.rgb = vec3(.35*col.r + .4*col.g + .25*col.b);
    
    // leave out the blues
    //col.b = 0.;
    
    //inversion
    // note the decimal point here
    //col.rgb = 1.-col.rgb;
    
    // darken
    //col.rgb *= col.rgb;

    // Interestingly, I want to do 4x(1-x) here, but it complains
    // about the 4 because it worries about loss of precision
    // but it's fine doing it by repeated addition
    //col.rgb *= (1. - col.rgb);
    //col.rgb += col.rgb;
    //col.rgb += col.rgb;
    
    
    
    
    gl_FragColor = col;
}

]])
end