create spectrum using kivy texture

Question:

According to Kivy docs, this piece of code can be used to create a gradient from black and white. How does one create a spectrum using kivy textures?
I’ve been trying manipulating the samples variables but all I got is a gradient between only two color.

texture = Texture.create(size=(64, 64))

# create 64x64 rgb tab, and fill with values from 0 to 255
# we'll have a gradient from black to white
size = 64 * 64 * 3
buf = [int(x * 255 / size) for x in range(size)]
buf = b''.join(map(chr, buf))
texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
with self.canvas:
    Rectangle(texture=texture, pos=self.pos, size=(64, 64))

Something like this

Asked By: Juggernaut

||

Answers:

With some inspiration from this, I ended up with this code and this result.

from itertools import chain

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture


class MyWidget(Widget):
    def __init__(self, **args):
        super(MyWidget, self).__init__(**args)

        self.texture = Texture.create(size=(5, 1), colorfmt="rgb")
        pixels = bytes([int(v * 255) for v in chain((0, 0, 0, 1), (0, 0, 0, 1))])
        buf = ''.join(pixels)
        self.texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
        with self.canvas:
            Rectangle(pos=self.pos, size=self.size, texture=self.texture)


class TestApp(App):
    def build(self):
        return MyWidget(size=(368, 512))


if __name__ == '__main__':
    TestApp().run()

The trick is to try to display a texture bigger than its size.
result

Answered By: Juggernaut

You can make a nested loop for that.
If you loop trough the pixels, and set the color.
The easiest thing would be to use hsv, and then convert to rgb.
So the outer loop sets the v (value), since that will be each row changing.
Inner loop will be the h (hue), each pixel in the row.
You can do something like this.

from kivy.app import App
from kivy.graphics.texture import Texture
from kivy.graphics import Rectangle
from kivy.uix.boxlayout import BoxLayout
from colorsys import hsv_to_rgb


class MyLayout(BoxLayout):

    def __init__(self,**kwargs):
        super(MyLayout,self).__init__(**kwargs)
        w = 64
        h = 64
        texture = Texture.create(size=(w, h))
        buf = []

        for i in range(h):
            for j in range(w):
                color = hsv_to_rgb(j/float(w),1,i/float(h)) # colorsys takes (0,0,0) to (1,1,1)
                pixel = [int(a*b) for a,b in zip(color,[255,255,255])] # since color goes from (0,0,0) to (1,1,1), we multiply by 255
                buf.extend(pixel)   

        buf = b''.join(map(chr, buf))
        texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
        with self.canvas:
            Rectangle(texture=texture, pos=self.pos, size=(w, h))


class MyApp(App):

    def build(self):
        return MyLayout()


if __name__ == "__main__":
    MyApp().run()
Answered By: el3ien
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.