OpBitmap - Scanline (Maske für SetShape erzeugen)

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von _X_ »

Der Titel sagt denke ich alles.

Folgenden Code verwende ich um alles, was auf Image1 nicht weiß ist schwarz zu Färben.
Da die Maske für SetShape() aber Schwarz als Transparents und Weiß als sichtbar interpretiert, müsste ich alles was Weiß ist Schwarz färben und alles andere Weiß.
Kompliziert, ich weiß :mrgreen:
Wenn ich jetzt Test halber im Folgenden Code statt:

Code: Alles auswählen

pRGBTRiple(Line)[px].rgbtBlue := 0;
pRGBTRiple(Line)[px].rgbtRed := 0;
pRGBTRiple(Line)[px].rgbtGreen := 0;
das verwende:

Code: Alles auswählen

pRGBTRiple(Line)[px].rgbtBlue := 50;
pRGBTRiple(Line)[px].rgbtRed := 50;
pRGBTRiple(Line)[px].rgbtGreen := 50;

bekomme ich eine SIGSEV.

Jetzt meine Frage: Warum?
Die genaue stelle, an der SIGSEV auftritt füge ich später noch hinzu.
So, hier ist die Position: AV tritt in der Unit GraphType in der Zeile 1624 auf


Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
var
  ConvBitmap: TCanvasOPBitmap;
  px, py: integer;
  Line: PAPixel32;
begin
  ConvBitmap := TCanvasOPBitmap.Create();
  AssignBitmapToOpBitmap(image1.Picture.Bitmap, ConvBitmap);
  ConvBitmap.PixelFormat := opbitmap.pf24bit;
  for py := 0 to Height do
  begin
    Line := ConvBitmap.ScanLine[py];
    for px := 0 to Width do
    begin
        if ((pRGBTRiple(Line)[px].rgbtBlue <> 255) or (pRGBTRiple(Line)[px].rgbtRed <> 255) or (pRGBTRiple(Line)[px].rgbtGreen <> 255)) then
        begin
          pRGBTRiple(Line)[px].rgbtBlue := 0;
          pRGBTRiple(Line)[px].rgbtRed := 0;
          pRGBTRiple(Line)[px].rgbtGreen := 0;
        end;
    end;
  end;
 
  AssignOpBitmapToBitmap(ConvBitmap, Image2.Picture.Bitmap);
  Image2.Repaint;
  ConvBitmap.Free;
end;

mfg _X_

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

Re: OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von theo »

Mit der Scanline muss man schon präzise arbeiten.
Du machst z.B.

for py := 0 to Height do

Was ist hier Height? Vom Formular? Da müsste die Höhe des OpBitmap sein, und dann noch -1 abziehen.
Bei Width dasselbe.

Es gibt in opimglib ein paar Fkt. die du vielleicht brauchen oder dich daran orientieren kannst.

procedure ReplaceColor(Bitmap: TCanvasOPBitmap; Pos: TPoint; NewColor: TColor; Tolerance: byte = 35);
procedure ReplaceColorRGB(Bitmap: TCanvasOPBitmap; Pos: TPoint; NewR, NewG, NewB: Byte; Tolerance: byte = 0);
procedure ReplaceNotColor(Bitmap: TCanvasOPBitmap; NonColor, NewColor: TColor; Tolerance: byte);
procedure BlackToAlpha(Bitmap: TCanvasOPBitmap);
procedure WhiteToAlpha(Bitmap: TCanvasOPBitmap);

_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

Re: OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von _X_ »

Eigentlich war meine Frage hier im Forum also völlig unnötig.
Das ich die falsche Höhe und Breite verwende ist mir einfach nicht aufgefallen.
Der Folgende Code macht genau das, was ich brauche:

Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
var
  ConvBitmap: TCanvasOPBitmap;
  px, py: integer;
  Line: PAPixel32;
begin
  ConvBitmap := TCanvasOPBitmap.Create();
  AssignBitmapToOpBitmap(image1.Picture.Bitmap, ConvBitmap);
  ConvBitmap.PixelFormat := opbitmap.pf24bit;
  for py := 0 to Image1.Height - 1 do
  begin
    Line := ConvBitmap.ScanLine[py];
    for px := 0 to Image1.Width - 1 do
    begin
      if ((pRGBTRiple(Line)[px].rgbtBlue <> 255) or (pRGBTRiple(Line)[px].rgbtRed <> 255) or (pRGBTRiple(Line)[px].rgbtGreen <> 255)) then
      begin
        pRGBTRiple(Line)[px].rgbtBlue := 255;
        pRGBTRiple(Line)[px].rgbtRed := 255;
        pRGBTRiple(Line)[px].rgbtGreen := 255;
      end
      else
      begin
        pRGBTRiple(Line)[px].rgbtBlue := 0;
        pRGBTRiple(Line)[px].rgbtRed := 0;
        pRGBTRiple(Line)[px].rgbtGreen := 0;
      end;
    end;
  end;
 
  AssignOpBitmapToBitmap(ConvBitmap, Image2.Picture.Bitmap);
  Image2.Repaint;
  ConvBitmap.Free;
end;
Danke für die Hilfe Theo!

mfg _X_

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

Re: OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von theo »

_X_ hat geschrieben:Der Folgende Code macht genau das, was ich brauche:


OK, noch logischer wäre allerdings

ConvBitmap.Height
ConvBitmap.Width

zu verwenden.

_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

Re: OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von _X_ »

Ja, aber eigentlich egal, weil sie auf jeden fall gleich groß sind.

mfg _X_

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

Re: OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von theo »

_X_ hat geschrieben:Ja, aber eigentlich egal, weil sie auf jeden fall gleich groß sind.


Nö, erstens ist es aus Prinzip schlecht, solche unsicheren Annahmen zu machen, wenn man die korrekte Variante mit dem gleichen Aufwand haben kann und
zweitens stimmt es tatsächlich nicht.
Image1.Picture.Bitmap.Width muss nicht gleich sein wie Image1.Width.

Kannst du gerne testen beim Resizen des Image.

_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

Re: OpBitmap - Scanline (Maske für SetShape erzeugen)

Beitrag von _X_ »

Hm, wusste ich nicht.
Ich habe es auf ConvBitmap.Height/Width umgestellt.
Vieleicht veröffentliche das Ergebnis mal im Forum, kommt eben darauf an, was herraus kommt ^^

mfg _X_

Antworten