![]() |
Verlauf mit "gewichteter" Farbe mittels Log?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
ich versuche seit geraumer Zeit, einen Verlauf zwischen zwei Farben so zu ändern, dass eine der beiden Farben mehr Gewicht hat, also über eine gewisse Fläche hinweg dominanter ist. Ich habe mit Log() expermimentiert und habe festgestellt, dass ich damit der Sache näherkomme. Leider geht der Verlauf jedoch nicht von Anfang bis Ende, sondern wird kurz vor Ende unterbrochen und fängt neu an. Im Anhang ist ein Beispiel davon. Ich verwende folgenden Code (Quelle leider unbekannt):
Delphi-Quellcode:
function GetColorBetween(StartColor, EndColor: TColor; Pointvalue,
aFrom, aTo : Extended): TColor; var F: Extended; r1, r2, r3, g1, g2, g3, b1, b2, b3: Byte; function CalcColorBytes(fb1, fb2: Byte): Byte; begin result := fb1; if fb1 < fb2 then Result := FB1 + Trunc(F * (fb2 - fb1)); if fb1 > fb2 then Result := FB1 - Trunc(F * (fb1 - fb2)); end; begin if Pointvalue <= aFrom then begin result := StartColor; exit; end; if Pointvalue >= aTo then begin result := EndColor; exit; end; F := ((Pointvalue - aFrom) / (aTo - aFrom)); {==== Hier kommt einer meiner Versuche ===} F:= LogN(10, F); {======================================} asm mov EAX, Startcolor cmp EAX, EndColor je @@exit mov r1, AL shr EAX,8 mov g1, AL shr Eax,8 mov b1, AL mov Eax, Endcolor mov r2, AL shr EAX,8 mov g2, AL shr EAX,8 mov b2, AL push ebp mov al, r1 mov dl, r2 call CalcColorBytes pop ecx push ebp Mov r3, al mov dL, g2 mov al, g1 call CalcColorBytes pop ecx push ebp mov g3, Al mov dL, B2 mov Al, B1 call CalcColorBytes pop ecx mov b3, al XOR EAX,EAX mov AL, B3 SHL EAX,8 mov AL, G3 SHL EAX,8 mov AL, R3 @@Exit: mov @result, eax end; end; procedure FillGradient(Canvas : TCanvas; aStart, aWidth, aHeight : Integer; Color1, Color2 : TColor; Direction : TDirection); var i : Integer; begin if (aWidth > 0) and (aHeight > 0) then begin case Direction of diHorizontal: for i := aStart to aWidth do begin Canvas.Pen.Color := GetColorBetween(Color1, Color2, i, aStart, aWidth); Canvas.MoveTo(i, 0); Canvas.LineTo(i, aHeight); end; diVertical: for i := aStart to aHeight do begin Canvas.Pen.Color := GetColorBetween(Color1, Color2, i, aStart, aHeight); Canvas.MoveTo(0, i); Canvas.LineTo(aWidth, i); end; end; end; end; Leider bin ich ja mathematisch minderbegabt, d.h. ich sehe zwar mit verschiedenen Log-Arten die Ergebnisse (z.B. viele, immer kleiner werdende Verlaufsstrecken), kann mir aber nicht erklären, wie ich einen soliden Wert ermittle, um einen durchgängigen Verlauf von A nach B zu generieren :-( Wisst ihr hier eine Formel, mit der ich das lösen könnte? Dank und Gruß Jürgen **** EDIT **** Ich habe nun mit Prozentwerten gearbeitet und erhalte eine sehr ähnliche Ausgabe, mit der ich ja schon *fast* zufrieden wäre:
Delphi-Quellcode:
Der Verlauf wird nun von der Startfarbe her gewichtet
F := ((Pointvalue - aFrom) / (aTo - aFrom));
Percent:= (100 * Pointvalue) / (aTo - aFrom); F:= (Percent * F) / 100; -- das würde ich jetzt noch gerne umkehren. Leider bisher noch ohne Erfolg. |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Ich habe jetzt nicht alles ganz genau durchgelesen, aber ich vermute mal dass du irgendwo eine "Laufvariable" i hast, die von 0 bis 1 als Faktor der Randfarben für die Mischung zuständig ist. In diesem Fall ist das simpelste "biasing" die Potenzierung, also genau die Umkehrfunktion vom Logarithmus.
Lasse i ganz normal laufen, aber rechne die Farben mit i^k*C1 + (1-i^k)*C2. Wenn dein i nicht 0..1 ist, skaliere es darauf. Das tolle ist dabei nämlich, dass 0^k=0 und 1^k=1 bleiben, nur die Werte da zwischen werden quasi "verbogen" - ohne je [0;1] zu verlassen. Je nach dem wie du k nun wählst ist dein Verlauf mehr nach C1 oder C2 verschoben, wobei k=1 der übliche lineare Verlauf ist. Ein wenig gewöhnungsbedürftig: Volles Schieben nach C2 wäre bei k=0,00000...1 und nach C1 k=+inf |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Medium,
ich habe das eben mal (versucht) umzusetzen. Dieses Dach (^) kenne ich nur von Pointern, aber du meintest damit also die Funktion Power(), oder?
Delphi-Quellcode:
Beim Skalieren, wie du es nennst, war ich mir auch nicht
var
Pointvalue, // entspricht aktueller Position k: extended; [...] { Pointvalue geht von 0 bis Image.Widht/Height, also auf 0..1 skalieren } Pointvalue:= (Pointvalue / aTo); k:= 1; F:= power(Pointvalue, k)*StartColor + (1-power(Pointvalue, k))*EndColor; sicher, aber zumindest bleibt Pointvalue nun zwischen 0 und 1. Poinvalue müsste also stimmen. Als Ergebnis erhalte ich bei k=1 leider 3 Verläufe (siehe Anhang). Wenn K Richtung 0 geht, werden es ganz viele kleine Verläufe :-( Wo steckt denn da der Fehler? Dank und Gruß Jürgen |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Ich glaub' ich bin ganz nah dran, wenn ich die Aufgabe richtig verstanden hatte:
Delphi-Quellcode:
PS: Nochmal leicht verändert, da Systemfarben nicht als Palettefarbe, sondern als Paletteneintrag behandelt werden...
function GetColorBetween(FromColor, ToColor: TColor; FromDomPercent : Byte;
LoRange, HiRange, Position : Integer): TColor; type TRGB = packed record R,G,B,P : Byte; end; const Gewichtung = 200; var FromClr, ToClr, ResultClr : TRGB; i : Integer; begin i := ColorToRGB(FromColor); FromClr := TRGB(i); i := ColorToRGB(ToColor); ToClr := TRGB(i); // Hier FromColor anteilig in ToColor einrechnen if FromDomPercent in [1..100] then begin ToClr.R := ToClr.R + ((FromDomPercent * FromClr.R) div 100); ToClr.G := ToClr.G + ((FromDomPercent * FromClr.G) div 100); ToClr.B := ToClr.B + ((FromDomPercent * FromClr.B) div 100); end; // Verlauf berechnen i := (Position * 255) div (HiRange - LoRange); ResultClr.R := ( (ToClr.R * i) + (FromClr.R * (255 - i)) ) div 255; ResultClr.G := ( (ToClr.G * i) + (FromClr.G * (255 - i)) ) div 255; ResultClr.B := ( (ToClr.B * i) + (FromClr.B * (255 - i)) ) div 255; ResultClr.P := 0; Result := TColor(ResultClr); end; procedure FillGradient(Canvas: TCanvas; FromClr, ToClr: TColor; FromDomPercent: Byte; aRect: TRect; Vertical : Boolean); var i : Integer; begin if Vertical then begin for i := aRect.Top to aRect.Bottom do begin Canvas.Pen.Color := GetColorBetween(FromClr, ToClr, FromDomPercent, aRect.Top, aRect.Bottom, i); Canvas.MoveTo(aRect.Left, i); Canvas.LineTo(aRect.Right, i); end; end else begin for i := aRect.Left to aRect.Right do begin Canvas.Pen.Color := GetColorBetween(FromClr, ToClr, FromDomPercent, aRect.Left, aRect.Right, i); Canvas.MoveTo(i, aRect.Top); Canvas.LineTo(i, aRect.Bottom); end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin FillGradient(PaintBox1.Canvas, clRed, clBlue, SpinEdit1.Value, PaintBox1.ClientRect,False); end; PPS: Dominanz-Aufgabe noch mit eingebettet... 0-100% Domininaz der From-Farbe möglich (wobei 100% nicht die Zielfarbe völlig verschwinden lässt) |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Liste der Anhänge anzeigen (Anzahl: 1)
Es wird übrigens nur die Farbe verändert, nicht die Helligkeit. Deshalb ist zum Testen Black -> White ganz schlecht, denn die Grausstufen ändern sich bei reiner Farb-Änderung nicht.
In der Anlage das Project, mit dem ich experimentiert hab' |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Satty67,
vielen Dank erstmal für Deine Mühe! Leider meinte ich mit "Gewichtung" etwas anderes, obwohl man sicher auch deine Routine gut gebrauchen kann. Die Start- und Endfarbe sollte jedoch nicht verändert werden, sondern der Verlauf sollte eben nicht linear vorangehen, sondern überproportional (oder wie man das nennt). D.h. im ersten Drittel ist die Dominanz der ersten Farbe noch deutlicher und lässt dann erst allmählich nach. Im Anhang noch mal ein Beispiel von einem normalen und dem von mir gemeinten Verlauf. Gruß Jürgen |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Liste der Anhänge anzeigen (Anzahl: 1)
Ok, dann hatte ich das falsch verstanden. (aber macht nicht, das experimentieren mit Farben macht mit am meisten Spass)
Hier dann mal ein anderer Ansatz (im Anhang das Projekt zum Testen)
Delphi-Quellcode:
function GetColorBetween(FromColor, ToColor: TColor; Distributor : Byte;
LoRange, HiRange, Position : Integer): TColor; type TRGB = packed record R,G,B,P : Byte; end; var FromClr, ToClr, ResultClr : TRGB; i,j, FirstPart, SecondPart, FullRange : Integer; begin i := ColorToRGB(FromColor); FromClr := TRGB(i); i := ColorToRGB(ToColor); ToClr := TRGB(i); // Verlauf berechnen FullRange := (HiRange - LoRange); FirstPart := (Distributor * FullRange) div 100; SecondPart := FullRange - FirstPart; if Position < FirstPart then begin j := (Position * 50) div FirstPart; end else begin j := ((Position- FirstPart) * 50) div SecondPart; j := j + 50; end; i := (j * 255) div 100; ResultClr.R := ( (ToClr.R * i) + (FromClr.R * (255 - i)) ) div 255; ResultClr.G := ( (ToClr.G * i) + (FromClr.G * (255 - i)) ) div 255; ResultClr.B := ( (ToClr.B * i) + (FromClr.B * (255 - i)) ) div 255; ResultClr.P := 0; Result := TColor(ResultClr); end; procedure FillGradient(Canvas: TCanvas; FromClr, ToClr: TColor; Distributor: Byte; aRect: TRect; Vertical : Boolean); var i : Integer; begin if Vertical then begin for i := aRect.Top to aRect.Bottom do begin Canvas.Pen.Color := GetColorBetween(FromClr, ToClr, Distributor, aRect.Top, aRect.Bottom, i); Canvas.MoveTo(aRect.Left, i); Canvas.LineTo(aRect.Right, i); end; end else begin for i := aRect.Left to aRect.Right do begin Canvas.Pen.Color := GetColorBetween(FromClr, ToClr, Distributor, aRect.Left, aRect.Right, i); Canvas.MoveTo(i, aRect.Top); Canvas.LineTo(i, aRect.Bottom); end; end; end; procedure TFormFarbverlauf.Button2Click(Sender: TObject); begin If ColorDialog1.Execute then PanelFrom.Color := ColorDialog1.Color; end; procedure TFormFarbverlauf.Button3Click(Sender: TObject); begin If ColorDialog1.Execute then PanelTo.Color := ColorDialog1.Color; end; procedure TFormFarbverlauf.TrackBar1Change(Sender: TObject); begin LabelTrackbar.Caption := IntToStr(TrackBar1.Position)+' %'; FillGradient(PaintBox1.Canvas, PanelFrom.Color, PanelTo.Color, TrackBar1.Position, PaintBox1.ClientRect,False); end; |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hätte da auch was im Angebot :stupid:
Code:
namespace Test_1
{ public partial class Form1 : Form { double potenz; Color col1; Color col2; public Form1() { InitializeComponent(); col1 = Color.Red; col2 = Color.Blue; potenz = 1; } private void pictureBox1_Paint(object sender, PaintEventArgs e) { double pos = 0; double amount = 0; Color tempColor; Pen myPen = new Pen(col1); for (int i = 0; i < pictureBox1.Width; i++) { pos = (double)i / (pictureBox1.Width - 1); amount = 1 - Math.Pow(pos, potenz); // 1 - Weil wir den Betrag der ersten Farbe haben wollen tempColor = MixColors(col1, col2, amount); myPen.Color = tempColor; e.Graphics.DrawLine(myPen, new Point(i, 0), new Point(i, pictureBox1.Height - 1)); } } private Color MixColors(Color col1, Color col2, double amount) { if (amount < 0 || amount > 1) throw new ArgumentOutOfRangeException("amount"); byte R = (byte)(col1.R * amount + col2.R * (1 - amount)); byte G = (byte)(col1.G * amount + col2.G * (1 - amount)); byte B = (byte)(col1.B * amount + col2.B * (1 - amount)); return Color.FromArgb(R, G, B); } private void trackBar1_ValueChanged(object sender, EventArgs e) { potenz = Math.Pow(1.1, trackBar1.Value); label1.Text = String.Format("Potenz: {0:F3}", potenz); pictureBox1.Invalidate(); } } } |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Kriegt ich Delphi 5 nicht beigebracht (ist das C# oder Delphi-Prism?)
*** Zu meinem zweiten Ansatz noch kurz die Idee dahinter: Ich gehe einfach davon aus, das irgendwo der Farbverlauf die Mitte hat (Anteil beider Farben gleich) und verschiebe danach nur die Mitte und berechne Teilfarbverläufe zu neuen Mitte |
Re: Verlauf mit "gewichteter" Farbe mittels Log?
Ist C# ;)
Ich habe den Ansatz von Medium gewählt. Also mit der Laufvariable und der Potenz. d.h. es wird eine Laufvariabele genommen die von 0 bis 1 geht (jeweils inkl.) Der Anteil der zweiten Farbe ergibt sich dann aus laufvariable^Potenz - wenn also die Potenz gleich 1 ist isses ein linearer Farbverlauf. Der Anteil der ersten Farbe ist dann der Rest (1 - laufvariable^Potenz) Die Potenz muss zwischen 0 und unendlich liegen. Wenn sie null ist, ist der Anteil der zweiten Farbe immer Null, bis auf das Ende da springt er auf eins (also 100%) Das andere Extrem ist unendlich, da ist der Anteil der zweiten Farbe erst null und springt danach sofort auf 1. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:05 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz