Transparent und TBitMap

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Transparent und TBitMap

Beitrag von pluto »

Hallo,
kann es sein das TransparentColor mit Tbitmap nicht geht?

Code: Alles auswählen

map[x-1,y-1].SpriteImage.TransparentColor:=RGB(0,255,0);
  map[x-1,y-1].SpriteImage.Transparent:=True;
  map[x-1,y-1].LoadImage;
Die Grafik wird zwar angezeigt, aber halt nicht Transparent....
// BitBlt(Buffer.Handle,left,top,Width,Height,SpriteImage.Canvas.Handle,0,0,SRCCOPY);
Buffer.Canvas.CopyRect(rect(left,top,left+Width,top+Height),SpriteImage.canvas,rect(0,0,Width,Height));
OutCanvas.CopyRect(rect(left,top,left+Width,top+Height),SpriteImage.canvas,rect(0,0,Width,Height));

// Buffer.Canvas.Draw(left,top,SpriteImage);
// OutCanvas.Draw(left,top,SpriteImage);

// BitBlt(OutCanvas.Handle,left,top,Width,Height,Buffer.Canvas.Handle,left,top,SRCCOPY);
so habe ich es versucht.... und es wird nie Transparent gezeichnet....
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Kapier nicht was du da genau machst.
Also wenn die ersten drei Zeilen bedeuten, dass du das Bild vor dem Laden transparent machen willst, geht's wohl schon mal nicht.
Er kann ja keine Maske bauen, für ein Bild welches nicht da ist.

Dann bin ich mir nicht sicher, ob CopyRect auf die Transparenz Rücksicht nimmt.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Ich meine Draw müsste das können, geht aber auch nicht. Ich hatte das schonmal danach gemacht ging aber auch nicht.

Ich werde jetzt was eigenes schreiben. mit pixel.

Ich möchte eine Funktion schreiben der du Zwei Canvas Objekte übergibst.
Das Eigentliche Bild und das Hintergrund Bild. Und natürlich die Trazparent Farbe(evlt. sogar als Array). ach ja: und ich brauche noch die Gewünschten Position Angaben als Parameter.

Jetzt nur noch muss ich nur noch in zwei Schleifen die Pixel durch gehen. und entscheiden ob die Farbe ersetzt werden soll oder nicht.

Die Positions Angaben müssen sich auf das zweite(Hintergrund Bild) beziehen.

Im Prinzip müsste das doch klappen oder ?

Das Hintergrund Bild enthält dann halt ein Hintergrund....

evlt. versuche ich das noch mal mit deiner OpBitMap... evlt. geht es damit schneller was ich mir gar nicht vorstellen kann, weil ich das Bild ja umwandeln müsste mehrmals.... was wieder zeit Kostet.... oder sehe ich da was falsch ?
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Also das mit dem durch die Pixel wandern ist sicher nicht schneller als OpBitmap. Ansonsten kommt's immer drauf an, wie du es einsetzt.
Generell muss ja nur umgewandelt werden, wenn es auf den Bildschirm kommt. Du kannst also vorher einen Haufen Pixel-Manipulationen machen, ohne dass es zwischenzeitlich umgewandelt werden muss.
Bei kleineren Bildern sollte die Umwandlung auch kaum zu bemerken sein.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich habe es jetzt so versucht:

Code: Alles auswählen

{ for y:=0 to Height do begin
    for x:=0 to Width do begin
      if tmp.Canvas.Pixels[x,y] = TranzparentColor then begin
        tmp.Canvas.Pixels[x,y]:=BackupBuffer.Canvas.Pixels[left+x,top+y]
      end; // if
    end // x
  end; // x}
was eigentlich auch klappen müsste es ist nur viel zu langsam.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

wie würde das denn in Opbitmap gehen ?
ich möchte ja nicht 40%ige durchsichtige Flächen haben sondern komplet so halt wie in Delphi... TranzparentMode ist auch noch gar nicht Fertig, den habe ich mal setzten wollen da kam eine Fehler Meldung im Ausgabe Fenster.

Das es halt noch nicht Implementiert ist
MFG
Michael Springwald

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

ransparent ist implementiert jedenfalls in > 0.9.24, glaub auch in der .22 schon. Soweit ich weiss is Scanline auch implementiert jedenfalls gibts n scanline example von daher bräuchte man opbitmap für sowas gar net.
Sschau einfach nochmal heos ersten Post an dann klapps auch mit der Transparenz.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

bei mir gibt es kein Scanline !

was meinst du mit deinem Letzten Abstatzt ?
könntest du evlt. ein kleines beispiel erstellen ?
Seit stunden suche ich nach einer Lösung, meine ist leider zu langsam.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

mein Lazarus kennt leider kein PaintToRGB32bitScanLine(
habe alle units vom beispiel eingebunden.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich habe das jetzt mit OpBitMap versucht:

Code: Alles auswählen

procedure DrawTranzParentRectImage(aBuffer:TBitMap; aBuffer2,abuffer3:TBitMap; const left, top:Integer);
var
  Hintergrund:TOPPicture;
  ah,b2:TCanvasOPBitmap;
begin
  Hintergrund:=TOPPicture.Create;
  AssignBitmapToOpBitmap(abuffer2,Hintergrund.Bitmap);
 
  b2:=TCanvasOPBitmap.Create;
  AssignBitmapToOpBitmap(abuffer,b2);
 
 
  ah:=TCanvasOPBitmap.Create;
//  ah.AlphaBlend:=True;
  ah.Width:=abuffer.Width; ah.Height:=abuffer.Height;
  ah.Canvas.Brush.Color:=clWhite;
  ah.Transparent:=True;
  ah.TransparentColor:=clWhite;
 
  ah.Canvas.Draw(left,top,b2);
 
  Hintergrund.Bitmap.Transparent:=True;
  Hintergrund.Bitmap.TransparentColor:=clWhite;
 
  Hintergrund.Bitmap.Canvas.Draw(left,Top, ah);
 
  AssignOpBitmapToBitmap(Hintergrund.Bitmap,aBuffer3);
  Hintergrund.Free; ah.Free; b2.free;
end;
so geht es leider nicht..... es gibt Grafik Fehler

edit01:

Code: Alles auswählen

procedure TPluto2DSprite.DrawTrazparent;
var
  x,y:Integer;
  tmp:TBitMap;
  r1,r2:TRect;
begin
  tmp:=TBitMap.Create; tmp.Width:=Width; tmp.Height:=Height;
  BitBlt(tmp.canvas.Handle,0,0,Width,Height,BackupBuffer.canvas.Handle,left,top,SRCCOPY);
 for y:=0 to Height do begin
    for x:=0 to Width do begin
      if SpriteImage.Canvas.Pixels[x,y] <> TranzparentColor then begin
        tmp.Canvas.Colors[x,y]:=SpriteImage.Canvas.Colors[x,y];
        //BackupBuffer.Canvas.Pixels[left+x,top+y]
      end; // if
    end // x
  end; // y
 
  buffer.canvas.Draw(left,top,tmp);
  OutCanvas.Draw(left,top,tmp);
end;
so geht das zwar wie gewünscht, aber es ist zu langsam.

Backupbuffer ist der Hintergrund, Outcanvas ist eine Paintbox, SpriteImage Enthält die Grafik /Figur die gezeichnet werden muss.

zuerst wird der Teil vom Hintergrund in TMP gezeichnet und jetzt wird der Teil von SpriteImage die nicht Trazparent sind kopiert.

ich hatte das auch noch mal anders herum aber leider genauso langsam.

Aber wie geht denn draw ? das macht es doch genauso...

edit01:

Code: Alles auswählen

procedure TFPCustomCanvas.Draw (x,y:integer; image:TFPCustomImage);
var xx,xi,yi,xm,ym,r,t : integer;
begin
  xm := x + image.width-1;
  if xm >= width then
    xm := width - 1;
  ym := y + image.height-1;
  if ym >= height then
    ym := height - 1;
  xi := x;
  yi := y;
  if clipping then
    CheckRectClipping (ClipRect, xi,yi, xm,ym);
  for r := xi to xm do
    begin
    xx := r - x;
    for t := yi to ym do
      colors [r,t] := image.colors[xx,t-y];
    end;
end;
so macht es Lazarus, also Praktisch genauso wie ich...

edit03: was heißt das auf deutsch ?
ransparent - Some parts of the image are not opaque. aka the background
can be seen through.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben:ich habe das jetzt mit OpBitMap versucht:
....
so geht es leider nicht..... es gibt Grafik Fehler
Bei mir geht das gut.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var b1,b2:TCanvasOPBitmap;
begin
 b1:=TCanvasOPBitmap.Create;
 b2:=TCanvasOPBitmap.Create;
 AssignBitmapToOpBitmap(Image2.Picture.Bitmap,b1);
 AssignBitmapToOpBitmap(Image3.Picture.Bitmap,b2);
 b2.TransparentColor:=clwhite;
 b1.Canvas.Draw(20,20,b2);
 b1.TransparentColor:=clwhite;
 AssignOpBitmapToBitmap(b1,Image1.Picture.Bitmap);
 b1.free;
 b2.free;
end;
Zuerst das eine Bild Transparent mit Versatz auf's andere kopiert und dann das ganze Transparent auf's Image.
Dateianhänge
opbtrans.png
opbtrans.png (5.74 KiB) 2263 mal betrachtet

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

mein Lazarus kennt leider kein PaintToRGB32bitScanLine(
Manchmal weiss ich net mehr wie man dir helfen soll, diese Funktion ist ja auch im Beispiel selbst deklariert wenn du das also benutzen willst, musst du schon die Funktion mitkopieren.
was meinst du mit deinem Letzten Abstatzt ?
könntest du evlt. ein kleines beispiel erstellen ?
Seit stunden suche ich nach einer Lösung, meine ist leider zu langsam.
Theo hat dir schon in seiner ersten Antwort gesagt was du falsch machst.
Das meinte ich, ich habs sicherheitshalber eben trotsdem nochmal ausprobiert und es funktioniert alles.

eben mal schnell mit dem Lazarus Splashscreen und 2 Images ausprobiert: Funktioniert alles so wie es soll.
Image1.Picture.Bitmap.TransparentColor:=Image1.Picture.Bitmap.Canvas.Pixels[10,10];
Image1.Picture.Bitmap.TransparentMode:=tmFixed;
Image1.Picture.Bitmap.Transparent:=True;
Image2.Picture.Bitmap.Height := 500;
Image2.Picture.Bitmap.Width := 500;
Image2.Picture.Bitmap.Canvas.Draw(0,0,Image1.Picture.Bitmap);
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

@Christian
in meiner Lazarus Version kommt nur eine Meldung im Ausgabe Fenster die besagt das es
TransparentMode noch nicht "richtig" gibt.

Wenn man die Zeile rauß nimmt macht er es nicht Transparent

Ich habe noch eine 0.9.23 Lazarus Version.

Das mit PaintToRGB32bitScanLine( habe ich wohl übersehen.... :oops:

@theo

Code: Alles auswählen

// Der Geht
  b1:=TCanvasOPBitmap.Create;
  // Der geht nicht mehr
  b2:=TCanvasOPBitmap.Create;
Edit: ich musste nur die IDE neu starten, somit konnte ich b1 und b2 schonmal Installisieren.
Ich habe Probleme zwei TCanvasOPBitmap zu erstellen.
Einer geht beim zweiten hängt sich der Rechner fast auf.

Ich habe eine Zeichen Fläche von 640 X 400 darauf können Sprite(Objekte) von einer Größe 20X20 Pixel drauf.

evlt. ist das zu viel.....

Vielen Dank für eure Versuche mir zu helfen. Ich muss wohl einsehen das es
a: MIt dieser Lazarus Version die ich habe noch nicht geht
b: oder das es auf meiner Art und weise einfach nicht gehen möchte.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

@theo ich verstehe das noch nicht 100%ig:
b1 ist das Hintergrund Bild oder ? das hat bei mir eine Größe von 640 X 400
Das wird einmal zugewiesen

b2: Ist jetzt das Bild das eine Größe von 20X20 Pixeln hat. und dieses Bild soll jetzt Tranzparent auf dem Hintergrund in ein Buffer gezeichnet werden. welches dann Sichtbar gemacht wird.

Code: Alles auswählen

procedure TPluto2DSprite.DrawTrazparent;
var
  x,y:Integer;
  r1,r2:TRect;
 
begin
  tmp.Canvas.Draw(0,0,SpriteImage);
  AssignBitmapToOpBitmap(tmp,b1);
 
  b1.Canvas.Draw(0,0,SpriteMager.Engine.b2);
  b1.TransparentColor:=clwhite;
 
  AssignOpBitmapToBitmap(b1,tmp2);
 
 
//  BitBlt(tmp.canvas.Handle,0,0,Width,Height,BackupBuffer.canvas.Handle,left,top,SRCCOPY);
{/  tmp.Canvas.
  for x:=0 to Width do begin
    for y:=0 to Height do begin
      if SpriteImage.Canvas.Pixels[x,y] <> TranzparentColor then begin
        tmp.Canvas.Pixels[x,y]:=SpriteImage.Canvas.Pixels[x,y];
      end; // if
    end // x
  end; }// y
 
  buffer.canvas.Draw(left,top,tmp2); OutCanvas.Draw(left,top,tmp2);
end;
Das ist jetzt mein Code, damit er Zeit Spart habe ich einiges Rauß genommen und es wird nur noch einmal gemacht.
z.b.das hier:
AssignBitmapToOpBitmap(Engine.BackupBuffer,Engine.b2);
ich glaube das währe viel zu aufwendig das jedes mal zu machen.

und das Installisieren von b1 und b2 habe mache ich auch wo anders b2 wird direkt von der Engine Instlalisiert und b1 vom Sprite.

frei gegeben werden sie im Destroy....

der Fehler ist jetzt zeichnet er die "Wände" Gar nicht mehr.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ES GEHT:

Code: Alles auswählen

procedure TPluto2DSprite.DrawTrazparent;
var
  x,y:Integer;
  r1,r2:TRect;
 
begin
  tmp.Canvas.Draw(0,0,SpriteImage);
  AssignBitmapToOpBitmap(tmp,b1);
 
//  Draw(0,0,SpriteMager.Engine.b2);
  r1:=rect(0,0,Width,Height);
  r2:=rect(left,top,Width,Height);
  b1.Canvas.CopyRect(r1,SpriteMager.Engine.b2.Canvas,r2);
  b1.TransparentColor:=clwhite;
 
  AssignOpBitmapToBitmap(b1,tmp2);
 
 
//  BitBlt(tmp.canvas.Handle,0,0,Width,Height,BackupBuffer.canvas.Handle,left,top,SRCCOPY);
{/  tmp.Canvas.
  for x:=0 to Width do begin
    for y:=0 to Height do begin
      if SpriteImage.Canvas.Pixels[x,y] <> TranzparentColor then begin
        tmp.Canvas.Pixels[x,y]:=SpriteImage.Canvas.Pixels[x,y];
      end; // if
    end // x
  end; }// y
 
  buffer.canvas.Draw(left,top,tmp2); OutCanvas.Draw(left,top,tmp2);
end;
VIELEN DANK THEO deine OpBitmap ist mal wieder Super.... die geschwindigkeit ist auch toll
nur in der Linken ecke zeichnet er was nicht.... ich vermute das es hier ein Fehler sein muss in opBitmap... von CopyRect evlt. aber das sehe ich morgen.

nochmals VIELEN DANK....
MFG
Michael Springwald

Antworten