Forum Archive

Is it possible to tint iconicons using scene.image?

inoddy

When using scene.image to draw iconicons they appear black. Using scene.tint makes no difference. I would like them to appear blue. Any ideas?

A workaround is to use ui Buttons. But it seems overkill to use buttons just to draw a passive icon.

from scene import *

class MyScene (Scene):

    def draw(self):
        background(1, 1, 0)
        tint(0, 0, 1)
        image('ionicons-checkmark-circled-32', 300, 300)

run(MyScene())
JadedTuna

@inoddy, maybe you can use PIL.Image to load that image and then tint it using some PIL functions?

inoddy

Did you have something specific in mind? I tried this:

from scene import *
from PIL import Image
from PIL import ImageOps

class MyScene (Scene):

    def draw(self):
        background(1, 1, 0)
        tint(0, 0, 1)
        img = Image.open('ionicons-arrow-down-c-32').convert('L')
        img = ImageOps.colorize(img, 'blue', 'white').convert('RGBA')
        img = load_pil_image(img)
        image(img, 300, 300)

run(MyScene())

but it coloured the whole box blue instead of the part of the icon that I wanted blue. I hope there's something better than grabbing all the pixels and changing them individually.

Sebastian

The only way I know how to do this, is to loop over all of the pixels :P

from scene import *
from PIL import Image

class MyScene (Scene):
    def setup(self):
        img = Image.open('ionicons-arrow-down-c-32').convert('RGBA')
        pixeldata = img.load()
        for y in xrange(img.size[1]):
            for x in xrange(img.size[0]):
                if pixeldata[x, y] != (0,0,0,0):
                    r, g, b, a = pixeldata[x, y]
                    pixeldata[x, y] = (0, 0, 255, a)
        self.img = load_pil_image(img)

    def draw(self):
        background(1,1,0)
        image(self.img, 300, 300)

run(MyScene())
inoddy

That works quite well (if a little slow - precaching is a good idea).

I still can't help thinking that there is a better way since ui seems to do it quickly.

Thanks for the help.

JonB

Numpy would be much faster, if you want to do it pixel wise.
http://stackoverflow.com/questions/384759/pil-and-numpy

I'm no PIL expert, but check out the ImagePalette module. You might need to convert to black and white first, or quantize, etc, then it seems like you may be able to directly modify the palette.

Another possibility would be to use ImageMath, but the documentation doesn't seem great there...

inoddy

This works

from scene import *
from PIL import Image

class MyScene (Scene):
    def setup(self):
        img = Image.open('ionicons-arrow-down-c-256').convert('RGBA')
        red, green, blue, alpha = img.split()
        img = Image.merge('RGBA', (red, green, alpha, alpha))
        self.img = load_pil_image(img)

    def draw(self):
        background(1,1,0)
        image(self.img, 300, 300)

run(MyScene())

It's still a bit inefficient. The ionicon is opened as an LA image. I convert it to RGBA because Image.split() does not work with LA images - it would be good if I could extract the alpha without the RGB conversion.