AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Verlauf mit "gewichteter" Farbe mittels Log?
Thema durchsuchen
Ansicht
Themen-Optionen

Verlauf mit "gewichteter" Farbe mittels Log?

Ein Thema von Pfoto · begonnen am 3. Apr 2009 · letzter Beitrag vom 5. Apr 2009
Antwort Antwort
Seite 1 von 2  1 2      
Pfoto

Registriert seit: 26. Aug 2005
Ort: Daun
541 Beiträge
 
Turbo Delphi für Win32
 
#1

Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 3. Apr 2009, 21:31
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:
    F := ((Pointvalue - aFrom) / (aTo - aFrom));
    Percent:= (100 * Pointvalue) / (aTo - aFrom);
    F:= (Percent * F) / 100;
Der Verlauf wird nun von der Startfarbe her gewichtet
-- das würde ich jetzt noch gerne umkehren. Leider bisher
noch ohne Erfolg.
Miniaturansicht angehängter Grafiken
farbverlauf_183.png  
Jürgen Höfs
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#2

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 05:25
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
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Pfoto

Registriert seit: 26. Aug 2005
Ort: Daun
541 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 09:17
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:
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;
Beim Skalieren, wie du es nennst, war ich mir auch nicht
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
Miniaturansicht angehängter Grafiken
verlauf-2_425.png  
Jürgen Höfs
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#4

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 11:25
Ich glaub' ich bin ganz nah dran, wenn ich die Aufgabe richtig verstanden hatte:

Delphi-Quellcode:
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;
PS: Nochmal leicht verändert, da Systemfarben nicht als Palettefarbe, sondern als Paletteneintrag behandelt werden...

PPS: Dominanz-Aufgabe noch mit eingebettet... 0-100% Domininaz der From-Farbe möglich (wobei 100% nicht die Zielfarbe völlig verschwinden lässt)
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#5

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 12:56
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'
Angehängte Dateien
Dateityp: 7z farbverlauf_510.7z (777,8 KB, 9x aufgerufen)
  Mit Zitat antworten Zitat
Pfoto

Registriert seit: 26. Aug 2005
Ort: Daun
541 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 13:49
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
Miniaturansicht angehängter Grafiken
verlauf-vergleich_103.png  
Jürgen Höfs
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#7

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 14:23
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;
Angehängte Dateien
Dateityp: 7z farbverlauf2_143.7z (911,8 KB, 7x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#8

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 14:31
Ich hätte da auch was im Angebot
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();
        }
    }
}
Angehängte Dateien
Dateityp: exe test_1_103.exe (9,5 KB, 9x aufgerufen)
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#9

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 14:37
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
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#10

Re: Verlauf mit "gewichteter" Farbe mittels Log?

  Alt 4. Apr 2009, 14:52
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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:09 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz