以前没弄过DELPHI,最近学了1个多星期时间,无聊时候把以前把C#写的部分图像处理代码转换成DELPHI,竟然发现D处理图片的速度比C#快了20倍··················D处理图片0.3s,C#处理同一图片6s多 ,差距真大····················   
我写的算法调用GDI+函数,无汇编便于理解,觉的有帮助就顶一个,顶的多就发布下一篇图像处理,转帖的话请写明转帖和原作者: 睿割氏窝老攻 ,QQ 235483710 EMAIL: [email protected] 代码太多,怕看不清楚,下面是我的BLOG地址 :http://blog.csdn.net/huruihappy/archive/2008/09/06/2892902.aspx

解决方案 »

  1.   

    delphi下利用缩略图功能显示图片,不管何种类开型图片,显示速度超快
      

  2.   

    相当的有问题,Canvas.Pixels是对GDI SetPixels/GetPixels的调用,循环内部用它操作DIB颜色和直接操作DIB内存数据比性能存在巨大差异。抛开SIMD优化/浮点运算优化不谈,在高级语言层次很多地方都存在优化空间。当然上面的是重点,这个尺寸的图进行这种复杂度的运算时间应该是毫秒级的,甚至更少,300毫秒太多了。
      

  3.   

    同意楼上观点,Canvas.Pixels处理像素N慢,至少得在图像扫描线上操作。
      

  4.   

    你再试试ScanLine,效率会比你直接Canvas.Pixels快上N倍。
      

  5.   

    换成啥操作比较快 如何直接操作DIB内存数据?
      

  6.   

    没弄过多久D,很多东西不知道,我只是想表现一个算法,如果能取得更好的性能就更好了  。换成啥操作比较快 如何直接操作DIB内存数据?
      

  7.   

    DIB和Delphi无关,这里的DIB是Windows下设备无关位图,设备无关位图其实本质上是内存位图,Canvas是用一个绑定的DC对其进行操作,而用DC操作位图因为GDI对于各种色深位图操作的统一性,性能实际上是非常差的。用Bitmap.ScanLine可以获得每一行位图DIB数据的首地址,Bitmap.ScanLine[Bitmap.Height-1]是整个DIB的数据的首地址。当然和GetPixels得到的不同,这里不一定是RGB颜色,这个是由DIB位图的色深决定的,如果是24位色,那就是3字节表示一个颜色。32位色那就是4字节表示一个颜色。16位色自然就是2字节,不过存在555和565两种不同的内存格式。也就是绿色可以使用5bit表示也可能是6bit。至于8位以下的DIB,那就是相对应的位数的数据对应一个调色板中的序号,并不表示具体颜色。用SIMD对于这种运算也是可以大幅度提升性能的,比如你上面大量R/G/B分别进行同样计算的代码,用SIMD可以轻松优化成一次运算,直接就是几乎3倍的性能提升。
      

  8.   

    阿发伯在这方面很有造诣,你可以请教一下。顺便请教一下阿发伯,直接用流读bmp文件到数组,和用ScanLine读到数组哪个更快
      

  9.   

    我一般都是直接操作ScanLine,如果有些操作需要备份,直接GetMem后Move。用流读到数组操作应该也不慢,但是比较麻烦,一是要自己做解析,二是自己格式转换(总不能一样的操作,还分什么24位、32位、555、565的代码),那多麻烦。这是我的一孔之见。:)
      

  10.   

    毫无疑问,直接读到数组快,Bitmap格式不需要做复杂解释,文件头和位图BITMAPFILEHEADER/BITMAPINFOHEADER都是Win SDK直接定义的。对应VCL里的TBitmapFileHeader/TBitmapInfoHeader,根据Header确定后面的调色板和位图数据格式。而TBitmap为了使用GDI直接进行操作,需要创建DIB,作了很多多余操作。可阅读TBitmap.ReadDIB中的代码。要习惯阅读代码,程序上的问题嘛,所有的结论都可以精确得出。根本不需要靠猜测。这是很多Delphi程序员的坏习惯,喜欢靠想象力得出结论。虽然Delphi是个很好的工具,但看看Windows程序设计这类基础书籍还是有必要的,缺乏基础,一样驾驭不了Delphi。
      

  11.   

    楼上的看法从理论上非常正确,但实际并不切实可行。
        1、“虽然Bitmap格式不需要做复杂解释”,但是各种图片的像素格式是不一样的,对同样的操作,难道每个格式都去写一段代码?不如此,就得自己解析和转换图像格式,自己写的解析、转换代码又比TBitmap效率高多少呢?
        2、操作TBitmap的ScanLine的意义还在于,不仅是可以处理Bitmap格式图像,在第三方代码支持下,还可以以同样的代码去处理其它格式的图像,如jpeg、png以及gif等,否则,和上面的结果一样:要么每个格式都去写一段代码,要么自己去解析和转换。
        所以,操作TBitmap其实是看中了它的像素格式转换能力。再说了,毕竟基础扎实、语言驾驭能力很强的高手也只是极少数,而往往这类高手的实际运用能力并不是很强,毕竟人的精力是有限的。
      

  12.   


    “但是各种图片的像素格式是不一样的,对同样的操作,难道每个格式都去写一段代码”,ScanLine得到的内存结构和文件中的的数据结构完全一致。你确信去阅读了ReadDIB的代码吗?这就是Copy操作而已。如果你基于这个理由,那么用Bitmap同样解决不了,用 ScanLine得到的位图数据同样要根据色深差异做差异化处理,这个我上面说明过。TBitmap只是VCL中用于UI绘图的基础类。VCL是专业的图像库吗?性能什么都可以不管,请问DIB的尺寸上限问题如何解决?你尝试用TBitmap创建一个稍微大点的位图,如何?能成功吗?绑定DIB的位图的必然有其使用的局限性。做图像处理自己写位图类也是理由足够充分的。至于你说的那些格式,基于libjpeg/libpng/libgif做解析都很简单,没有任何难度。回到话题的开始,“直接用流读bmp文件到数组,和用ScanLine读到数组哪个更快”,毫无疑问,直接读快,这是个不需要推理证明的真理。
      

  13.   

        TBitmap对位图有Copy操作,难道自己做解析就不是Copy操作?我不否认自己写的专业解析代码可能比TBitmap的通用代码快,高手会说,不用怀疑,绝对快,我说是不见得,并不是人人都有那么高的编程技巧的!同样的算法,有不同的人来实现代码,其效率有着天壤之别!
        将不同格式的位图,用TBitmap转换为相同的格式,对大多数图像来说,色深差异做差异化处理已经做得很好了。
        “基于libjpeg/libpng/libgif做解析都很简单,没有任何难度”,这也只是高手们说的话!
         回答问题,大家都有说话的权利,不同的观点,可以争论,说错了什么,当然可以指出,但是,如果以高手自居,动不动就教训别人,只有自己天下第一,就不大好了。我前面只是说了,“我一般都是直接操作ScanLine”,“用流读到数组操作应该也不慢,但是比较麻烦”的话,就被高手指责为“喜欢靠想象力得出结论”,“缺乏基础,一样驾驭不了Delphi”,请问,我在哪里做了什么“结论”?!
        我并不想就此事同谁来做个争辩,因为我不是“高手”,我们不是一个档次的水平,“诸如基于libjpeg/libpng/libgif做解析”之类的问题,对我来说是相当困难的,所以,争辩起来没多大意义。只是垦请高手们注意说话的语气!“缺乏”什么,能不能“驾驭”什么,是自己的事,用不着别人教训!
      

  14.   

    一般位图不需要解析,这是一直在表达的基本观点,从文件中把一段数据原样复制到内存中,也就是ScanLine指向的内存,呵呵,阅读VCL代码能解决的问题,没有争论价值。
      

  15.   


    虽然我说了不想就此事辩论,但还是忍不住问一下,8、16、24以及32位位图的内存布局是一样的?转换为相同格式叫不叫Copy?一般位图不须解析,特殊的呢?非位图格式呢?再简单也还是解析吧!还是那句话,观点不同,可以争论,但是用不着教训别人,炫耀自己!大家都知道VCL代码是开源的,并非只有高手会读,低手们也会读的,只是理解层次不同而已。
      

  16.   

    对Delphi程序员的评价是泛指,对个人没有针对性。结合最近的经历,借题发表一番感叹,不要这么敏感。你真要扣字眼,好吧,结合语境,这句“用流读到数组操作应该也不慢”暴露了你潜意识的想法,你认为后者也不慢,现实是后者快的多。ScanLine得到的数据结构和文件中的数据完全一致,不存在任何多余的运算解码。很明显你在基于想象思考这个问题。话题没必要无限延伸,你不喜欢别人的说话风格也不妨碍讨论一个纯粹的技术问题。我也有对于国内Delphi开发者素质现状发表感慨的权利,言论自由。好啦,很多年没在CSDN码字了,该干啥干啥去吧,祝大家中秋快乐
      

  17.   


    TBitmap有解决差异性?ScanLine得到的内存和文件中的数据完全一致。好吧,你要说你基于GDI来处理DIB,那确实不存在差异,不过问题的出发点呢?
      

  18.   

       说了半天,我和你说的是不同的角度,我是从代码通用的角度考虑,你是从专门的代码角度考虑,正是因为从流得到的内存和文件中的数据完全一致,使得不同像素格式的位图无法使用通用代码,但是通过设置TBitmap.Pixelformat,将大部分图像格式转换为一致的,我是基于此点才说的那番话。所以,我们的争论真的没有意义。发感慨也不是什么坏事,但在评论别人的发言的时候发感慨,就不是什么“泛指,对个人没有针对性”了。算了,既然你解释了,也没必要纠缠于此,让他人见笑了。
      

  19.   


    修改了Pixelformat还是同一位图吗?这似乎和楼上说的取数据到数组目的就不一样了。另外说个多余的话题,TBitmap中真彩图转索引图都基于生成的固定调色板,作为图像处理来说几乎没有实用价值,没有哪个图像处理软件会这么做。
      

  20.   

    顺便说一句,评论别人的发言时,不要断章取义,我在前面5楼发言时说“同意楼上观点,Canvas.Pixels处理像素N慢,至少得在图像扫描线上操作”,这个“至少”你怎么就没看见,说明我并非认为TBitmap的ScanLine操作就是最佳的,到后来,我只是从通用处理角度说了“我一般都是直接操作ScanLine”,“用流读到数组操作应该也不慢,但是比较麻烦,一是要自己做解析,二是自己格式转换”,这话那里又错了?
      

  21.   

    我是楼主 ,大家讨论热烈哇 我感觉TBitmap 的 ScanLine 速度是比读canvas的像素快多了 ,程序优化空间很大,但是还是有点问题··D中的TBitmap貌似只有R G b 三个颜色分量,取不到alpha通道的值。如果图片在内存中的话,怎么获得alpha通道。?顺便再请教下,图像的算法问题。自己的独创算法 基本实现了Photoshop里面的置换滤镜算法,可以用于处理图像纹理贴图,比如给衣服褶皱加纹理扭曲等效果,但是当“置换因子”过大时,整个纹理图虽然能依据褶皱进行扭曲,但是图像显示出的纹理是散状的点,无法像PS那样连贯的扭曲,大家帮忙优化下。··
      

  22.   


    顺便再请教下,图像的算法问题。自己的独创算法 基本实现了Photoshop里面的置换滤镜算法,可以用于处理图像纹理贴图,比如给衣服褶皱加纹理扭曲等效果,但是当“置换因子”过大时,整个纹理图虽然能依据褶皱进行扭曲,但是图像显示出的纹理是散状的点,无法像PS那样连贯的扭曲,大家帮忙优化下。··
      

  23.   

    如果楼主想深入研究的话我建议你看看opencv
    http://www.opencv.org.cn/index.php
      

  24.   

    初学者,还不太了解DELPHI,现在学这个的不太多了。我就是觉得他比VB好,就学了。希望大家多多帮助呀。多发布好的有关DELPHI的东西。
      

  25.   

    呵呵,GDI+的可不能移植哟,偶现在的图像库全用自己的函数,直接用算法实现,既加深了功力,又保证了库的可移植性.
      

  26.   

    不错-------------------------------------------------
    北京国展大型人才招聘会(9.27)
    http://www.315job.com/YaoQingHan/20080927.html
      

  27.   


    你可以参见图像操作大牛人Maozefa的博客(http://blog.csdn.net/maozefa)内容,使用GDI+能很好的解决你所说的问题
      

  28.   

    delphi 封装的windows对bmp的处理比较好,c#根本无法比拟,楼主的代码优化后至少可以提升10备.