2014-08-29 11 views
5

Vấn đềTại sao tôi mất tính minh bạch khi gọi BitBlt hoặc CopyRect?

Tôi cố gắng để sao chép 32x32 gạch từ một TBitmap thành một TPaintbox đó là biên tập bản đồ của tôi, nhưng tôi dường như không thể có được sự minh bạch hoạt động đúng.

Xem hình dưới đây:

Lưu ý: Đối với mục đích của bản demo và thử nghiệm, tôi đã đặt một TImage bên dưới TPaintbox đó sẽ giúp xem nếu tính minh bạch đang làm việc hay không.

enter image description here

Như bạn thấy, gạch thường xuyên vẽ một cách chính xác, nhưng gạch rằng cần phải minh bạch được rút ra với nền trắng.

Tôi bây giờ sử dụng các lớp học thích hợp để quản lý bản đồ và gạch của tôi, và dưới đây là hai cách tôi đã cố gắng vẽ:

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; 

Tôi đã thử sử dụng định dạng hình ảnh bitmap và png cho tileet (hình ảnh bên trái trên scre enshot). Sự khác biệt duy nhất giữa bitmap và png là CopyRect cuộc đấu tranh để vẽ ngay cả một vài gạch khi nó là một png, nhưng BitBlt quản lý để vẽ mà không có bất kỳ hạn chế rõ ràng.

Dù sao, làm cách nào để sao chép/vẽ một phần của TBitmap lên TPaintbox mà không làm mất tính minh bạch hoặc trong trường hợp của tôi mà không sao chép nền trắng?

Cập nhật 1

Tiếp theo từ một số các ý kiến ​​dưới đây tôi đã cố gắng gọi AlphaBlend chức năng nhưng điều này vẫn khiến kết quả không mong muốn (chú ý màu xanh xung quanh vùng trong suốt):

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

Cảm ơn.

+5

BitBlt, StretchBlt (CopyRect) không có hỗ trợ minh bạch. Sử dụng Canvas.Draw. –

+6

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

+0

@RemyLebeau Tôi đang xem 'TransparentBlt' ngay bây giờ ... Lazarus dường như ghét thêm các đơn vị: 'JwaWinGDI' mặc dù để sử dụng vì nó messes lên các loại khác như TBitmap, vì vậy tôi phải khai báo các loại tiêu chuẩn như' Graphics.TBitmap' vv –

Trả lời

0

Có 3 cách phổ biến để làm việc với bitmap trong suốt, hai sử dụng công cụ Delphi tiêu chuẩn đầu tiên và một phần ba đòi hỏi một thư viện của bên thứ ba:

Nếu bạn sử dụng một trong hai phương pháp chuẩn, không sử dụng BitBlt hoặc CopyRect. Sử dụng phương thức Vẽ của chủ hình ảnh trong suốt để vẽ trên canvas đích.

  1. Giữ các ảnh bitmap trong suốt trong danh sách TImageList và sử dụng TImageList.Draw để vẽ trực tiếp lên khung đích (không tô màu trên bitmap trung gian vì bạn sẽ mất tính minh bạch tại đây). Để thêm hình ảnh vào danh sách hình ảnh vào thời gian thiết kế, nhấp chuột phải và chọn Trình biên tập danh sách hình ảnh. Hình ảnh trong danh sách có thể là ảnh bitmap, biểu tượng, hình ảnh PNG, GIF và JPEG: bất kỳ loại hình ảnh nào mà TImage hỗ trợ.ImageLists cũng hỗ trợ định dạng 32 bit, do đó, các bitmap phối trộn alpha và các tệp PNG hoạt động chính xác. Bạn cũng có thể tải hình ảnh trong thời gian chạy. Nếu bitmap của bạn được lưu trữ ở dạng không trong suốt nhưng có màu trong suốt, bạn có thể sử dụng phương thức TImageList.AddMasked (Bitmap: TBitmap; MaskColor: TColor). Bạn có thể tự chuyển màu trong suốt trong tham số thứ hai hoặc clDefault để cho phép người tạo hình ảnh lấy màu của điểm ảnh dưới cùng bên trái.
  2. Giữ hình ảnh của bạn trong tệp PNG hoặc tài nguyên và tải chúng vào tệp Vcl.Imaging.pngimage.TpngImage, sau đó gọi TpngImage.Draw để vẽ PNG trực tiếp trên canvas đích. Như trên, không vẽ trên bitmap trung gian vì bạn sẽ mất tính minh bạch tại đây.
  3. Sử dụng TBitmap32 từ GR32, thư viện của bên thứ ba. Trong trường hợp này, không sử dụng TBitmap32 với hình ảnh trong suốt để vẽ trực tiếp trên HDC, Canvas hoặc TBitmap. Sử dụng dmBlend và DrawTo hoặc BlockTransfer() để vẽ trên một TBitmap32 khác. Ví dụ, để vẽ một cách minh bạch trên một TBitmap, tạo một bộ đệm trung gian TBitmap32: (1) Sao chép hình ảnh từ TBitmap vào bộ đệm TBitmap32; (2) Áp dụng hình ảnh trong suốt của bạn vào cache TBitmap32 bằng DrawTo hoặc BlockTransfer(), tránh sử dụng Canvas hoặc HDC để trộn hai ảnh vì chúng mất thông tin lớp alpha; (3) Sao chép ảnh từ bộ nhớ cache TBitmap32 vào TBitmap của bạn.
Các vấn đề liên quan