Mega Code Archive

 
Categories / Delphi / Graphic
 

Drawing and mixing trasparent bitmaps

Title: Drawing and mixing trasparent bitmaps Question: Usually, when you make a game, it's very usefull to draw transparent bitmaps (without background). And so, mix bitmaps, (one over another one). This is a simple way to do that. Answer: //--------------------------------------------------------------------------- // Author : Digital Survivor [Esteban Rodrguez Nieto | Jos Plano] // Email : plmad666@gmail.com | jose.plano@gmail.com // Web site : www.ds-studios.com.ar //--------------------------------------------------------------------------- { The following unit draws two bitmaps on a form. One is used as the background and the second one as the foreground. The foreground bitmap is displayed as a "transparent" bitmap. This shows the two bitmaps mixed, one over another, We need to use the known BitBlt API to do the job. This example is quite fast.} Unit TranspBMP; Interface Uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; Type TForm1 = Class (TForm) Procedure FormCreate (Sender : TObject); Procedure FormClose (Sender : TObject; Var Action : TCloseAction); Private { Private declarations } ImageForeGround : TImage; ImageBackGround : TImage; Public { Public declarations } End; Procedure DrawTransparentBitmap (Ahdc : HDC; Image : TImage; XStart, YStart : Word); Var Form1 : TForm1; Implementation {$R *.DFM} Procedure DrawTransparentBitmap (Ahdc : HDC; Image : TImage; XStart, YStart : Word); Var TransparentColor : TColor; CColor : TColorRef; BmAndBack, BmAndObject, BmAndMem, BmSave, BmBackOld, BmObjectOld, BmMemOld, BmSaveOld : HBitmap; HdcMem, HdcBack, HdcObject, HdcTemp, HdcSave : HDC; PtSize : TPoint; Begin // Set the transparent color to be the lower left pixel of the bitmap TransparentColor := Image.Picture.Bitmap.Canvas.Pixels [0, Image.Height - 1]; TransparentColor := TransparentColor or $02000000; HdcTemp := CreateCompatibleDC (Ahdc); SelectObject (HdcTemp, Image.Picture.Bitmap.Handle); // Select the bitmap // Convert bitmap dimensions from device to logical points PtSize.X := Image.Width; PtSize.Y := Image.Height; DPtoLP (HdcTemp, PtSize, 1); // Convert from device logical points // Create some DCs to hold temporary data HdcBack := CreateCompatibleDC (Ahdc); HdcObject := CreateCompatibleDC (Ahdc); HdcMem := CreateCompatibleDC (Ahdc); HdcSave := CreateCompatibleDC (Ahdc); // Create a bitmap for each DC BmAndBack := CreateBitmap (PtSize.X, PtSize.Y, 1, 1, NIL); BmAndObject := CreateBitmap (PtSize.X, PtSize.Y, 1, 1, NIL); BmAndMem := CreateCompatibleBitmap (Ahdc, PtSize.X, PtSize.Y); BmSave := CreateCompatibleBitmap (Ahdc, PtSize.X, PtSize.Y); // Each DC must select a bitmap object to store pixel data BmBackOld := SelectObject (hdcBack, bmAndBack); BmObjectOld := SelectObject (hdcObject, bmAndObject); BmMemOld := SelectObject (hdcMem, bmAndMem); BmSaveOld := SelectObject (hdcSave, bmSave); // Set proper mapping mode SetMapMode (HdcTemp, GetMapMode (Ahdc)); // Save the bitmap sent here, because it will be overwritten BitBlt (HdcSave, 0, 0, PtSize.X, PtSize.Y, HdcTemp, 0, 0, SrcCopy); // Set the background color of the source DC to the color contained in the // parts of the bitmap that should be transparent CColor := SetBkColor (HdcTemp, TransparentColor); // Create the object mask for the bitmap by performing a BitBlt() // from the source bitmap to a monochrome bitmap BitBlt (HdcObject, 0, 0, PtSize.X, PtSize.Y, HdcTemp, 0, 0, SrcCopy); // Set the background color of the source DC back to the original color SetBkColor (HdcTemp, CColor); // Create the inverse of the object mask BitBlt (HdcBack, 0, 0, PtSize.X, PtSize.Y, HdcObject, 0, 0, NotSrcCopy); // Copy the background of the main DC to the destination BitBlt (HdcMem, 0, 0, PtSize.X, PtSize.Y, Ahdc, XStart, YStart, SrcCopy); // Mask out the places where the bitmap will be placed BitBlt (HdcMem, 0, 0, PtSize.X, PtSize.Y, HdcObject, 0, 0, SrcAnd); // Mask out the transparent colored pixels on the bitmap BitBlt (HdcTemp, 0, 0, PtSize.X, PtSize.Y, hdcBack, 0, 0, SrcAnd); // Xor the bitmap with the background on the destination DC BitBlt (HdcMem, 0, 0, PtSize.X, PtSize.Y, hdcTemp, 0, 0, SrcPaint); // Copy the destination to the screen BitBlt (Ahdc, XStart, YStart, PtSize.X, PtSize.Y, HdcMem, 0, 0, SrcCopy); // Place the original bitmap back into the bitmap sent here BitBlt (HdcTemp, 0, 0, PtSize.X, PtSize.Y, HdcSave, 0, 0, SrcCopy); // Delete the memory bitmaps DeleteObject (SelectObject (HdcBack, BmBackOld)); DeleteObject (SelectObject (HdcObject, BmObjectOld)); DeleteObject (SelectObject (HdcMem, BmMemOld)); DeleteObject (SelectObject (HdcSave, BmSaveOld)); // Delete the memory DCs DeleteDC (HdcMem); DeleteDC (HdcBack); DeleteDC (HdcObject); DeleteDC (HdcSave); DeleteDC (HdcTemp); End; Procedure TForm1.FormCreate (Sender : TObject); Begin // Create image controls for two bitmaps and set their parents ImageForeGround := TImage.Create (Form1); ImageForeGround.Parent := Form1; ImageBackGround := TImage.Create (Form1); ImageBackGround.Parent := Form1; // Load images ImageBackGround.Picture.LoadFromFile ('c:\mad.bmp'); ImageForeGround.Picture.LoadFromFile ('c:\utilman.bmp'); // Set background image size to its bitmap dimensions With ImageBackGround Do Begin Left := 0; Top := 0; Width := Picture.Width; Height := Picture.Height; End; // Set the foreground image size centered in the background image With ImageForeGround Do Begin Left := (ImageBackGround.Picture.Width - Picture.Width) Div 2; Top := (ImageBackGround.Picture.Height - Picture.Height) Div 2; Width := Picture.Width; Height := Picture.Height; End; // Do not show the transparent bitmap as it will be displayed BitBlt()ed // by the DrawTransparentBitmap() function ImageForeGround.Visible := False; // Draw the tranparent bitmap note how the DC of the foreground is used in // the function below DrawTransparentBitmap (ImageBackGround.Picture.Bitmap.Canvas.Handle, ImageForeGround, ImageForeGround.Left, ImageForeGround.Top); End; Procedure TForm1.FormClose (Sender: TObject; Var Action : TCloseAction); Begin // Free images ImageForeGround.Free; ImageBackGround.Free; End; End.