AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Region vom Bitmap erstellen...

Ein Thema von turboPASCAL · begonnen am 5. Sep 2009 · letzter Beitrag vom 3. Aug 2011
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#1

Region vom Bitmap erstellen...

  Alt 5. Sep 2009, 17:08
Hi,

isch möschde eine Region (HRGN) von einem Bitmap auf Basis einer bestimmten Farbe erstellen.
Soweit sogut. Das eigentliche Problem an der Sache ist das Auffinden und Zusammensetzen
der Regionen.

Ich kann ja jeden passenden Pixel zu einer Region "adden", das ist mir aber zu unoptimal™.
Nun suche ich einen Algo. der was taugt.

Hat jemand einen Vorschlag ?

( ich hatte mir schon mal vor längerer zeit was gebastelt, leider finde ich es nicht mehr... )
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

Re: Region vom Bitmap erstellen...

  Alt 5. Sep 2009, 17:42
ich weiß grad nicht wie, aber man konnte auch ein (Schwarz/Weiß) BitMap irgendwie direkt zur Region hinzufügen.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#3

Re: Region vom Bitmap erstellen...

  Alt 5. Sep 2009, 17:50
Ja, irgend wie mit ExtCreateRegion. Bin gerade am Nachforschen...
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

Re: Region vom Bitmap erstellen...

  Alt 5. Sep 2009, 18:00
im Notfall wirklich Pixel für Pixel
http://www.bobpowell.net/region_from_bitmap.htm

http://www.codeguru.com/cpp/g-m/bitm...icle.php/c1751
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#5

Re: Region vom Bitmap erstellen...

  Alt 6. Sep 2009, 08:13
Also mal von C nach D.
Delphi-Quellcode:
function BitmapToRegion(bmp: TBitmap; TransparentColor: TColor): HRGN;
const
  AllocUnit = 100;
type
  PRectArray = ^TRectArray;
  TRectArray = array[0..(MaxInt div SizeOf(TRect)) - 1] of TRect;
var
  pr: PRectArray; // used to access the rects array of RgnData by index
  h: HRGN; // Handles to regions
  RgnData: PRgnData; // Pointer to structure RGNDATA used to create regions
  x, y, x0: Integer; // coordinates of current rect of visible pixels
  maxRects: Cardinal; // Number of rects to realloc memory by chunks of AllocUnit
begin
  Result := 0;

  maxRects := AllocUnit;
  GetMem(RgnData, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * maxRects));
  try
    with RgnData^.rdh do
    begin
      dwSize := SizeOf(RGNDATAHEADER);
      iType := RDH_RECTANGLES;
      nCount := 0;
      nRgnSize := 0;
      SetRect(rcBound, MAXLONG, MAXLONG, 0, 0);
    end;

    for y := 0 to bmp.Height - 1 do
    begin
      x := 0;
      while x < bmp.Width - 1 do
      begin

        // Pixel suchen die der transp. Farbe entsprechen & x solange erhöhen
        x0 := x;
        while x < bmp.Width - 1 do
        begin
          // ohne scanline zu Testzwecken - mit (Windows.)GetPixel
          if GetPixel(bmp.Canvas.Handle, x, y) = DWORD(TransparentColor) then break;
          Inc(x);
        end;

        // test to see if we have a non-transparent area in the image
        if x > x0 then
        begin
          // increase RgnData by AllocUnit rects if we exceeds maxRects
          if RgnData^.rdh.nCount >= maxRects then
          begin
            Inc(maxRects, AllocUnit);
            ReallocMem(RgnData, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * MaxRects));
          end;

          // Add the rect (x0, y)-(x, y+1) as a new visible area in the region
          pr := @RgnData^.Buffer; // Buffer is an array of rects
          with RgnData^.rdh do
          begin
            SetRect(pr[nCount], x0, y, x, y + 1);
            // adjust the bound rectangle of the region if we are "out-of-bounds"
            if x0 < rcBound.Left then rcBound.Left := x0;
            if y < rcBound.Top then rcBound.Top := y;
            if x > rcBound.Right then rcBound.Right := x;
            if y + 1 > rcBound.Bottom then rcBound.Bottom := y + 1;
            Inc(nCount);
          end;
        end; // if x > x0

        // Need to create the region by muliple calls to ExtCreateRegion, 'cause
        // it will fail on Windows 98 if the number of rectangles is too large
        if RgnData^.rdh.nCount = 2000 then
        begin
          h := ExtCreateRegion(nil, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * maxRects), RgnData^);
          if Result > 0 then
          begin // Expand the current region
            CombineRgn(Result, Result, h, RGN_OR);
            DeleteObject(h);
          end
          else // First region, assign it to Result
            Result := h;
          RgnData^.rdh.nCount := 0;
          SetRect(RgnData^.rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
        end;
        Inc(x);
      end; // scan every sample byte of the image
    end;

    // need to call ExCreateRegion one more time because we could have left
    // a RgnData with less than 2000 rects, so it wasn't yet created/combined
    h := ExtCreateRegion(nil, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * MaxRects), RgnData^);
    if Result > 0 then
    begin
      CombineRgn(Result, Result, h, RGN_OR);
      DeleteObject(h);
    end else
      Result := h;
  finally
    FreeMem(RgnData, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * MaxRects));
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  ARgn: HRGN;
  ABitmap: TBitmap;
begin
  ABitmap := TBitmap.Create;
  try
    ARgn := BitmapToRegion(Image1.Picture.Bitmap, clFuchsia);
    SetWindowRgn(Form1.Handle, ARgn, True);
  finally
    ABitmap.Free;
  end;
end;
Das ist allerding (in etwa) genauso wie mein alter Code nur das ich nur mit CombineRgn() und CreateRoundRgn() arbeitete.

Irgend wie heht das sicherlich auch anders / einfacher...
Angehängte Dateien
Dateityp: zip extcreateregiondemo_840.zip (225,6 KB, 33x aufgerufen)
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

Re: Region vom Bitmap erstellen...

  Alt 6. Sep 2009, 09:44
Vorallen da ich mir etwas sichter bin, mal eine Version gesehn zu haben, wo ein Bitmap direkt einer Funktion gegeben wurde und fertig war's

Aber ich hatte vor 'ner ganzen Weile selber nochmal danach gesucht und nix gefunden,
wobei ich mir halt sicher war das noch 'ne größere Weile vorher (ist schon bestimmt mindestens 3 Jahre her) mal gesehn zu haben
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#7

Re: Region vom Bitmap erstellen...

  Alt 6. Sep 2009, 10:32
Zitat:
wobei ich mir halt sicher war das noch 'ne größere Weile vorher (ist schon bestimmt mindestens 3 Jahre her) mal gesehn zu haben
Ja, das kenn ich.

Zitat:
Vorallen da ich mir etwas sichter bin, mal eine Version gesehn zu haben, wo ein Bitmap direkt einer Funktion gegeben wurde und fertig
So in etwa dachte ich auch daran.

In der TRgnData-Strucktur müsste man den "Daten"-Buffer irgend wie nutzen.

Aber erst mal muss man verstehen wie und was TRgnData-Strucktur macht usw.
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Progman

Registriert seit: 31. Aug 2007
Ort: 99974 MHL
695 Beiträge
 
Delphi 10.1 Berlin Starter
 
#8

Re: Region vom Bitmap erstellen...

  Alt 6. Sep 2009, 10:51
Meinst du sowas?
Delphi-Quellcode:
type
  TRGBArray = array[0..32767] of TRGBTriple;
  PRGBArray = ^TRGBArray;

type
  TfrmMain = class(TForm)
    ...
  private
    { Private-Deklarationen }
    HG: TBitmap;
    FRegion: THandle;
    function CreateRegion(Bmp: TBitmap): THandle;
  public
    ...
  end;

implementation

function TfrmMain.CreateRegion(Bmp: TBitmap): THandle;
var
  X, Y, StartX: Integer;
  Excl: THandle;
  Row: PRGBArray;
  TransparentColor: TRGBTriple;
begin
  Bmp.PixelFormat := pf24Bit;
  Result := CreateRectRGN(0, 0, Bmp.Width, Bmp.Height);
  for Y := 0 to Bmp.Height - 1 do
  begin
    Row := Bmp.Scanline[Y];
    StartX := -1;
    if Y = 0 then
      TransparentColor := Row[0];
    for X := 0 to Bmp.Width - 1 do
    begin
      if (Row[X].rgbtRed = TransparentColor.rgbtRed) and
        (Row[X].rgbtGreen = TransparentColor.rgbtGreen) and
        (Row[X].rgbtBlue = TransparentColor.rgbtBlue) then
      begin
        if StartX = -1 then StartX := X;
      end
      else
      begin
        if StartX > -1 then
        begin
          Excl := CreateRectRGN(StartX, Y, X + 1, Y + 1);
          try
            CombineRGN(Result, Result, Excl, RGN_DIFF);
            StartX := -1;
          finally
            DeleteObject(Excl);
          end;
        end;
      end;
    end;
    if StartX > -1 then
    begin
      Excl := CreateRectRGN(StartX, Y, Bmp.Width, Y + 1);
      try
        CombineRGN(Result, Result, Excl, RGN_DIFF);
      finally
        DeleteObject(Excl);
      end;
    end;
  end;
end;


//Borderstyle muss bsNone sein
procedure TfrmMain.FormCreate(Sender: TObject);
var Bmp: TBitmap;
begin
  HG:=TBitmap.Create;
  HG.LoadFromFile(ResPath+'Monitor.bmp');
  Bmp := TBitmap.Create;
  try
    bmp.Assign(HG);
    Width:=HG.Width;
    ClientHeight:=HG.Height;
    FRegion := CreateRegion(Bmp);
    SetWindowRGN(Handle, FRegion, True);
  finally
    Bmp.Free;
  end;
  ...
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  DeleteObject(FRegion);
  HG.Free;
end;

procedure TfrmMain.FormPaint(Sender: TObject);
begin
  BitBlt(canvas.handle, 0, 0, Clientwidth, Clientheight,HG.Canvas.handle, 0, 0, SRCCOPY);
end;
Das erzeugt einer Region anhand eines Bitmaps. Das Fenster hat dann die Form des Bitmaps. Als transparent wird die Farbe der Pixels 0,0 festgelegt (glaub ich)
Karl-Heinz
Populanten von Domizilen mit fragiler, transparenter Aussenstruktur sollten sich von der Translation von gegen Deformierung resistenter Materie distanzieren!
(Wer im Glashaus sitzt sollte nicht mit Steinen werfen)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

AW: Region vom Bitmap erstellen...

  Alt 28. Jul 2011, 05:43
Ich möchte meinen Button eine region verpassen
Mit Standard Button (TButton) funktioniert das aber leider nicht mit nonvcl Button.

Habe es mal mit beiden Functionen versucht.
Diese hier..
http://www.delphipraxis.net/948896-post5.html

und

auf dieser Seite.
http://www.delphipraxis.net/404171-post7.html


beides will nicht funktionieren.
Warum ist mir schleierhaft.

jemand eine Idee?


Delphi-Quellcode:
      if Region > 0 then
      begin
        GdipCreateHBITMAPFromBitmap(pointer(img), hbmReturn, $000000);
        if hbmReturn <> 0 then
        begin
          ABitmap := TBitmap.Create;
          ABitmap.Handle := hbmReturn;
          ABitmap.Width := btW;
          ABitmap.Height:= btH;

          FHImageButton := CreateWindowEx(WS_EX_TRANSPARENT, SKIMAGEBUTTON,
            '', Style, x, y, btW, btH, hOwner, ButID, SkinEngine.skInstance, nil);
          if FHImageButton <> 0 then
          begin
            SkinEngine.SetImageProperty(FHImageButton, PROP_IMAGE_BACK, Img);
            SkinEngine.SetImageProperty(FHImageButton, PROP_STYLE, BS_BITMAP);
            SkinEngine.SetImageProperty(FHImageButton, PROP_STATEMAX, StateMax);

            ARgn := BitmapToRegion(ABitmap.Handle, imgw, imgh, RGB(255,0,255), 0);
            SetWindowRgn(FHImageButton, ARgn, True);
            ABitmap.Free;
          end else
          begin
            // Lösche das Image
            SkinEngine.DeleteResource(hOwner, Img);
          end;
        end;

gruss

Geändert von EWeiss (28. Jul 2011 um 06:31 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#10

AW: Region vom Bitmap erstellen...

  Alt 28. Jul 2011, 07:32
Push ..

Hab mal ein Button Beispiel von Luckie umgestrickt. (nonvcl)
Also der Rosa bereich des Button soll abgeschnitten werden.

Vielleicht schaut ja mal jemand in den Sample rein.

gruss

Geändert von EWeiss (11. Jul 2019 um 17:03 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 13:17 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