2014-08-29 11 views
5

ProblemDlaczego tracę przezroczystość podczas wywoływania BitBlt lub CopyRect?

Próbuję skopiować 32x32 tabliczki z TBitmap w TPaintbox który jest mój edytor map, ale nie wydaje się uzyskać przezroczystość działa poprawnie.

Patrz zdjęcie poniżej:

Uwaga: Do celów demonstracji i testów, jakie postawił TImage pod spodem TPaintbox który pomoże sprawdzić, czy przezroczystość pracuje czy nie.

enter image description here

Jak widać, regularne płytki rysować poprawnie, ale płytki, które powinny być przezroczyste są rysowane z białym tłem.

Jestem teraz używając odpowiednich klas zarządzać moje mapy i płytek, a poniżej jest na dwa sposoby próbowałem rysunek:

CopyRect:

procedure TMap.DrawTile(Tileset: TBitmap; MapX, MapY, TileX, TileY: Integer; 
    MapCanvas: TCanvas); 
begin 
    if TileIsFree(MapX, MapY) then 
    begin 
    MapCanvas.CopyRect(
     Rect(MapX, MapY, MapX + fTileWidth, MapY + fTileHeight), 
     Tileset.Canvas, 
     Rect(TileX, TileY, TileX + fTileWidth, TileY + fTileHeight)); 
    end; 
end; 

BitBlt

procedure TMap.DrawTile(Tileset: TBitmap; MapX, MapY, TileX, TileY: Integer; 
    MapCanvas: TCanvas); 
begin 
    if TileIsFree(MapX, MapY) then 
    begin 
    BitBlt(
     MapCanvas.Handle, 
     MapX, 
     MapY, 
     fTileWidth, 
     fTileHeight, 
     Tileset.Canvas.Handle, 
     TileX, 
     TileY, 
     SRCCOPY); 
    end; 
end; 

Próbowałem używać formatów bitmapowych i png dla zestawu klocków (lewy obrazek na scre enshot). Jedyną różnicą między bitmapą i png jest to, że CopyRect stara się narysować nawet kilka płytek, gdy jest to png, ale BitBlt udaje się narysować bez żadnych oczywistych wad.

W każdym razie, w jaki sposób skopiować/narysować część TBitmap na TPaintbox bez utraty przejrzystości, lub w moim przypadku bez kopiowania również białego tła?

Update 1

Opierając się na niektóre komentarze poniżej Próbowałem wywołanie funkcji AlphaBlend ale nadal pozostawia niepożądane skutki (uwaga niebieskie kolory wokół obszarów przezroczystych):

procedure TMap.DrawTile(Tileset: Graphics.TBitmap; MapX, MapY, TileX, TileY: Integer; 
    MapCanvas: TCanvas); 
var 
    BlendFn: TBlendFunction; 
begin 
    if TileIsFree(MapX, MapY) then 
    begin 
    BlendFn.BlendOp := AC_SRC_OVER; 
    BlendFn.BlendFlags := 0; 
    BlendFn.SourceConstantAlpha := 255; 
    BlendFn.AlphaFormat := AC_SRC_ALPHA; 

    AlphaBlend(
     MapCanvas.Handle, 
     MapX, 
     MapY, 
     fTileWidth, 
     fTileHeight, 
     Tileset.Canvas.Handle, 
     TileX, 
     TileY, 
     fTileWidth, 
     fTileHeight, 
     BlendFn); 
    end; 
end; 

enter image description here

Dzięki.

+5

BitBlt, StretchBlt (CopyRect) nie obsługuje przezroczystości. Użyj Canvas.Draw. –

+6

Lub ['TransparentBlt()'] (http://msdn.microsoft.com/en-us/library/dd145141.aspx) –

+0

@RemyLebeau Patrzę teraz na 'TransparentBlt' ... Łazarz nie lubi dodawać the unit: 'JwaWinGDI' chociaż do zastosowań, ponieważ zakłóca inne typy, takie jak TBitmap, więc muszę zadeklarować standardowe typy, takie jak' Graphics.TBitmap' itd. –

Odpowiedz

0

Istnieją 3 popularne sposoby pracy z przezroczystych bitmap, dwa pierwsze wykorzystanie standardowych narzędzi Delphi i trzeci wymaga biblioteki innej firmy:

Jeśli używasz jednej z dwóch metod standardowych, nie używaj BitBlt lub CopyRect. Użyj metody Draw przezroczystego uchwytu obrazu, aby narysować płótno docelowe.

  1. Miej przezroczystych bitmap w TImageList i używać TImageList.Draw do malowania bezpośrednio na płótnie docelowego (nie malować na bitmapy pośredniczących, ponieważ można stracić przejrzystość tutaj). Aby dodać obrazy do listy obrazów w czasie projektowania, kliknij prawym przyciskiem myszy i wybierz Edytor listy obrazów. Obrazy na liście mogą być mapami bitowymi, ikonami, obrazami PNG, GIF i JPEG: dowolny typ obrazu obsługiwany przez program TImage.ImageLists obsługują także format 32-bitowy, więc pliki bitmapowe alfa i PNG działają poprawnie. Możesz również ładować obrazy w czasie wykonywania. Jeśli twoje bitmapy są przechowywane w nieprzezroczystej postaci, ale jest przezroczysty, możesz użyć metody TImageList.AddMasked (Bitmap: TBitmap; MaskColor: TColor). Możesz przekazać przezroczysty kolor w drugim parametrze lub clDefault, aby pozwolić, by imagelist wybrał kolor lewego dolnego piksela.
  2. Zachowaj obrazy w plikach PNG lub zasobach i załaduj je do pliku Vcl.Imaging.pngimage.TpngImage, a następnie wywołaj plik TpngImage.Draw, aby pomalować plik PNG bezpośrednio na obszarze docelowym. Jak wyżej, nie maluj na pośrednich bitmapach, ponieważ stracisz tu przezroczystość.
  3. Użyj TBitmap32 z GR32, biblioteki innej firmy. W takim przypadku Nie używaj TBitmap32 z przezroczystymi obrazami do rysowania bezpośrednio na HDC, Canvas lub TBitmap. Użyj dmBlend i DrawTo lub BlockTransfer(), aby narysować inną TBitmap32. Na przykład, aby rysować przezroczyście na mapie TBit, utwórz pośrednią pamięć podręczną TBitmap32: (1) Skopiuj obraz z TBitmap do pamięci podręcznej TBitmap32; (2) Zastosuj przezroczysty obraz do pamięci podręcznej TBitmap32 przy użyciu funkcji DrawTo lub BlockTransfer(), unikaj używania Canvas lub HDC do mieszania dwóch obrazów, ponieważ tracą informacje o warstwie alfa; (3) Skopiuj obraz z pamięci podręcznej TBitmap32 na TBitmap.
Powiązane problemy