![]() |
Region vom Bitmap erstellen...
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... ) |
Re: Region vom Bitmap erstellen...
ich weiß grad nicht wie, aber man konnte auch ein (Schwarz/Weiß) BitMap irgendwie direkt zur Region hinzufügen.
|
Re: Region vom Bitmap erstellen...
Ja, irgend wie mit ExtCreateRegion. Bin gerade am Nachforschen...
|
Re: Region vom Bitmap erstellen...
im Notfall wirklich Pixel für Pixel :freak:
![]() ![]() |
Re: Region vom Bitmap erstellen...
Liste der Anhänge anzeigen (Anzahl: 1)
Also mal von C nach D.
Delphi-Quellcode:
Das ist allerding (in etwa) genauso wie mein alter Code nur das ich nur mit CombineRgn() und CreateRoundRgn() arbeitete.
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; Irgend wie heht das sicherlich auch anders / einfacher... |
Re: Region vom Bitmap erstellen...
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 :nerd:
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 :? |
Re: Region vom Bitmap erstellen...
Zitat:
Zitat:
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. |
Re: Region vom Bitmap erstellen...
Meinst du sowas?
Delphi-Quellcode:
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) ;)
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; |
AW: Region vom Bitmap erstellen...
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.. ![]() und auf dieser Seite. ![]() 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 |
AW: Region vom Bitmap erstellen...
Push .. :duck:
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:38 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