1,183
社区成员
发帖
与我相关
我的任务
分享
var
TransMasks: array [0..2, 0..255] of Byte;
procedure TransparentPaint(DC: HDC; x, y: Integer; Bmp: TBitmap; Invert: Boolean;
ClrCnt: Integer; const TransColors: array of Cardinal);
const
ROP_DstCopy = $00AA0029;
var
MaskBits: Pointer;
mskLnW, srcLnW, srcPxW,
dln, sln, dpx, spx,
i, j, w, h: Integer;
pxMask, m, bk, fr: Byte;
hbmp: HBITMAP;
begin
// only support 24/32 bits bitmap
case Bmp.PixelFormat of
pf24Bit:
begin
srcPxW := 3;
srcLnW := BytesPerScanLine(Bmp.Width, 24, 32);
end;
pf32Bit:
begin
srcPxW := 4;
srcLnW := BytesPerScanLine(Bmp.Width, 32, 32);
end;
else
Exit;
end;
if Invert then
begin
bk := $FF;
fr := 0;
end
else begin
fr := $FF;
bk := 0;
end;
w := Bmp.Width;
h := Bmp.Height;
// setup transparent masks
if ClrCnt > 8 then ClrCnt := 8;
m := 1;
for i := 0 to ClrCnt-1 do
begin
dpx := Integer(@TransColors[i]);
TransMasks[0, PByte(dpx+2)^] := TransMasks[0, PByte(dpx+2)^] or m;
TransMasks[1, PByte(dpx+1)^] := TransMasks[1, PByte(dpx+1)^] or m;
TransMasks[2, PByte(dpx)^] := TransMasks[2, PByte(dpx)^] or m;
m := m shl 1;
end;
// calc monochrome bitmap's line width
mskLnW := ((w+7) shr 3 + 1) and $FFFFFFFE;
// allocate monochrome bitmap's bits data
MaskBits := AllocMem(mskLnW * h);
// dln, sln point to first scanline
dln := Integer(MaskBits);
sln := Integer(Bmp.ScanLine[0]);
// calculating mask bitmap
for i := 1 to h do
begin
dpx := dln;
spx := sln;
pxMask := $7F;
for j := 1 to w do
begin
m := TransMasks[0, PByte(spx)^] and TransMasks[1, PByte(spx+1)^] and TransMasks[2, PByte(spx+2)^];
if (m = 0) or ( m or (m-1) <> m + (m-1) ) then // not transparent color, set pixel bit as foreground bit
PByte(dpx)^ := (PByte(dpx)^ and pxMask) or ((not pxMask) and fr)
else // is transparent color, set pixel bit as transparent bit
PByte(dpx)^ := (PByte(dpx)^ and pxMask) or ((not pxMask) and bk);
Inc(spx, srcPxW); // next source pixel
// next dest pixel
asm
ROR pxMask, 1
JC @@1
INC dpx
@@1:
end;
end;
// next scanline
Inc(dln, mskLnW);
Dec(sln, srcLnW);
end;
// clear transparent masks for next time calling
for i := 0 to ClrCnt-1 do
begin
dpx := Integer(@TransColors[i]);
TransMasks[0, PByte(dpx+2)^] := 0;
TransMasks[1, PByte(dpx+1)^] := 0;
TransMasks[2, PByte(dpx)^] := 0;
end;
// generate monochrome bitmap
hbmp := CreateBitmap(w, h, 1, 1, MaskBits);
// paint
MaskBlt(DC, x, y, w, h, Bmp.Canvas.Handle, 0, 0, hbmp, 0, 0,
MakeRop4(SRCCOPY, ROP_DstCopy));
// free memory
DeleteObject(hbmp);
FreeMem(MaskBits);
end;