Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Region aus Umriss erstellen (https://www.delphipraxis.net/175549-region-aus-umriss-erstellen.html)

DeddyH 30. Jun 2013 11:18

Region aus Umriss erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich bräuchte mal eine zündende Idee. Ich habe div. PNG-Grafiken, die an den Seiten transparente Rechtecke aufweisen. Was ich nun erreichen möchte, ist, aus dem nicht transparenten Teil eine Region zu erstellen, die ich dann für SelectClipRgn benutzen kann. Zur Verdeutlichung eine simple Grafik im Anhang, der rote Bereich soll transparent sein, der weiße das gewünschte Clipping darstellen. Dass ich die Transparenz mittels (Alpha)Scanline ermitteln kann, ist mir klar, leider gelingt es mir bislang einfach nicht, damit die Form "herauszustanzen", wahrscheinlich stelle ich mich nur zu blöd an.

Ich bin für jeden Ansatz dankbar.

BUG 30. Jun 2013 12:55

AW: Region aus Umriss erstellen
 
Vielleicht findest du hier Anregung.

EWeiss 30. Jun 2013 12:59

AW: Region aus Umriss erstellen
 
Du kannst die gerne von mir verwenden wenn sie dir zusagt.
Die geht auch mit den kleinsten Pixeln an den Rändern ;)

Form..
Delphi-Quellcode:
procedure TSkinEngine.CreateFormRegion(hParent: HWND; TransColor: COLORREF);
type
  TRectArray = array[0..0] of TRect;
var
  bm:     Bitmap;
  pData:  PRgnData;
  lpRect: PRect;
  hRgn2:  HRGN;
  hRgn1:  HRGN;
  sRegionData: THandle;
  MaxRegions: integer;
  hDIB:   cardinal;
  I, J, K, M: integer;
  bRedraw: boolean;
  pr:     ^TRectArray;
  p32:    PByte;
  lPixel: PRGBQuad;

begin

  hDIB := GetPaintBitmap(hParent);
  if hDIB = 0 then
    exit;

  hRgn1  := 0;
  lPixel := nil;

  GetObject(hDIB, SIZEOF(bm), @bm);

  if TransColor = 0 then
    TransColor := cardinal(lPixel) and $FFFFFF;

  MaxRegions := 4000;

  sRegionData := GlobalAlloc(GMEM_MOVEABLE, SizeOf(RGNDATAHEADER) +
    SizeOf(TRECT) * MaxRegions);
  pData := GlobalLock(sRegionData);
  pData^.rdh.nCount := 0;
  pData^.rdh.dwSize := sizeof(RGNDATAHEADER);
  pData^.rdh.iType := RDH_RECTANGLES;
  pData^.rdh.nRgnSize := 0;
  pData^.rdh.rcBound.Left := 0;
  pData^.rdh.rcBound.Top := 0;
  pData^.rdh.rcBound.Right := bm.bmWidth;
  pData^.rdh.rcBound.Bottom := bm.bmHeight;

  lpRect := PRECT(@pData^.Buffer);

  p32 := PByte(integer(bm.bmBits) + (bm.bmHeight - 1) * bm.bmWidthBytes);
  for J := 0 to bm.bmHeight - 1 do
  begin
    I := 0;
    while I < bm.bmWidth do
    begin
      M := I;

      lPixel := Pointer(integer(p32) + I * SizeOf(cardinal));
      while I < bm.bmWidth do
      begin
        K := MakeColor(0, lPixel^.rgbRed, lPixel^.rgbGreen, lPixel^.rgbBlue) and
          $FFFFFF;

        if K <> integer(TransColor) then
        begin
          Inc(I);
          Inc(lPixel);
        end
        else
          Break;
      end;

      if I > M then
      begin
        if integer(pData^.rdh.nCount) >= MaxRegions then
        begin
          hRgn2 := ExtCreateRegion(nil, sizeof(RGNDATAHEADER) +
            (sizeof(TRECT) * pData^.rdh.nCount), PRGNDATA(pData)^);
          if hRgn1 = 0 then
          begin
            hRgn1 := hRgn2;
          end
          else
          begin
            CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR);
            skDeleteObject(hRgn2);
          end;
          pData^.rdh.nCount := 0;
        end;

        pr := @pData^.Buffer;
        SetRect(pr^[pData^.rdh.nCount], M, J, I, J + 1);
        if M < lpRect.Left then
          lpRect.Left := M;
        if I > lpRect.Right then
          lpRect.Right := I;
        if J < lpRect.Top then
          lpRect.Top := J;
        if J > lpRect.Bottom then
          lpRect.Bottom := J + 1;
        Inc(pData^.rdh.nCount);
        Inc(lpRect);
      end;

      Inc(I);
    end;
    Dec(p32, bm.bmWidthBytes);
  end;

  hRgn2 := ExtCreateRegion(nil, sizeof(RGNDATAHEADER) +
    (sizeof(TRECT) * pData^.rdh.nCount), pData^);

  if hRgn1 = 0 then
  begin
    hRgn1 := hRgn2;
  end
  else
  begin
    CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR);
    DeleteObject(hRgn2);
  end;

  GlobalFree(sRegionData);
  DeleteObject(hDIB);

  if hRgn1 <> 0 then
  begin
    if IsWindowVisible(hParent) then
      bRedraw := True
    else
      bRedraw := False;
    SetWindowRgn(hParent, hRgn1, bRedraw);
  end;

end;
Bitmap..
Delphi-Quellcode:
function TSkinEngine.RegionFromBitmap(hbmp: HBitmap; TransColor: ColorRef): HRGN;

type
  TRectArray = array[0..0] of TRect;
var
  bm:    Bitmap;
  pData: PRgnData;
  lpRect: PRect;
  hRgn2: HRGN;
  hRgn1: HRGN;
  sRegionData: THandle;
  MaxRegions: integer;
  I, J, K, M: integer;
  pr:    ^TRectArray;
  p32:   PByte;
  lPixel: PRGBQuad;

begin

  hRgn1  := 0;
  lPixel := nil;

  GetObject(hbmp, SIZEOF(bm), @bm);

  if TransColor = 0 then
    TransColor := cardinal(lPixel) and $FFFFFF;

  MaxRegions := 4000;

  sRegionData := GlobalAlloc(GMEM_MOVEABLE, SizeOf(RGNDATAHEADER) +
    SizeOf(TRECT) * MaxRegions);
  pData := GlobalLock(sRegionData);
  pData^.rdh.nCount := 0;
  pData^.rdh.dwSize := sizeof(RGNDATAHEADER);
  pData^.rdh.iType := RDH_RECTANGLES;
  pData^.rdh.nRgnSize := 0;
  pData^.rdh.rcBound.Left := 0;
  pData^.rdh.rcBound.Top := 0;
  pData^.rdh.rcBound.Right := bm.bmWidth;
  pData^.rdh.rcBound.Bottom := bm.bmHeight;

  lpRect := PRECT(@pData^.Buffer);

  p32 := PByte(integer(bm.bmBits) + (bm.bmHeight - 1) * bm.bmWidthBytes);
  for J := 0 to bm.bmHeight - 1 do
  begin
    I := 0;
    while I < bm.bmWidth do
    begin
      M := I;

      lPixel := Pointer(integer(p32) + I * SizeOf(cardinal));
      while I < bm.bmWidth do
      begin
        K := MakeColor(0, lPixel^.rgbRed, lPixel^.rgbGreen, lPixel^.rgbBlue) and
          $FFFFFF;

        if K <> integer(TransColor) then
        begin
          Inc(I);
          Inc(lPixel);
        end
        else
          Break;
      end;

      if I > M then
      begin
        if integer(pData^.rdh.nCount) >= MaxRegions then
        begin
          hRgn2 := ExtCreateRegion(nil, sizeof(RGNDATAHEADER) +
            (sizeof(TRECT) * pData^.rdh.nCount), PRGNDATA(pData)^);
          if hRgn1 = 0 then
          begin
            hRgn1 := hRgn2;
          end
          else
          begin
            CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR);
            SkinEngine.skDeleteObject(hRgn2);
          end;
          pData^.rdh.nCount := 0;
        end;

        pr := @pData^.Buffer;
        SetRect(pr^[pData^.rdh.nCount], M, J, I, J + 1);
        if M < lpRect.Left then
          lpRect.Left := M;
        if I > lpRect.Right then
          lpRect.Right := I;
        if J < lpRect.Top then
          lpRect.Top := J;
        if J > lpRect.Bottom then
          lpRect.Bottom := J + 1;
        Inc(pData^.rdh.nCount);
        Inc(lpRect);
      end;

      Inc(I);
    end;
    Dec(p32, bm.bmWidthBytes);
  end;

  hRgn2 := ExtCreateRegion(nil, sizeof(RGNDATAHEADER) +
    (sizeof(TRECT) * pData^.rdh.nCount), pData^);

  if hRgn1 = 0 then
  begin
    hRgn1 := hRgn2;
  end
  else
  begin
    CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR);
    DeleteObject(hRgn2);
  end;

  GlobalFree(sRegionData);
  DeleteObject(hbmp);

  Result := hRgn1;

end;
Die untere ist quasi die gleiche nur das ich hier die Region zurückgebe während sie oben mit
Delphi-Quellcode:
SetWindowRgn(hParent, hRgn1, bRedraw);

direkt gesetzt wird.

GetPaintBitmap(hParent); ist das Handle deines Bitmaps

gruss

DeddyH 30. Jun 2013 13:41

AW: Region aus Umriss erstellen
 
Danke Euch, ich hab das jetzt erst einmal hartkodiert, damit ich hier weiterkomme, schaue mir das aber in einer stillen Stunde nochmal ganz in Ruhe an :thumb:


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