Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: So 16.11.03 14:09 
Ist wesentlich komplizierter, als es sich im Titel anhört.
Ich schreibe an einem Programm, was u.a. ermöglichen soll, bei Bildern die "Sättigung" und die "Farbe" zu ändern. Sättigung klappt, Problem ist die Änderung der Farbe, ohne dabei die phys. Helligkeit und die Sättigung der Farbe zu ändern.
Ich orientiere mich im wesentlichen an den Erläuterungen hier:
home.arcor.de/ulile/node52.html

Eine Änderung der Farbe eines Pixels entspricht also einer Drehung des Pixels um die Raumdiagonale (0,0,0 / 255,255,255) im RGB-Würfel. Ich weiss aus der Schule, wie ich einen Punkt um eine der Koordiantenachsen (hier heissen die nicht x,y,z, sondern r,g,b).
Ich kann die Raumdiagonale so drehen, dass sie auf eine der Achsen (z.B. R) fällt. Wenn ich den so mitgedrehten Pixel dann um Winkel Alpha um die R-Achse drehe, und anschliessend die vorigen Drehungen rückgängig mache (um den entsprechenden Winkel zurückdrehen), dann habe ich (nach meiner Überlegung) eine Drehung um die Diagonale um Alpha berechnet.
Folgenden Quelltext habe ich, wobei die Trackbar von 0 bis 360 geht

ausblenden volle Höhe Delphi-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:
const
    cos45:real = 0.707106781186548;
    sin45:real = 0.707106781186548;
    cos35:real = 0.816496580927726;
    sin35:real = 0.577350269189625;

[...]
var
  OriginalBild:Tbitmap;
  Editbild:Tbitmap;
  // Editbild und Originalbild haben dieselben Dimensionen
  // initial sind beide exakt gleich, originalbild wird nicht verändert
  // Farbtiefe ist 24Bit

[...]
procedure TForm1.TrackbarFChange(Sender: TObject);
var x,y:integer;
    P,EditP : PByteArray;
    alpha:real;
    rt1,gt1,bt1:real;
    rt2,gt2,bt2:real;
    rint,bint,gint:integer;
begin
    // Umrechnung ins Bogenmaß
    alpha:=TrackbarF.Position/180 *Pi;
    for y := 0 to EditBild.Height -1 do
    begin
        P := OriginalBild.ScanLine[y];
        EditP := EditBild.ScanLine[y];
        for x := 0 to EditBild.Width -1 do
        begin
           // auf 1 normieren
            bt1:=P[3*x]/255;
            gt1:=P[3*x+1]/255;
            rt1:=P[3*x+2]/255;

            // 1. Drehung um +45° um die G-Achse, Diagonale liegt dann auf der RG-Ebene
            // Drehmatrix dafür:
            //  cos(45)  0   -sin(45)       b
            //    0      1       0      *   g
            //  sin(45)  0    cos(45)       r
            bt2 := cos45*bt1 - sin45*rt1;
            gt2 := gt1;
            rt2 := sin45*bt1 + cos45*rt1;

            // 2. Drehung um ca. -35°  um B-Achse, dann ist die R-Achse die Diagonale
            // Drehmatrix dafür: Beachte: cos(-x)=cos(x); sin(-x)=-sin(x)
            //  1        0         0            b
            //  0    cos(-35)  -sin(-35)    *   g
            //  0    sin(-35)   cos(-35)        r
            bt1 := bt2;
            gt1 :=  cos35*gt2 + sin35*rt2;
            rt1 := -sin35*gt2 + cos35*rt2;

            // Eigentliche Drehung, um die R-Achse um Winkel alpha
            //   cos(a)  -sin(a)  0       b
            //   sin(a)   cos(a)  0   *   g
            //     0         0    1       r
            bt2 := cos(alpha)*bt1 - sin(alpha)*gt1;
            gt2 := sin(alpha)*bt1 + cos(alpha)*gt1;
            rt2 := rt1;

            // die beiden vorigen Drehungen rückgängig
            bt1 := bt2;
            gt1 := cos35*gt2 - sin35*rt2;
            rt1 := sin35*gt2 + cos35*rt2;

            bt2 := cos45*bt1 + sin45*rt1;
            gt2 := gt1;
            rt2 := -sin45*bt1 + cos45*rt1;

             // wieder nach int umwandeln, evtl. Wert korrigieren
             bint:=round(bt2*255);
             gint:=round(gt2*255);
             rint:=round(rt2*255);
             if bint>255 then bint:=255;
             if gint>255 then gint:=255;
             if rint>255 then rint:=255;
             if bint<0 then bint:=0;
             if gint<0 then gint:=0;
             if rint<0 then rint:=0;
             EditP[3*x]   := bint;
             EditP[3*x+1] := gint;
             EditP[3*x+2] := rint;
    end;
    end;
    image1.Canvas.Draw(0,0,EditBild);
end;

In etwa funktioniert das auch. Allerdings beobachte ich bei einem Graustufenbild (Grauwerte liegen genau auf der Raumdiagonalen) AUCH eine Veränderung der Farbwerte, wenn ich die Trackbar verschiebe. Das kann aber eigentlich nicht sein, oder? Sieht jemand den Fehler? Oder hat Anregungen, woran das liegen könnte? Bin über alles dankbar. Vielleicht kann ein mathematisch versierter auch mal meine Winkel kontrollieren, ich hab da z.Z. einen ganzen Bretterstapel vorm Kopf...

_________________
We are, we were and will not be.