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

by admin on 2019年1月11日

上午兴起Q群里便相当红极一时,又有一部分同事内部整合喜结连理了。就此事件我们展开了积极向上热烈的议论,不是谈物质实际上的要送多少钱,而是精神层面的被冷淡感汗。首先是平时一个老实到宅的同事很烦躁,说正好新婚夫妇去她们屋送糖发柬的时候被坚决无视了,人家连理都不理他。好呢,补充表达下,这一个MM仍旧个单位官员啊。此时,本着平常、平时,大事小事,比惨比难,大战小战,身经万战从不输人不输阵,自家贺号自封战神(楠木正成哭晕在厕所,山中鹿之介说要坚强喔,七苦八难哈,嚯嗬嗐嘿)的吾横空出现立即将风头扭转,正言曰:你这些相对不算惨,偶也素,偶比你+1的是偶看他们一进屋就说了一堆吉祥话,结局和您是一模一样同等的哟。事实注脚,俺真具有大杀器的底子属性,此言一出,众人皆惊,满群即静,事实注明俺又一遍完胜。本着乘胜追击的动感,俺进一步加以讲解表明:

自我的天哪,上一篇博文是2年前的事体了。看来又虚度了2年生活,继续读书。。。
本文算是副产品,正品是运用FFmpeg从随机录像中生成GIF片段的小程序,等写完了再发。不为另外,只是为了给外孙子做动图,且看不惯这种工具也要收费!

每户怎么对你视而不见,置之度外,说来说去,大多是上下一心的问题。除去你那人实在无耻卑鄙,人嫌狗憎的可能。如果您是这等人畜无害型的,这就分分钟等待接受这种待遇吗。原因无他,以下通通归结:

声明

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

一、温和无害的性能。用文言文说就是你属于这种得罪的起的人种,尽管不留意对您的态势,也没啥问题。因为反正你也不会做出什么影响,更毫不顾虑你会打击报复回去。

怎么要测试 StretchBlt, StretchDIBits, DrawDibDraw 的特性

因为录像回看需要很高的来得性能,解码占了累累总括量,留给彰显的刻钟不多,能优化则优化吧。

事实上现在的CPU跑个录像播放已经绰绰有余了,GPU压根就不必用。即便是用Delphi自带的TImage控件,用Bitmap往里填也足以满意通常播放需求了。要是时光倒流到10年前,这可真是得去切磋DirectX、OpenGL了。可惜关于这哥俩,大部分都是C、C++的资源,我啃了半天SDL,觉得有些杀鸡用牛刀。所以就想着先实现需求吧,真的非凡了再优化吧。在自我的英特尔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的产品也有大小年,逢单的本子就是政通人和一些。即便轮子有时候得从头初叶造,不过“知其所以然”是乐在其中的事,相信我!

三、除去下面二种批判现实主义解读。再来点列举点旁人的题材,比如非凡已经被说滥了的磋商问题。在此要严重推荐香港海淀数百年古刹万寿寺相邻某神奇大学中一大BT专业—–思想政治教育标准!!!(DUANGDUANGDUANG,此处有雷声)这些标准是所谓培训团委书记的,可称的起是能人倍出,人才济济。据所有和此标准同学打过交道的铜子讲,那些标准的同桌都是应酬达人,社团神马活动、聚餐,不管全场有些许人,人家都能把每一个人给兼职顾到,让每一个人都有被重视、被照顾、被尊重的赶脚。人家的策略就是广阔撒网,重点培训。本着不了解这块云彩会下雨的动感,抱着万一你那天发达了的心,充裕兼顾到每一个人。如上边例子中这等对旁人视而不见的商事负分差评表现,在这等俗称“人精”的人流身上是不用会现出哒。

测试结果

一旦只关心结果,或者对Delphi不屑,这您就无须往下看了,我先交付结果吗。为您节约点时间。严厉意义上说,BitBlt不属于任何哥仨的营垒,因为不用缩放,所以速度自然快了。放在这里相比,就当是个Baseline吧。

  1. DrawDibDraw.aspx)最快(1ms级别)。
    不到StretchBlt和StretchDIBits的一半,且不需要用SetStretchBltMode.aspx)设置哪些缩放格局,画质看不出分别。
  2. StretchBlt.aspx)和StretchDIBits.aspx)难分伯仲。
    用了色彩拟合形式(HALFTONE)的话会大大扩大总括量,耗时4倍,比DrawDibDraw慢1个数据级。指出收缩图像时方可用COLORONCOLOR格局,肉眼看不出区别,但可以比HALFTONE形式提速4倍!
API COLORONCOLOR HALFTONE
BitBlt 400 400
DrawDibDraw 1125 1125
StretchBlt 3000 11406
StretchDIBits 3203 11576
  • 测试用机:CPU: 英特尔 i3 3220,内存: 8G DDRIII 1333,显卡: Intel 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.aspx)。
  • 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.aspx)。

据此你看,有相比就有异样啊。

源码

历数完具体问题再来写解决方案。无她,积极的,消极的,只有两条道路,没有中间路线。

界面

就放了多少个按钮而已,名称末尾为C的表示用了COLORONCOLOR形式,为H的象征用了HALFTONE情势。还有一个提姆(Tim)age控件。

方案一:你可以由此事终日自警自励。积极兑现以前朋友圈里疯转的当下你对自家视而不见将来本人自然要你为难这种帖子的能动精神。比如最鸡汤最励志最出名最刷屏刷朋友圈这句:前几日您对自我爱搭不理,明日自家让你高攀不起。这话里话外透着那么光棍,那么偏激,那么没钱加任性啊喂。真不像马云说的,倒像刘能说的。好吧,假若遵照那多少个携带方针去做,那么只要我和当事MM振奋精神,为令人高攀不起而读书AND努力,创业成功如故其中高升神马的,分分钟秒杀那个当时看不起你的人。用真情说话,用纸币鄙视TA。

常量

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
.aspx))中的API,关于DrawDibDraw的用法可以参照园子里的DrawDibDraw函数的行使情势。封装文件VFW.pas来自一篇《delphi视频头编程vfw》,出处已不可考,被署名汤姆(Tom)Nuydens的修改过。

完整源码

结论和提议

  • 只有收缩画面的(源图一定比目的图大):StretchBlt、StretchDIBits随便用,先用SetStretchBltMode选COLORONCOLOR情势,性能充足了。
  • 无法不加大画面的(源图比目标图小):要用StretchBlt、StretchDIBits,用SetStretchBltMode必须选HALFTONE形式。性能不能接受可选DrawDibDraw。
  • 图方便用DrawDibDraw,可能要多耗些资源吧(没规范总计过)。
  • 图形性能要求更高的,啃DirectX、OpenGL、SDL去呢。代码不难,难的是要明了那么多图形学概念。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图