2014-01-30 35 views
1

我想繪製一個源圖像(GR32 TBitmap32),該圖像在正常(TBitmap)圖像上包含一些完全透明且部分透明的像素,同時保留源圖像中的透明度。如何在TBitmap上透明地繪製TBitmap32?

我用這個:

BMP32.DrawTo(BMP.Canvas.Handle, 0, 0); 

但圖像沒有透明地繪製。


代碼:
一切是非常基本的:我有一個背景位圖(BKG),其中我加載,在應用程序啓動時,形成圖像。 然後在程序中應用我從磁盤(透明的那個)加載第二個圖像,然後在背景上繪製它。

var Bkg: TBitmap; 

procedure TfrmPhoto.FormCreate(Sender: TObject); 
begin 
Bkg:= LoadGraphEx(GetAppDir+ 'bkg.bmp'); { Load bitmap from file } 
{ 
Bkg.Transparent:= TRUE; 
Bkg.PixelFormat:= pf32bit; 
Bkg.TransparentColor:= clPink; 
} 
end; 


procedure TfrmPhoto.Apply2; 
VAR 
    Loader: TBitmap; 
    BMP32: tbitmap32; 
begin 
BMP32:= TBitmap32.Create; 
TRY 

    Loader:= TBitmap.Create; 
    TRY 
    Loader.LoadFromFile('c:\Transparent.BMP'); 
    BMP32.Assign(Loader); 
    FINALLY 
    FreeAndNil(Loader); 
    END; 

    { Mix images } 
    BMP32.DrawTo(Bkg.Canvas.Handle, 0, 0); <----- The problem is here 

    imgPreview.Picture.Assign(Bkg); { This is a TImage where I see the result } 
FINALLY 
    FreeAndNil(BMP32); 
END; 
end; 
+0

請問SSCCE是否太多了? –

+0

請編輯您的問題:添加您的Delphi版本的標籤,並顯示如何爲每個像素的32位股票啓用和設置透明模式TBitmap –

+0

添加的源代碼。 LoadGraphEx可以用LoadFromFile('')替換。否則,該項目應該是可編譯的。 – Ampere

回答

3

它與TransparentBlt()一起工作(但有2個缺點)。

  1. 我不喜歡TransparentBlt處理半透明像素(旋轉圖像的邊緣)的方式。將src圖像合併到背景後,邊緣看起來很糟糕。

  2. 爲了使用TransparentBlt,我必須將源圖像中的顏色(clPink)定義爲透明。這意味着如果源圖像中有一些粉紅色,結果看起來真的很糟糕(它將被視爲透明)。讓我們祈禱非粉紅色的圖像!

如果您發現直接從Bitmap32傳輸圖像(同時保留透明度)到後臺的方法,請發帖,我會接受您的答案!

我在這裏看到的解決方案(仍然是黑客攻擊)是處理TBitmap32中的所有內容,然後將最終結果導出爲TBitmap。我明天會試試這個。


更新:
解決方案:

這是怎麼合併兩個TBitmap32圖像,同時保持透明度:

Dst.CombineMode:= cmBlend; 
Dst.DrawMode:= dmBlend; 
Src.Draw(0, 0, Dst); 

DST和Src的是TBitmap32圖像。它不適用於TBitmap。

3

正如您自己已經建議的那樣,我會推薦完全在TBitmap32域中執行混合操作!原因是它提供了更多的混合方面的選擇,並且在可用的情況下使用MMX/SSE/SSE2(在現代機器上始終如此)。與讓GDI執行混合相比,使用這個可以獲得顯着的性能提升。

特別是這不是一個好主意,因爲GDI通常不使用任何SIMD操作碼(MMX/SSE)。

這也取決於每個零件的變化量。例如,通常情況下背景是相當靜態的,需要在變化時偶爾轉移到TBitmpa32上(例如在VCL樣式或UI主題變化上)。對於每次傳輸(GR32 < - > TBitmap等),可能會發生隱式轉換(DIB < - > DDB),從而使整個混合成爲O(n²)操作。因此,您最好只將一次(使用隱式轉換)轉換爲TBitmap32一次,然後完全在GR32域中執行混合。相反,如果TBitmap32是相當靜態的,並且TBitmap(或背景)發生了很大變化,最好單獨放置GR32並將TBitmap32複製到TBitmap並執行與GDI的混合。儘管GDI混合速度稍慢,但您可以避免使用額外的副本。否則,你的瓶頸將可能是內存吞吐量,而處理速度永遠不會觸及限制。

0

TBitmap32的dmBlend DrawMode打開透明度,但它只在兩個TBitmap32位圖之間起作用。不要使用帶有透明圖像的TBitmap32直接在HDC,Canvas或TBitmap上繪圖。使用dmBlend和DrawTo或BlockTransfer()在另一個TBitmap32上繪圖。例如,要在TBitmap上透明地繪製,請創建中間緩存TBitmap32:

  1. 將圖像從TBitmap複製到緩存TBitmap32;
  2. 使用DrawTo或BlockTransfer()將透明圖像應用於緩存TBitmap32,避免使用Canvas或HDC混合兩個圖像,因爲它們丟失了Alpha圖層信息;
  3. 將圖像從緩存TBitmap32複製回您的TBitmap。