Farbmixer in Lazarus

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Lapiz123
Beiträge: 9
Registriert: Do 14. Jan 2021, 20:42

Farbmixer in Lazarus

Beitrag von Lapiz123 »

Ich beschäftige mich aktuell mit einem Farbmischer in Lazarus, Ziel ist es mit den Scrollbars die Farbe der Kreise zu verändern. Der rechte Kreis ist soll mit dem R Slider verbunden sein und den Rotwert beeinflussen durch die Position vom Slider und mit den anderen Kreisen das ähnliche mit G (Grün) B (Blue). Die Kreise sollen sich auch an ihren überlappenden Stellen mischen und der gemischt Farbwert soll dann angezeigt werden. Die einzelnen Kreise sollen nur weils mit den 256 Farben des jeweiligen Kanals geändert werden können.

Formular Screenshot
https://i.imgur.com/R1homyK.png

corpsman
Beiträge: 1163
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Farbmixer in Lazarus

Beitrag von corpsman »

Da empfehle ich mal direct das mit OpenGL zu machen, da kannst es einfach Blenden lassen dürfte dort nur wenige Zeilen Code sein ;)
--
Just try it

wp_xyz
Beiträge: 3516
Registriert: Fr 8. Apr 2011, 09:01

Re: Farbmixer in Lazarus

Beitrag von wp_xyz »

Das geht auch mit LCL, allerdings nur pixelweise: Die Mittelpunkte der roten, grünen und blauen Kreise merken. Dann, wenn ein Pixel gesetzt werden soll, den Abstand vom jeweiligen Mittelpunkt berechnen (es reicht das Quadrat) und wenn dieser kleiner ist als der Kreisradius, die Farbkomponente entsprechend setzen. Statt der Pixels[]-Eigenschaft, arbeite ich mit einem LazIntfImage, damit geht's schnell genug und plattformübergreifend (wahrscheinlich geht es aber auch in Delphi-Manier mit Scanline)
Dateianhänge
color_mixture.zip
(2.49 KiB) 12-mal heruntergeladen

Lapiz123
Beiträge: 9
Registriert: Do 14. Jan 2021, 20:42

Re: Farbmixer in Lazarus

Beitrag von Lapiz123 »

wp_xyz hat geschrieben:
Mo 25. Jan 2021, 10:44
Das geht auch mit LCL, allerdings nur pixelweise: Die Mittelpunkte der roten, grünen und blauen Kreise merken. Dann, wenn ein Pixel gesetzt werden soll, den Abstand vom jeweiligen Mittelpunkt berechnen (es reicht das Quadrat) und wenn dieser kleiner ist als der Kreisradius, die Farbkomponente entsprechend setzen. Statt der Pixels[]-Eigenschaft, arbeite ich mit einem LazIntfImage, damit geht's schnell genug und plattformübergreifend (wahrscheinlich geht es aber auch in Delphi-Manier mit Scanline)
Danke für das anhängende Programm das hilft mir wirklich sehr danke, jetzt muss ich nur noch den Farbe Wert in HTML also #...... auslesen lassen der in der Mitte gemischt wurde. Ausgabe dann z.b. Auf einem Label oder so :)

wp_xyz
Beiträge: 3516
Registriert: Fr 8. Apr 2011, 09:01

Re: Farbmixer in Lazarus

Beitrag von wp_xyz »

Ich habe das Demoprogramm jetzt erweitert, so dass der Farbwert in der Mitte ausgelesen und nochmals separat in einem Panel angezeigt wird.

Also ich weiß nicht, ob es nur mir so geht, aber ich habe den Eindruck, dass auf dem Panel eine andere Farbe erscheint als in der Schnittfläche aller drei Kreise. Ich habe mit einem ScreenColorPicker die Farben extra manuell ausgelesen, und sie sind identisch. Wahrscheinlich wird das visuelle Farbempfinden durch die Anwesenheit der Nachbarkreise verfälscht. Daher halte ich diesen Farbmischer nicht für sehr geeignet.
Dateianhänge
color_mixer.png
color_mixer.png (6.48 KiB) 278 mal betrachtet
color_mixture2.zip
(2.72 KiB) 18-mal heruntergeladen

Lapiz123
Beiträge: 9
Registriert: Do 14. Jan 2021, 20:42

Re: Farbmixer in Lazarus

Beitrag von Lapiz123 »

wp_xyz hat geschrieben:
Di 26. Jan 2021, 12:20
Ich habe das Demoprogramm jetzt erweitert, so dass der Farbwert in der Mitte ausgelesen und nochmals separat in einem Panel angezeigt wird.

Also ich weiß nicht, ob es nur mir so geht, aber ich habe den Eindruck, dass auf dem Panel eine andere Farbe erscheint als in der Schnittfläche aller drei Kreise. Ich habe mit einem ScreenColorPicker die Farben extra manuell ausgelesen, und sie sind identisch. Wahrscheinlich wird das visuelle Farbempfinden durch die Anwesenheit der Nachbarkreise verfälscht. Daher halte ich diesen Farbmischer nicht für sehr geeignet.
Danke für dieses Programm, ich werde es auf jeden Fall integrieren, ich melde mich wenn ich Probleme haben sollte, wünsche dir einen wunderschönen Tag

Lapiz123
Beiträge: 9
Registriert: Do 14. Jan 2021, 20:42

Re: Farbmixer in Lazarus

Beitrag von Lapiz123 »

wp_xyz hat geschrieben:
Di 26. Jan 2021, 12:20
Ich habe das Demoprogramm jetzt erweitert, so dass der Farbwert in der Mitte ausgelesen und nochmals separat in einem Panel angezeigt wird.

Also ich weiß nicht, ob es nur mir so geht, aber ich habe den Eindruck, dass auf dem Panel eine andere Farbe erscheint als in der Schnittfläche aller drei Kreise. Ich habe mit einem ScreenColorPicker die Farben extra manuell ausgelesen, und sie sind identisch. Wahrscheinlich wird das visuelle Farbempfinden durch die Anwesenheit der Nachbarkreise verfälscht. Daher halte ich diesen Farbmischer nicht für sehr geeignet.
Danke nochmal für die große Hilfe mittlerweile konnte ich mein Projekt komplett beenden. Fehlt noch nur noch die Kommentierung. Wärst du so nett und würdest diese für folgende Part hinzufügst?

function Distance2(i, j: Integer; P: TPoint): Integer;
begin
Result := sqr(i-P.X) + sqr(j-P.Y);
end;

und


procedure TFarbmixerForm.PaintBox1Paint(Sender: TObject);
var
P1, P2, P3: TPoint;
R, Rsq: Integer;
bmp: TBitmap;
img: TLazIntfImage;
HBmp, HMask: HBitmap;
clr: TFPColor;
i, j: Integer;
begin
R := Paintbox1.Width div 3;
Rsq := R*R;
P1 := Point(R, R);
P2 := Point(Paintbox1.Width - R, R);
P3 := Point(Paintbox1.Width div 2, PaintBox1.Height - R);

bmp := TBitmap.Create;
try
bmp.SetSize(Paintbox1.Width, Paintbox1.Height);
bmp.PixelFormat := pf24bit;
bmp.Canvas.Brush.Color := clBlack;
bmp.Canvas.FillRect(0, 0, bmp.Width, bmp.Height);

img := bmp.CreateIntfImage;
try
for j := 0 to img.Height-1 do
for i := 0 to img.Width - 1 do
begin
clr := img.Colors[i, j];
if Distance2(i, j, P1) <= Rsq then
clr.Red := sbRed.Position shl 8;
if Distance2(i, j, P2) <= Rsq then
clr.Green := sbGreen.Position shl 8;
if Distance2(i, j, P3) <= Rsq then
clr.Blue := sbBlue.Position shl 8;
img.Colors[i, j] := clr;
end;
img.CreateBitmaps(HBmp, HMask);
bmp.BitmapHandle := HBmp;
bmp.MaskHandle := HMask;
finally
img.Free;
end;
Paintbox1.Canvas.Draw(0, 0, bmp);
finally
bmp.Free;
end;
end;

wp_xyz
Beiträge: 3516
Registriert: Fr 8. Apr 2011, 09:01

Re: Farbmixer in Lazarus

Beitrag von wp_xyz »

Lapiz123 hat geschrieben:
Mo 8. Feb 2021, 00:56
Danke nochmal für die große Hilfe mittlerweile konnte ich mein Projekt komplett beenden. Fehlt noch nur noch die Kommentierung. Wärst du so nett und würdest diese für folgende Part hinzufügst?
Offenbar hast du dann den Code nicht verstanden. Vielleicht wird's mit diesen Kommentaren klarer:

Code: Alles auswählen

// Berechnet das Quadrat des Abstands des Pixels am Ort (i, j) von dem Punkt P
function Distance2(i, j: Integer; P: TPoint): Integer;
begin
  Result := sqr(i-P.X) + sqr(j-P.Y);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  P1, P2, P3: TPoint;
  R, Rsq: Integer;
  bmp: TBitmap;
  img: TLazIntfImage;
  HBmp, HMask: HBitmap;
  clr: TFPColor;
  i, j: Integer;
begin
  // Radius jedes Farbkreises
  R := Paintbox1.Width div 3;
  Rsq := R*R;
  // Mittelpunkte der Farbkreise
  P1 := Point(R, R);
  P2 := Point(Paintbox1.Width - R, R);
  P3 := Point(Paintbox1.Width div 2, PaintBox1.Height - R);

  // Wir zeichnen zunnächst auf einem Bitmap
  bmp := TBitmap.Create;
  try
    bmp.SetSize(Paintbox1.Width, Paintbox1.Height);
    bmp.PixelFormat := pf24bit;
    bmp.Canvas.Brush.Color := clBlack;
    bmp.Canvas.FillRect(0, 0, bmp.Width, bmp.Height);

    // Um die Farben einzeln ansprechen zu können, wird das Bitmap in ein
    // LazIntfImage umgewandelt (es gäbe aber auch andere Möglichkeiten).
    img := bmp.CreateIntfImage;
    try
      // Alle Pixel (i, j) des LazIntfImage durchlaufen
      for j := 0 to img.Height-1 do
        for i := 0 to img.Width - 1 do
        begin
          // Farb-Record des Pixels am Ort (i, j)
          clr := img.Colors[i, j];
          // Wenn der Abstand des aktuellen Pixels (i, j) vom Mittelpunkt des
          // roten Kreises kleiner ist als der Kreisradius, wird die rote
          // Farbkomponente auf dem in der roten Scrollbar vorgegebenen Wert gesetzt.
          // Da sich die Beziehung a<b nicht ändert, wenn man sie quadriert, werden
          // hier statt den Abständen lediglich die Quadrate der Abstände verglichen.
          if Distance2(i, j, P1) <= Rsq then
            clr.Red := sbRed.Position shl 8;
            // Jede Farbkomponente im LazIntfImage hat 16 bit, in TColor nur 8 bit.
            // Durch die "shl 8"-Operation werden die 8 Bit um 8 Positionen ins High-Byte von clr.Red verschoben.
          // genauso mit grün...
          if Distance2(i, j, P2) <= Rsq then
            clr.Green := sbGreen.Position shl 8;
          // ... und mit blau.
          if Distance2(i, j, P3) <= Rsq then
            clr.Blue := sbBlue.Position shl 8;
          img.Colors[i, j] := clr;
        end;
      // Inhalt des LazIntfImage auf das Zeichenbitmap übertragen
      img.CreateBitmaps(HBmp, HMask);
      bmp.BitmapHandle := HBmp;
      bmp.MaskHandle := HMask;
    finally
      img.Free;
    end;
    // Zeichenbitmap auf der Paintbox ausgeben.
    Paintbox1.Canvas.Draw(0, 0, bmp);
  finally
    bmp.Free;
  end;
end;

Antworten