Entwickler-Ecke

Multimedia / Grafik - Farbvergleich


dude - Di 08.04.03 20:05
Titel: Farbvergleich
Hiho,

ich hätte da mal eine etwas komplexere Frage:

Ich will sozusagen einen Farbvergleich bauen.
Das Programm nimmt die Pixelfarbe eines Bildes (schwarz-weiss).
Ich will nun die Weiss-Schwarz Pallette mit einer Schwarz-Grün Palette verrgleichen. d.h

Graustufen : | dunkelgrau | leichteshellgrau | grau | hellgrau | ...
----------------------------------------------------------------------------
Grünstufen : | dunkelgrün | leichteshellgrün | grün | hellgrün | ...

das heisst, wenn die pixelfarbe ein bestimmtes grau ist, dann soll die andere farbe proportional die entsprechende grau sein.

Da habe ich ein Problem:

Wie erstelle ich eine Farbpallette, bei denen man manuell eine Farbvermischung programmieren kann.

Dann, wie vergleiche ich diese, dass sie im gleichen verhätnis sind (bloss andere Farbe?)

Mfg, dude


MKehrer - Mi 09.04.03 09:23

Hi dude,

das mußt du die farben in ein anderes Farbschema konvertieren.
Dort kannst Du diese Vergleiche machen.

TColor ist im RGB-Farbschema (siehe OH)
Für Deine Vergleiche braucht Du glaub ich das HSB-Schema.

Dort wird eine Farbe durch Farbtyp, Helligkeit und Sättigung ausgedrückt.

Wie man umrechnet findest Du im Internet.

Manfred


Gausi - Mi 09.04.03 09:58

@MKehrer: So ne Umrechnung hab ich auch mal verzweifelt gesucht, ich habe aber keine vernünftige gefunden. Wo gibts die?

@dude: Ich weiss nicht, ob das mit Delphi klappt, hab mal ein ähnliches Programm für DOS mit TP geschrieben. Da hab ich bmp's bearbeitet

Bei Grautönen sind alle drei Farbwerte gleich (z.B. R=127, G=127, B=127). Wenn du den Grünteil um einen bestimmten Wert erhöhst (evtl. prozentual) und die beiden anderen ggf. etwas erniedrigst, bekommst du ein mehr oder weniger helles grün.


MKehrer - Mi 09.04.03 10:54

@Gausi
Ich hab da mal vor Jahren schon Konvertierungsfunktionen geschrieben.
ungefähr so:


Quelltext
1:
2:
TRGBColor = record r,g,b:Byte End;
  THSBColor = record h,s,b:Byte End;


und dann

Quelltext
1:
2:
  Function HSBToRGB 
  Funcrion HSBToTColor .....


liegt bei zu Hause irgendwo rum
Die Berechnungsgrundlagen hab ich aus dem Internet
vielleicht find ichs heute, dann poste ich es morgen hier.


dude - Mi 09.04.03 15:10

ja das wäre gut, wenn ich ein beispiel sage - weil solche wörter sagen mir zum teil nix.
Eigentlich brauch ich ja auch nur eine funktion, die mir eine grau farbe in einen gleich hellen grünwert umrechnet. Da ist deine Methode (soweit ich verstanden hab) auch nützlich und ein bisschen übersichtlicher.

I'm watin..


MKehrer - Do 10.04.03 08:22

@Dude,Gausi.
Ich hab´s natürlich vergessen, hoffentlich denke ich heute dran.

Aber hier ist alles beschrieben:

http://www.ufg.ac.at/zid/public_html/funk/medientechnik/material/Umrechnung_zwischen_Farbraeumen.pdf

Der rest ist schnell codiert.
Zum Verständnis von H,S und B eignet sich ein herkömmlicher Farbdialog von Windows, Delphi oder einer Bildverarbeitungssoftware ganz gut.
Einfach etwas rumspielen.


dude - Do 10.04.03 13:18

schön, bloß bringt mir diese Farberklärung nix:

1.Was ich brauch ist, eine visuelle -> lineare <- Farbpallette die von Schwarz nach weiss verläuft.
2.Dann muss ich von einem Pixel ablesen können, welchen Farbwert er hat.
3.Den muss ich dann mit der ->linaren<- Farbpallette vergleichen.
4. Von der Tabelle bekomm ich dann einen Wert heraus.
5. Dieser Wert sollte ich mit der neu erzeugten ->linearen<- Frabpallette (die von schwarzbis grün geht) vergleichen.
6. So dass ich im Endeffekt einen gleichhellen GrünTon herausbekommen habe, mit dem ich dann nacher bequem auf Canvas malen kann.

Ach ja, und zu allem sollte eine verständlich Erklärung sein (mit Beispiel).
Ok, ich stell ein wenig viele Anforderungen...


MKehrer - Do 10.04.03 13:35

Hi Dude,

ich weiß nicht wo Dein Problem ist

Nimm den Colordialog von Delphi
setze Farbe auf 80 und Sättigung auf 240

jetzt kannst Du rechts and der Helligkeit schrauben
wenn du nur schwarz bis grün haben willst mußt du halt den Hellwert auf 120 statt 240 skalieren.

Der Hellwert ist glaube ich (R+G+B)/3
( Für dich dann (R+G+B)/6 )

Der Rest ist leicht codiert wenn Du Die Umrechnungen hast.


Gausi - Do 10.04.03 15:28

@mkehrer:
So ähnliche Dokumente hab ich haufenweise gefunden. Auch die Umrechnungsformel am Ende kommt mir ziemlich bekannt vor. Problem damals war, dass die Werte, die ich da ausrechne, in keiner Weise mit den Werten übereinstimmen, die bei dem megatollensuper-mspaint rauskamen. Vermutlich ist es aber so, das mspaint da mist baut. Ist aber auch egal, trotzdem danke.

@dude: Bist du sicher, dass deine neue Farbpalette von schwarz bis grün geht? Ich würde eher eine nehmen, die ebenfalls von weiss nach schwarz geht, aber eben nicht über graustufen, sondern über grünstufen.


MKehrer - Do 10.04.03 15:37

@Gausi

oft stimmt die softwaretechnische umsetzung mit der Theorie nicht überein.
Der Farbraum in HSB ist rotsymetrisch
Der Farbtyp hat demzufolge [0..360] in der Software hat er aber meist [0..255]
genauso die helligkeit manchmal [0..240] oder [0..255]
Wenn man das beachtet und weiss was man will, dann geht´s ganz gut.

Ich bring meine func´s morgen mit, wenn ich´s nicht wieder vergesse.


MKehrer - Fr 11.04.03 08:39

Hurra ich hab´s nicht vergessen :D

Hier ist die ganze Unit
Hab ich seit Jahren nicht nicht mehr angeschaut, müsste aber gehen


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
type
  TRGBColor = Record Red,Green,Blue:Byte; End; //0..255 jeweils
  THSLColor = Record Hue,Sat,Light:Byte; End;    // Hue = 0..239; Sat,Light =0..240

Function RGB(R,G,B:Byte):TRGBColor;
Function HSL(H,S,L:Byte):THSLColor;
Function RGB2Color(c:TRGBColor):TColor;
Function Color2RGB(c:TColor):TRGBColor;
Function RGB2HSL(c:TRGBColor):THSLColor;
Function HSL2RGB(c:THSLColor):TRGBColor;
Function HSL2Color(c:THSLColor):TColor;
Function Color2HSL(c:TColor):THSLColor;

implementation

Function RGB(R,G,B:Byte):TRGBColor;
//-------------------------------------------------
Begin
  Result.Red:=R; Result.Green:=G; Result.Blue:=B;
End;

Function HSL(H,S,L:Byte):THSLColor;
//-------------------------------------------------
Begin
  Result.Hue:=H; Result.Sat:=S; Result.Light:=L;
End;


Function RGB2Color(c:TRGBColor):TColor;
//-------------------------------------------------
Begin
  Result:=$02000000+65536*c.Blue+256*c.Green+c.Red;
End;

Function Color2RGB(c:TColor):TRGBColor;
//-------------------------------------------------
Begin
  Result.Red:=LoByte(LoWord(c));
  Result.Green:=HiByte(LoWord(c));
  Result.Blue:=LoByte(HiWord(c));
End;

Function RGB2HSL(c:TRGBColor):THSLColor;
//-------------------------------------------------
Var H,S,L,R,G,B,maxi,mini :Double;
Begin
  H:=9999;  //Hinweis unterdrücken
  With c do begin R:=Red/255; G:=Green/255; B:=Blue/255; End;
  maxi:=Max(Max(R,G),B);
  mini:=Min(Min(R,G),B);
  L:=(maxi+mini)/2;//(R+G+B)/3;
  If Maxi=Mini then With Result do Begin Light:=Round(255*L); Sat:=0; Hue:=0; Exit; End;
  If L<=0.5
      then S:=(maxi-mini)/(maxi+mini)
      else S:=(maxi-mini)/(2-maxi-mini);
  If R=maxi then H:=(G-B)/(maxi-mini);
  If G=maxi then H:=2+(B-R)/(maxi-mini);
  If B=maxi then H:=4+(R-G)/(maxi-mini);
  H:=H*40;  //von 0..6 auf 0..240 skaliert
  If H<0 then H:=H+240;
  Result.Hue:=Round(H);
  Result.Sat:=Round(240*S);
  Result.Light:=Round(240*L);
End;

Function HSL2RGB(c:THSLColor):TRGBColor;
//-------------------------------------------------
Var H,S,L,R,G,B,m1,m2 :Double;
  Function Value(n1,n2,h:Double):Double;
  Var hue,v:Double;
  Begin
    hue:=h;
    v:=9999;  //Hinweis unterdrücken
    If hue>360 then hue:=hue-360;
    If hue<0   then hue:=hue+360;
    If hue<60 then v:=n1+(n2-n1)*hue/60;
    If (hue>=60) and (hue<180) then v:=n2;
    If (hue>=180) and (hue<240) then v:=n1+(n2-n1)*(240-hue)/60;
    If hue>=240 then v:=n1;
    Result:=v;
  End;
Begin
  H:=c.Hue*360/240; S:=c.Sat/240; L:=c.Light/240;
  If S=0 then With Result Do Begin Red:=Round(255*L); Green:=Round(255*L); Blue:=Round(255*L); Exit; End;
  If L<=0.5
     then m2:=L*(1+S)
     else m2:=L+S-L*S;
  m1:=2*L-m2;
  R:=Value(m1,m2,H+120);
  G:=Value(m1,m2,H);
  B:=Value(m1,m2,H-120);
  Result.Red:=Round(255*R);
  Result.Green:=Round(255*G);
  Result.Blue:=Round(255*B);
End;

Function HSL2Color(c:THSLColor):TColor;
//-------------------------------------------------
Begin
  Result:=RGB2Color(HSL2RGB(c));
End;

Function Color2HSL(c:TColor):THSLColor;
//-------------------------------------------------
Begin
  Result:=RGB2HSL(Color2RGB(c));
End;


dude - Di 15.04.03 12:53

danke !

jetzt muss ich mich nur noch in quelltext einarbeiten...stöhn.


dude - Di 15.04.03 13:43

hätte da mal eine frage:

Was bedeutet dieser Quelltext Teil ?

Quelltext
1:
2:
3:
4:
5:
Function RGB2Color(c:TRGBColor):TColor; 
//------------------------------------------------- 
Begin 
  Result:=$02000000+65536*c.Blue+256*c.Green+c.Red; 
End;

Was ist 65536 ?
Und für was muss man dies mit der Farbe Schwarz addieren ?


Und dann noch:

Die Befehle Min, Max im Teil

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Function RGB2HSL(c:TRGBColor):THSLColor; 
//------------------------------------------------- 
Var H,S,L,R,G,B,maxi,mini :Double; 
Begin 
  H:=9999;  //Hinweis unterdrücken 
  With c do begin R:=Red/255; G:=Green/255; B:=Blue/255; End; 
  maxi:=Max(Max(R,G),B); 
  mini:=Min(Min(R,G),B); 
  L:=(maxi+mini)/2;//(R+G+B)/3;

funktionieren nicht. Es kommt ein Fehler:

[Fehler] farbenschau.pas(69): Undefinierter Bezeichner: 'Max'
[Fehler] farbenschau.pas(70): Undefinierter Bezeichner: 'Min'
[Fataler Fehler] farbenschauproject.dpr(5): Verwendete Unit 'farbenschau.pas' kann nicht compiliert werden

Sorry, aber es ist mein erstes richtiges Farbenprogrammieren, udn deswegen hab ich noch keine Ahnung davon.


worm - Sa 19.04.03 21:53

Nimm dir mal 'ne Form und setz 'ne Scrollbar und zwei Labels rein. Bei den Labels Autosize auf False und ein bisschen größer machen, und bei der Scrollbar Max auf 255 und dann diesen Code für OnChange:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TForm1.ScrollBar1Change(Sender: TObject);
const
  HellGruenR = 128;
  HellGruenG = 255;
  HellGruenB = 128;

  function Grau(hell: Byte): TColor;
  begin
    //Result := RGB(hell, hell, hell);
    Result := (hell) or (((hell shl 8) or hell) shl 8);
  end;

  function Gruen(hell: Byte): TColor;
  begin
    Result := RGB((HellGruenR * hell) shr 8,
                  (HellGruenG * hell) shr 8,
                  (HellGruenB * hell) shr 8);
  end;

begin
  Label1.Color := Grau(ScrollBar1.Position);
  Label2.Color := Gruen(ScrollBar1.Position);
end;
Ist das das, was Du wolltest? Über die Konstanten HellGruenR etc kannst Du einstellen, wie genau dein Hellgrün jetzt aussehen sollte.
Von grau zu grün kannst Du dann konvertieren mit DieGrueneFarbe := Gruen(Byte(DeineGraueFarbe));
Hoffe, das hilft dir weiter!
Cya, f0k AKA worm