• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Delphi 7中对StretchBlt, StretchDIBits, DrawDibDraw, BitBlt 的性能测试 - 原创 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

我的天哪,上一篇博文是2年前的事情了。看来又虚度了2年光阴,继续学习。。。
本文算是副产品,正品是利用FFmpeg从任意视频中生成GIF片段的小程序,等写完了再发。不为别的,只是为了给儿子做动图,且看不惯这种工具也要收费!

声明

本文是首先看到了求比Stretchblt方法更快的缩放算法的帖子,请参看其中署名为“张辉明”的回复。我做了优化和一些修正,但DrawDibDraw部分的调用是原文照录的。(其实上文就是我Bing了DrawDibDraw时搜到的。)

为什么要测试 StretchBlt, StretchDIBits, DrawDibDraw 的性能

因为视频回放需要很高的显示性能,解码占了很多计算量,留给显示的时间不多,能优化则优化吧。

其实现在的CPU跑个视频播放已经绰绰有余了,GPU压根就不必用。即便是用Delphi自带的TImage控件,用Bitmap往里填也可以满足普通播放需求了。如果时光倒流到10年前,那可真是得去研究DirectX、OpenGL了。可惜关于这哥俩,大部分都是C、C++的资源,我啃了半天SDL,觉得有点杀鸡用牛刀。所以就想着先实现需求吧,真的不行了再优化吧。在我的Intel i3 3220上,用StretchDIBits播放视频时最多也就跑了22%。

为什么还抱着Delphi不放?

  1. 性价比第一
    敢问性能、便捷、体积俱佳的Windows开发环境,谁敢和Delphi比?C#,Java是优秀,可为了一个小功能就跑它个虚拟机,实在划不来啊。C++倒是够sharp,可学习过程太痛苦了,代码还不容易写。
  2. 全能
    都说Python好,可我眼拙,实在看不出来好在哪里,局限性太大。唯一的好处是能让新手快速上手编程,还有一个好处是能让你忘记计算机是怎么运作的!
  3. 怀旧
    十几年前自学的东西,从Delphi 3开始用,有感情了。只要Windows不停止对32位程序的支持,我就会一直用下去。(关于这一点,我要狠狠鄙视Apple一下。)
  4. Delphi 7是经典
    和Visual Studio、水果一样,当年Borland的产品也有大小年,逢单的版本就是稳定一些。虽然轮子有时候得从头开始造,但是“知其所以然”是乐在其中的事,相信我!

测试结果

如果只关心结果,或者对Delphi不屑,那您就不必往下看了,我先给出结果吧。为您节省点时间。严格意义上说,BitBlt不属于其他哥仨的阵营,因为不用缩放,所以速度当然快了。放在这里比较,就当是个Baseline吧。

  1. DrawDibDraw最快(1ms级别)。
    不到StretchBlt和StretchDIBits的一半,且不需要用SetStretchBltMode设置什么缩放模式,画质看不出分别。
  2. StretchBltStretchDIBits难分伯仲。
    用了色彩拟合模式(HALFTONE)的话会大大增加计算量,耗时4倍,比DrawDibDraw慢1个数量级。建议缩小图像时可以用COLORONCOLOR模式,肉眼看不出区别,但可以比HALFTONE模式提速4倍!
API COLORONCOLOR HALFTONE
BitBlt 400 400
DrawDibDraw 1125 1125
StretchBlt 3000 11406
StretchDIBits 3203 11576
  • 测试用机:CPU: Intel i3 3220,内存: 8G DDRIII 1333,显卡: AMD Radeon HD 7700 (对测试结果没影响吧),Windows 10专业版
  • 测试次数:1000次
  • 时间单位:millisecond(毫秒)
  • COLORONCOLOR:删除不需要的点。
    这是SetStretchBltMode的参数,指定目标设备(区域)的缩放模式。在用StretchDIBits和StretchBlt时必须得设置一个缩放模式,不然,嘿嘿,惨不忍睹。官方说明是:“Deletes the pixels. This mode deletes all eliminated lines of pixels without trying to preserve their information.”,中文意思大概就是:删除不需要的像素点。该模式删除所有无用的点阵,这些点的所有信息都不予保留。 参见SetStretchBltMode
  • HALFTONE:将源区域的颜色溶入目标区域中去。
    作用同上。官方说明是:“Maps pixels from the source rectangle into blocks of pixels in the destination rectangle. The average color over the destination block of pixels approximates the color of the source pixels.”中文大概意思是:将源矩形区域的像素点信息拟合到目标区域周边的多个像素块中。目标区域多个像素块的颜色值会进行平均,以便最大程度地接近源像素的色彩。参见SetStretchBltMode

源码

界面

就放了几个按钮而已,名称末尾为C的表示用了COLORONCOLOR模式,为H的表示用了HALFTONE模式。还有一个Timage控件。

常量

FileName定义了Bmp图片文件名,Count定义了测试循环的次数。

FileName='1.bmp';
Count=1000;
FontSize=20;

BMP文件读取

因为StretchBlt和BitBlt只需要提供源HDC,不需要用tagBITMAPINFO和原始RGB数据区作为参数,所以直接用了TBitmap控件载入图片文件。

procedure TMainForm.StretchBltDisplay;
var
  bmp : TBitmap ;
  i : Integer ;
  Start : DWORD ;
begin
  Bmp:= TBitmap.Create ;
  bmp.LoadFromFile(FileName);

  Start := GetTickCount ;
  for i := 1 to count do
  begin
    StretchBlt(image1.Canvas.Handle, 0, 0, image1.ClientWidth, image1.ClientHeight,
              bmp.Canvas.Handle, 0,0,bmp.Width,bmp.Height, SRCCOPY);
    image1.Canvas.TextOut(10,10,inttostr(i));
    image1.Refresh;
  end;
  MainForm.Caption := IntToStr(GetTickCount - Start);

  bmp.Free ;
end;

DrawDibDraw和DrawDibDraw都需要用到BMP原始信息做参数,所以只好写了个LoadBmp从文件中读取数据。
因为要把原始信息带出去,所以带了var前缀。

procedure LoadBmp(bmpFile: String; var bmpinfo:TBitmapInfo; var pBmpData:Pointer);
var
  bmf: TBitmapFileHeader;
  imageSize: LongWord;
  Stream: TFileStream;
begin
   try
    Stream:= TFileStream.Create(bmpFile, fmOpenRead or fmShareDenyWrite);
    Stream.Read(bmf, sizeof(Bmf));
    Stream.Read(bmpinfo, sizeof(bmpinfo));
    imageSize:= bmf.bfSize-bmf.bfOffBits;
    stream.Seek(bmf.bfOffBits,0);

    FreeMem(pBmpData);
    GetMem(pBmpData, imageSize);

    Stream.Read(pBmpData^, ImageSize);
  finally
    FreeAndNil(Stream);
  end;
end;

关于var前缀

一开始以为,用指针就可以在函数内给外部的指针分配内存并传出结果了。但其实不对,外面的指针还一直是nil。必须带上var前缀才行(指针的指针)。

关于VFW

DrawDibDraw是VFW(Video for Windows)中的API,关于DrawDibDraw的用法可以参考园子里的DrawDibDraw函数的使用方法。封装文件VFW.pas来自一篇《delphi摄像头编程vfw》,出处已不可考,被署名Tom Nuydens的修改过。

完整源码

结论和建议

  • 单纯缩小画面的(源图一定比目标图大):StretchBlt、StretchDIBits随便用,先用SetStretchBltMode选COLORONCOLOR模式,性能足够了。
  • 必须放大画面的(源图比目标图小):要用StretchBlt、StretchDIBits,用SetStretchBltMode必须选HALFTONE模式。性能无法接受可选DrawDibDraw。
  • 图省事用DrawDibDraw,可能要多耗些资源吧(没精确测算过)。
  • 图形性能要求更高的,啃DirectX、OpenGL、SDL去吧。代码不难,难的是要理解那么多图形学概念。

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Matlabmex编程发布时间:2022-07-18
下一篇:
matlab与modelsim联调cic抽取滤波器发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap