Farbverlauf

Fragen zu Tkinter.
Antworten
jmurauer
User
Beiträge: 8
Registriert: Mittwoch 22. November 2006, 14:31

Hallo,
ich weiß zwar nicht, ob ich hier dafür richtig bin, aber vielleicht funktioniert es ja.

Ich muss einen Farbverlauf bauen. D.h. in einem canvas erzeuge ich Rechtecke und gehen denen eine Farbe mit fill = "#aabbcc" oder so weiter.

Mein Problem: ich möchte diese Farben den natürlichen, physikalschen Farben, so wie die von der Sonne kommen (ganz schwarz bis ganz weiß und dazwischen alle möglichen anderen Farben) nachbilden. D.h. so etwas wie das Auge die Wellenlänge "sieht".

Wenn ich annehme, meine Farbenzahle gehen von 0 bis 100, also von schwarz bis weiß, mit welchem Algo ordne ich sie dann dem fill-Wert zu?

Danke
Benutzeravatar
Arthur
User
Beiträge: 23
Registriert: Sonntag 12. November 2006, 18:07

ich würds in etwa so machen:

Code: Alles auswählen

for x in range[0, 265]:

root=Tk()

canvas=Canvas(root, width=100, height=256)
canvas.grid()

for x in range(0, 256):
    y=list(hex(x))
    y[:2]=''          #pyhton hängt immer ein 0x for die hexadezimlae zahl, das muss weg
    if len(y)==1:
        y=['0']+y
    a=''
    for z in y:       #Rückumwandelung in einen String
        a=a+z
    y=a
    canvas.create_line(0, x, 100, x, fill='#'+y+y+y)
für andere farbmischungen musste am besten einen wert konstan lassen oder so

[/code]
jmurauer
User
Beiträge: 8
Registriert: Mittwoch 22. November 2006, 14:31

Danke für die rasche Antwort, aber das war nicht das Problem - ich habe leider meine Frage sehr ungenau formuliert.

Es geht um so etwas wie die Farbtemperatur: Als Input habe ich eine Zahl (Farbtemperatur) und ich möchte den dazugehörigen Farbwert der Form #aabbcc ermitteln. Dann kann ich das Ding auch zeichnen.

In der Wikipedia findet man hier näheres
http://de.wikipedia.org/wiki/Farbtemperatur

Siehe dazu den färbigen Balken. Mein Input ist also z.B. 4000 (oder eine andere Zahl, die ich dann auf 4000 umrechnen) und ich möchte #aabbcc so, dass es eben dieses hellgelb ergibt.
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

Hi jmurauer,
gibt es da nur rot, gelb, weiß und blau?
Dann würde ich irgendwie die vier Farben Farbe definieren, zu jeder Farbe den Zahlenbereich in dem sie vorkommt(bei rot also 1800-4000), und dann gucken, in welchem Bereich der Wert liegt: Ist er z.B. 3000, musst du halt ne mischung zwischen dem gelb- und dem rot-wert berechnen. Falls du noch ein bisschen mit den Werten spielen möchtest, nimm doch einfach tkColorChooser, da kann man Werte oder Farbe einstellen, und erhält das andere.
Gruß, jj

ps:
jmurauer hat geschrieben:Siehe dazu den färbigen Balken. Mein Input ist also z.B. 4000 (oder eine andere Zahl, die ich dann auf 4000 umrechne[n]) und ich möchte #aabbcc so, dass es eben dieses hellgelb ergibt
--> oder willst du immer gelb rauskriegen? :wink:
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Ich glaube, das könnte Dir helfen: http://www.fourmilab.ch/documents/specrend/specrend.c. Ist zwar in C und sieht sehr komplex aus, es dürfte aber einfach sein, einen Python-Wrapper zu schreiben, der die RGB-Werte aus der Temperatur berechnet. Als Anleitung könnte die main()-Routine des Programms dienen.
MfG
HWK
jmurauer
User
Beiträge: 8
Registriert: Mittwoch 22. November 2006, 14:31

Danke,
dass ist ein Volltreffer!!!
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das freut mich. Wenn Du den Code für den Farbverlauf fertig hast, wäre es schön, wenn Du ihn ins Forum stellen würdest. Mich interessiert das jedenfalls.
MfG
HWK
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Ich hab's mal selbst probiert:
Die main()-Funktion von 'specrend.c' habe ich folgendermaßen ersetzt:

Code: Alles auswählen

int PASCAL __export colspec(int temp)
{
    int t;
    double x, y, z, r, g, b;
    struct colourSystem *cs = &SMPTEsystem;
    bbTemp = temp;
    spectrum_to_xyz(bb_spectrum, &x, &y, &z);
    xyz_to_rgb(cs, x, y, z, &r, &g, &b);
    constrain_rgb(&r, &g, &b);
    norm_rgb(&r, &g, &b);
    t = (unsigned char)(255 * r);
    t <<= 8;
    t += (unsigned char)(255 * g);
    t <<= 8;
    t += (unsigned char)(255 * b);
    return t;
}
Danach habe ich mit Watcom 'colspec.dll' erzeugt. Das Python-Script zum Testen sieht so aus:

Code: Alles auswählen

import ctypes

from Tkinter import *


class ShowColSpec:
    def __init__(self, parent):
        colspec = ctypes.WinDLL('colspec')
        temp1 = 1000
        temp2 = 10000
        width = 1000
        height = 100
        canvas = Canvas(parent, width=width, height=height, bg='white')
        canvas.pack(expand=YES, fill=BOTH)
        for i in range(width + 1):
            temp = i * (temp2 - temp1) / width + temp1
            rgb = colspec.colspec(temp)
            canvas.create_line(i, 0, i, height, fill='#%06X' % rgb)


if __name__ == '__main__':
    root = Tk()
    root.title('Farbspektrum')
    ShowColSpec(root)
    root.mainloop()
Die Ausgabe entspricht aber nicht wirklich den bekannten Farbspektren.
Schade eigentlich
HWK
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das sieht schon besser aus:
Ich habe zusätzlich folgende Funktionen eingefügt:

Code: Alles auswählen

void lambda_to_xyz(int lambda, double *x, double *y, double *z)
{
    int i, j;
    i = (lambda - 380) / 5;
    j = (lambda - 380) % 5;
    *x = (cie_colour_match[i + 1][0] * j + cie_colour_match[i][0] * (5 - j)) / 5;
    *y = (cie_colour_match[i + 1][1] * j + cie_colour_match[i][1] * (5 - j)) / 5;
    *z = (cie_colour_match[i + 1][2] * j + cie_colour_match[i][2] * (5 - j)) / 5;
}
int PASCAL __export colspec2(int lambda)
{
    int t;
    double x, y, z, r, g, b;
    struct colourSystem *cs = &SMPTEsystem;
    lambda_to_xyz(lambda, &x, &y, &z);
    xyz_to_rgb(cs, x, y, z, &r, &g, &b);
    constrain_rgb(&r, &g, &b);
    norm_rgb(&r, &g, &b);
    t = (unsigned char)(255 * r);
    t <<= 8;
    t += (unsigned char)(255 * g);
    t <<= 8;
    t += (unsigned char)(255 * b);
    return t;
}
'colspec' wurde in 'colspec1' umbenannt.
Das Test-Script sieht dann so aus:

Code: Alles auswählen

import ctypes

from Tkinter import *


class ShowColSpec:
    def __init__(self, parent):
        colspec = ctypes.WinDLL('colspec')
        lambda1 = 380
        lambda2 = 779
        temp1 = 1000
        temp2 = 10000
        width = 1000
        height = 100
        canvas = Canvas(parent, width=width, height=height, bg='white')
        canvas.pack(expand=YES, fill=BOTH)
        for i in range(width + 1):
            temp = i * (temp2 - temp1) / width + temp1
            rgb = colspec.colspec1(temp)
            canvas.create_line(i, 0, i, height / 2, fill='#%06X' % rgb)
        for i in range(width + 1):
            lambda_ = i * (lambda2 - lambda1) / width + lambda1
            rgb = colspec.colspec2(lambda_)
            canvas.create_line(i, height / 2 + 1, i, height, fill='#%06X' % rgb)


if __name__ == '__main__':
    root = Tk()
    root.title('Farbspektrum')
    ShowColSpec(root)
    root.mainloop()
MfG
HWK
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Und so geht es ganz einfach:

Code: Alles auswählen

#!/usr/bin/python
# File: colspec.py
# Script zur Darstellung eines Farbspektrums

from Tkinter import *


class ShowColSpec:
    def __init__(self, parent):
        height = 50
        width = 6 * 256
        canvas = Canvas(parent, width=width, height=height, bg='white')
        canvas.pack(expand=YES, fill=BOTH)
        for i in range(256):
            canvas.create_line(i, 0, i, height, fill='#%02X00FF' % (255 - i))
        for i in range(256):
            canvas.create_line(i + 256, 0, i + 256, height,
                               fill='#00%02XFF' % i)
        for i in range(256):
            canvas.create_line(i + 512, 0, i + 512, height,
                               fill='#00FF%02X' % (255 - i))
        for i in range(256):
            canvas.create_line(i + 768, 0, i + 768, height,
                               fill='#%02XFF00' % i)
        for i in range(256):
            canvas.create_line(i + 1024, 0, i + 1024, height,
                               fill='#FF%02X00' % (255 - i))
        for i in range(256):
            canvas.create_line(i + 1280, 0, i + 1280, height,
                               fill='#FF00%02X' % i)


if __name__ == '__main__':
    root = Tk()
    root.title('Farbspektrum')
    ShowColSpec(root)
    root.mainloop()
MfG
HWK
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Bei den letzten Varianten habe ich mich leider ganz auf die Ausgabe eines kompletten Spektrums konzentriert. Deshalb jetzt noch eine Variante, die für einen Indexwert die Farbe als RGB zurückliefert. Der Index liegt hier zwischen 0 und 1535, kann aber natürlich beliebig angepasst werden.

Code: Alles auswählen

#!/usr/bin/python
# File: ind2col.py
# Script zur Darstellung eines Farbspektrums

def ind2col(ind):
    ind %= 6 * 256
    i, j = divmod(ind, 256)
    a = 0x10000 >> (8 * (i % 3))
    if i & 1:
        b = j
    else:
        b = 255 -j
    c = 0xFF << (8 * (i / 2))
    return a * b + c

if __name__ == '__main__':
    from Tkinter import *
    root = Tk()
    root.title('Farbspektrum')
    height = 50
    width = 6 * 256 / 2
    canvas = Canvas(root, width=width, height=height, bg='white')
    canvas.pack(expand=YES, fill=BOTH)
    for i in range(width):
        canvas.create_line(i, 0, i, height, fill='#%06X' % ind2col(2 * i))
    root.mainloop()
MfG
HWK
Antworten