好吧,我承认:这是在无聊中写的一个无聊的图形函数

阿呆_ 2009-09-29 02:51:47
正在无聊地等待测试机执行完庞大的测试任务。为了避免睡着,随手写了一个画图的过程。 没多大用处,不过是指定图片的透明色然后画透明bitmap到DC,呃,可以一次性指定图片中最多8种颜色都作为透明色。

速度还可以。和TBitmap.Draw比较了一下,画1280*1024*24bit图片各100次:

指定一种透明色,我的过程耗时2375毫秒,TBitmap.Draw耗时4078毫秒。
指定8种透明色,我的过程耗时2279毫秒,TBitmap.Draw(还是一种透明色)耗时4031毫秒

代码奉上:


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;

...全文
538 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
xhj12077021 2009-11-13
  • 打赏
  • 举报
回复
先做记号

下班好好研究
wfl568 2009-11-13
  • 打赏
  • 举报
回复
mark
wliaoc 2009-11-13
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 hjkto 的回复:]
引用 31 楼 idle_ 的回复:
不能直接用我提供的图片, 那个是JPG图片,是有损压缩的,真实颜色值并不是你看到的,比如红色可能颜色值是$000000FE而不是clRed($000000FF), 而且并不是一块同色区域中的颜色值都相等(尽管你肉眼看上去是一样的)


能不能给个图片,或生成图片的代码,我也刚学图形编程,希望前辈指点
[/Quote]

自己用画布弄张图
sandok 2009-10-26
  • 打赏
  • 举报
回复
怎么那么厉害呢
hxy3100 2009-10-26
  • 打赏
  • 举报
回复
lz说的不错,换张自己画的图就可以了
大肚肥肥 2009-10-24
  • 打赏
  • 举报
回复
mark
syonmsn 2009-10-24
  • 打赏
  • 举报
回复
学习学习!
码农天天向上 2009-10-14
  • 打赏
  • 举报
回复
把我头都整晕~~
hjkto 2009-10-14
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 idle_ 的回复:]
不能直接用我提供的图片, 那个是JPG图片,是有损压缩的,真实颜色值并不是你看到的,比如红色可能颜色值是$000000FE而不是clRed($000000FF), 而且并不是一块同色区域中的颜色值都相等(尽管你肉眼看上去是一样的)
[/Quote]

能不能给个图片,或生成图片的代码,我也刚学图形编程,希望前辈指点
hjkto 2009-10-13
  • 打赏
  • 举报
回复
楼主,请教一下,复制你的代码,下载你提供的图片,也加上哪一句了
为什么按钮按一后,只有黄色部分变动了一小点,其它的还是原图呢?
fenshm 2009-10-13
  • 打赏
  • 举报
回复
mark`!
dd_zhouqian 2009-10-13
  • 打赏
  • 举报
回复
不错,很强
阿呆_ 2009-10-13
  • 打赏
  • 举报
回复
不能直接用我提供的图片, 那个是JPG图片,是有损压缩的,真实颜色值并不是你看到的,比如红色可能颜色值是$000000FE而不是clRed($000000FF), 而且并不是一块同色区域中的颜色值都相等(尽管你肉眼看上去是一样的)
winstonbonaparte 2009-10-12
  • 打赏
  • 举报
回复
强悍
ck_邬 2009-10-12
  • 打赏
  • 举报
回复
标记一下..估计很好玩.
beifangke 2009-10-12
  • 打赏
  • 举报
回复
不错!
linghengmao 2009-10-12
  • 打赏
  • 举报
回复
幫頂
cathasninelives 2009-10-11
  • 打赏
  • 举报
回复
拜读一下
mdejtod 2009-10-05
  • 打赏
  • 举报
回复
那就要问楼主了哟,
hjkto 2009-10-05
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 mdejtod 的回复:]
关键要看你要透明的图片是什么样的,我都说了,如果背景色不是纯色的,是不行的!至于楼主的代码,我倒没认真的去看,
[/Quote]

图片,就是楼主指供的哪张图片
加载更多回复(21)

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧