Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Bmp+Farbe mit "or" verknüpfen - kein Copymode vorhanden (https://www.delphipraxis.net/82800-bmp-farbe-mit-verknuepfen-kein-copymode-vorhanden.html)

Cöster 19. Dez 2006 17:03


Bmp+Farbe mit "or" verknüpfen - kein Copymode vorh
 
Hi!

Es gibt ja jede Menge verschiedene CopyModes (SRCCOPY, ...), aber ich habe keinen gefunden, der das Source-Bitmap mittels "or" mit einer Farbe (z.B. Brush.Color des Dest-Images) verknüpft.

Deswegen hab ich mir dafür selber nen Code geschrieben:

Delphi-Quellcode:
// kopiert "Src or Color" an die Position (AX, AY) des Dest-Bitmaps
procedure DrawOr(const Dest: TBitmap; AX, AY: Integer; const Src: TBitmap; Color: TColor);
type
   TPixArray = array[0..2] of Byte;
var
   Buffer: TBitmap;
   SrcP: ^TPixArray;
   X, Y: Integer;
begin
   Buffer := TBitmap.Create;
   try
      Buffer.SetSize(Src.Width, Src.Height);
      BitBlt(Buffer.Canvas.Handle, 0, 0, Buffer.Width, Buffer.Height,
         Src.Canvas.Handle, 0, 0, SRCCOPY);
      Buffer.PixelFormat := pf24Bit;
      for Y := 0 to Buffer.Height - 1 do
      begin
         SrcP := Buffer.ScanLine[Y];
         for X := 0 to Buffer.Width - 1 do
         begin
            SrcP^[3 * X] := SrcP^[3 * X] or ((Color shr 16) and $FF);
            SrcP^[3 * X + 1] := SrcP^[3 * X + 1] or ((Color shr 8) and $FF);
            SrcP^[3 * X + 2] := SrcP^[3 * X + 2] or (Color        and $FF);
         end;
      end;
      Buffer.Transparent := Src.Transparent;
      Buffer.TransparentColor := Src.TransparentColor;
      Dest.Canvas.Draw(AX, AY, Buffer);
   finally
      Buffer.Free;
   end;
end;
Lässt sich dieser Code optimieren? Hab ich ihn umsonst geschrieben, weil es schon irgendwo eine (bessere) Alternative gibt?

[edit]Wertparameter der Objektreferenzen in Konstantenparameter umgewandelt[/edit]

Flare 19. Dez 2006 17:11

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Habe es nicht getestet und auch sonst nix weiter zu sagen, nur ist in deinem Header ein Fehler drin, es sollte
Delphi-Quellcode:
procedure DrawOr(var Dest: TBitmap; AX, AY: Integer; Src: TBitmap; Color: TColor);
heißen, da du sonst Dest ja nicht wieder zurückgeben kannst.


Flare

Muetze1 19. Dez 2006 17:14

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Flare
Habe es nicht getestet und auch sonst nix weiter zu sagen, nur ist in deinem Header ein Fehler drin, es sollte
Delphi-Quellcode:
procedure DrawOr(var Dest: TBitmap; AX, AY: Integer; Src: TBitmap; Color: TColor);
heißen, da du sonst Dest ja nicht wieder zurückgeben kannst.

Nein, damit gibst du ihm nur die Möglichkeit die Instanz zu verändern - also er könnte nun hier die übergebene Instanz freigeben und eine neue erzeugen, aber zurückgeben kann er die Daten trotzdem, da es ein Instanzenzeiger ist.

Er könnte sogar Const nehmen und der Code würde immernoch funktionieren. Mit Const würde er nur dafür sorgen, dass die Methode die Instanz nicht verändern darf, ihre Eigenschafte und Werte aber schon.

Cöster 19. Dez 2006 17:26

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Muetze1
Er könnte sogar Const nehmen

Sollte ich auch? :stupid: D.h. bringt das optimierungstechnisch was? In der Hilfe steht ja, dass das bei Strings und strukturierten Typen den Code optimiert. Strukturierte Typen sind so definiert:

Zitat:

Zu den strukturierten Typen gehören Mengen-, Array-, Record- und Datei-, Klassen-, Klassenreferenz- und Interface-Typen.
Was genau versteht man unter Klassenreferenztypen? Ist eine Instanz ein Klassenreferenztyp? Denn dann würde sich ein const ja lohnen.

cruiser 19. Dez 2006 17:34

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Dest ist eine Referenz auf ein TBitmap, oder ;)

Cöster 19. Dez 2006 17:53

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von cruiser
Dest ist eine Referenz auf ein TBitmap, oder ;)

Hm, TBitmap ist eine Klasse, aber ein TBitmap ist ein Objekt einer Klasse, also nicht eine Klasse :gruebel: oder doch?

cruiser 19. Dez 2006 18:37

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
So oder so aber, dass es wirklich spürbar performanter wird kann ich mir nich vorstellen :)

ausser du machst das ... uhm ... sehr oft und schnell hintereinander

Khabarakh 19. Dez 2006 19:04

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Cöster
Zitat:

Zitat von cruiser
Dest ist eine Referenz auf ein TBitmap, oder ;)

Hm, TBitmap ist eine Klasse, aber ein TBitmap ist ein Objekt einer Klasse, also nicht eine Klasse :gruebel: oder doch?

Objektreferenz und Klassenreferenz kannst du als synonym betrachten ;) .

Cöster 19. Dez 2006 20:08

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Khabarakh
Objektreferenz und Klassenreferenz kannst du als synonym betrachten ;) .

Ah gut, also const, ich editier es mal im ersten Beitrag. Gibt es sonst noch Optimierungsmöglichkeiten?

Khabarakh 19. Dez 2006 20:19

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Soweit ich weiß, sollte ein 32-Bit-Bild schneller zu bearbeiten sein, vor Allem kannst du dann das gesamte Pixel auf einmal mit der Farbe verrechnen und musst nicht jeden Kanal einzeln behandeln. Mir ist auch nicht ganz klar, wofür du das temporäre Bitmap benötigst.

Muetze1 19. Dez 2006 20:27

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Khabarakh
Mir ist auch nicht ganz klar, wofür du das temporäre Bitmap benötigst.

BitBlt() weiss nichts vom TransparentColor etc und beachtet dies nicht. Draw() hingegen von Delphi macht dies entsprechend. (Was logisch ist, da Delphi intern gehandelte Eigenschaft)

Khabarakh 19. Dez 2006 20:31

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Ob das wirklich schneller ist als das Blending direkt in die Schleife zu packen?

Muetze1 19. Dez 2006 20:33

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Khabarakh
Ob das wirklich schneller ist als das Blending direkt in die Schleife zu packen?

Stimmt schon. Direkt in der Schleife die Pixeldaten berechnen, das Ergebnis mit dem TransparentColor Wert vergleichen und nur bei Ungleichheit direkt in das Ausgabebild zuweisen. Durch das lineare Durchlaufen könnte man sogar recht bequem mit den Einzel-Pointern arbeiten (PRGBQuad).

/EDIT: Naja, aber dann müsste ja noch Dest von der Farbtiefe her angepasst werden. Ich habe dies einfach mal in Quellcode gefasst und gemacht. Ob es schneller ist, kA - müsste man(n) ausprobieren...

Delphi-Quellcode:
// kopiert "Src or Color" an die Position (AX, AY) des Dest-Bitmaps
Procedure DrawOr(Const Dest: TBitmap; Const AX, AY: Integer; Const Src: TBitmap; Const Color: TColor);
Var
  lBuffer: TBitmap;
  DstP, SrcP: PRGBQuad;
  X, Y: Integer;
  lTransColor,
  lNewColor: TRGBQuad;
  lColor: TRGBTriple;
Begin
    // Ok, Src könnte ja ein DDB sein und darf vllt. nicht verändert werden. Daher bleib ich mal bei der Kopie
  lBuffer := TBitmap.Create;
  Try
    lBuffer.SetSize(Src.Width, Src.Height); // D5 und D7 kennen es nicht ...
    BitBlt(lBuffer.Canvas.Handle, 0, 0, lBuffer.Width, lBuffer.Height, Src.Canvas.Handle, 0, 0, SRCCOPY);
    lBuffer.PixelFormat := pf32Bit;
    Dest.PixelFormat := pf32Bit; // diese Veränderung noch an Dest

    With lTransColor Do
    Begin
      rgbRed     := GetRValue(ColorToRGB(Src.TransparentColor));
      rgbGreen   := GetGValue(ColorToRGB(Src.TransparentColor));
      rgbBlue    := GetBValue(ColorToRGB(Src.TransparentColor));
      rgbReserved := 0;
    End;
    With lColor Do
    Begin
      rgbtRed  := GetRValue(ColorToRGB(Color));
      rgbtGreen := GetGValue(ColorToRGB(Color));
      rgbtBlue := GetBValue(ColorToRGB(Color));
    End;

    For Y := 0 To Pred(lBuffer.Height) Do
    Begin
       SrcP := lBuffer.ScanLine[Y];
       DstP := Dest.ScanLine[Y + AY];
       Inc(DstP, AX);

       For X := 0 To Pred(lBuffer.Width) Do
       Begin
         lNewColor.rgbRed     := SrcP^.rgbRed  Or lColor.rgbtRed;
         lNewColor.rgbGreen   := SrcP^.rgbGreen Or lColor.rgbtGreen;
         lNewColor.rgbBlue    := SrcP^.rgbBlue Or lColor.rgbtBlue;
         lNewColor.rgbReserved := 0;

         If Not ( Src.Transparent And CompareMem(@lNewColor, @lTransColor, SizeOf(TRGBQuad)) ) Then
         Begin
           //lNewColor.rgbReserved := SrcP^.rgbReserved; // ??? Alpha Wert Original belassen? 
           DstP^ := lNewColor;
         End;

         Inc(SrcP);
         Inc(DstP);
       End;
    End;
  Finally
    lBuffer.Free;
  End;
End;
Nur geschrieben - nicht getestet!

Hawkeye219 19. Dez 2006 21:24

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Hi!
Zitat:

Zitat von Cöster
Es gibt ja jede Menge verschiedene CopyModes (SRCCOPY, ...), aber ich habe keinen gefunden, der das Source-Bitmap mittels "or" mit einer Farbe (z.B. Brush.Color des Dest-Images) verknüpft.

cmSrcPaint sollte helfen, wenn man die Ziel-Bitmap geeignet vorbereitet:

Delphi-Quellcode:
procedure DrawOr (const Dest: TBitmap; AX, AY: Integer; const Src: TBitmap; Color: TColor);
begin
  with Dest.Canvas do
    begin
      Brush.Style := bsSolid;
      Brush.Color := Color;
      FillRect (Rect(AX, AY, AX + Src.Width, AY + Src.Height));
      CopyMode := cmSrcPaint;
      Draw (AX, AY, Src);
      CopyMode := cmSrcCopy;
    end;
end;
Gruß Hawkeye

Cöster 20. Dez 2006 12:15

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
@ Hawkeye: So ließe sich allerdings keine Transparenz realisieren.

Muetze1 20. Dez 2006 12:19

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Cöster
@ Hawkeye: So ließe sich allerdings keine Transparenz realisieren.

Darum ging es ihm auch nicht. Du hattest keinen COPYMODE mit OR gefunden, den hat er dir genannt (also bei dir die Schleife). Das was du nach der Schleife machst, also Transparenz setzen und mit Draw übertragen, dass ist dann doch weiterhin möglich. Hawkeye hat hier nicht behauptet deine komplette Routine damit zu erschlagen sondern nur den von dir vermissten CopyMode mit OR.

Cöster 20. Dez 2006 13:01

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Dass es keine Copy-Modes mit Or gibt, hab ich nicht behauptet (MergePaint, NotSrcErase, PatPaint, SrcPaint). Ich meinte nur, dass es keinen CopyMode gibt, der ein Bmp mit or mit einer Farbe kombiniert (wie das andere CopyModes mit der Brush.Color tun, allerdings mit anderen Operatoren bzw. verknüpft direkt danach nochmal mit dem Dest-Bmp).

Ich denke für "Color or Transparent-Bitmap" guck ich mir deinen Beispielcode nochmal an (ließe sich allerdings auch noch optimieren, z.B. wird immer wieder auf Transparent geprüft. Außerdem könnte es eine Zugriffsverletzung geben, wenn das Src-Bmp nicht vollständig ins Dest-Bmp passt).

Muetze1 20. Dez 2006 13:18

Re: Bmp+Farbe mit "or" verknüpfen - kein Copymode
 
Zitat:

Zitat von Cöster
Dass es keine Copy-Modes mit Or gibt, hab ich nicht behauptet (MergePaint, NotSrcErase, PatPaint, SrcPaint). Ich meinte nur, dass es keinen CopyMode gibt, der ein Bmp mit or mit einer Farbe kombiniert (wie das andere CopyModes mit der Brush.Color tun, allerdings mit anderen Operatoren bzw. verknüpft direkt danach nochmal mit dem Dest-Bmp).

Was dir Hawkeye nun geliefert hat.

Zitat:

Zitat von Cöster
Ich denke für "Color or Transparent-Bitmap" guck ich mir deinen Beispielcode nochmal an (ließe sich allerdings auch noch optimieren, z.B. wird immer wieder auf Transparent geprüft. Außerdem könnte es eine Zugriffsverletzung geben, wenn das Src-Bmp nicht vollständig ins Dest-Bmp passt).

Zugriffsverletzung: glaube ich nicht. Die Bitmap Daten liegen im Anwendungsbereich und würden entweder die vorhergehenden Scanlines überschreiben bzw. anderen belegten Speicher, aber zu einer AV müsste man schon Glück haben - aber eine Überprüfung sollte sonst vorher geschehen.

Die Überprüfung auf Transparent sollte nicht viel ausmachen - ob da eine lokale Variable noch was rausholt ist fraglich. Grundlegend ging es nur darum die Ideen zusammen zu fassen und nicht fertigen Code zu präsentieren - wie geschrieben: ungetestet!


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:26 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