这里只介绍初级技巧,并且多数只是一些提示,不包含代码和一些概念的详细说明。 技巧一:双缓冲消除闪烁。 很多初学者认为闪烁产生的原因是刷新速度太慢,这是个完全错误的认识。 闪烁产生的原因是相邻的两帧或多帧之间,图像内容的差异过大。在实际编程中,
这里只介绍初级技巧,并且多数只是一些提示,不包含代码和一些概念的详细说明。
技巧一:双缓冲消除闪烁。
很多初学者认为闪烁产生的原因是刷新速度太慢,这是个完全错误的认识。
闪烁产生的原因是相邻的两帧或多帧之间,图像内容的差异过大。在实际编程中,这个差异的来源主要有三个:
1,windows自身对程序窗口背景的擦除,导致两帧之间插入空白帧。这个可以通过处理OnEraseBkgnd或者类似的地方来解决。
2,程序自身清除背景。这个就是双缓冲要取代的。
3,绘制过程表现。由于没有使用双缓冲,绘图的整个过程会重现在屏幕上,这种过程的重现会引起闪烁。
双缓冲技术的实质是:在后台缓冲绘制下一帧要显示的图形,绘制完成后切换到前台显示。由于前台显示的是上一次绘制的结果,对于连续运动的图像来说,两帧之间的差异很小,人感觉起来就是平滑的变化了。
这一技术的实现,请参考游戏开发和图像处理的书籍和资料。
技巧二:数据与显示分离。
这个技巧常见于图像处理程序,例如绘图软件等。
绝大多数初学者的第一个图像处理程序,把绘制好的图像保存为文件的过程,都是直接从DC中获取数据,然后转为BMP或者其他格式的。
这种方式对于一个简单的demo或者不做商业用途的小程序来说,是完全可以的。而一旦图像处理需要涉及一些复杂的算法,例如alpha融合,模糊,锐化等,这种方式就无法满足要求了。
正确的做法是:定义自己的图像数据格式(一般认为24bitBMP的格式就是很优秀的格式了,也能满足多数情况的需要),然后制定自定义格式到DC等设备的映射规则。所有的数据运算都在自己的数据结构内部完成,而结果经过映射后,显示在给定的设备上。
之所以不用DC,有四个主要原因:
1,DC是易变的。同一程序的不同部分,都拥有对DC的修改权限,甚至其他程序也会修改你程序的DC资源。
2,DC的精度是受限的。对于一个特定的图像处理算法,可能会引起数据的丢失或上溢,多次处理的结果会导致图像的色彩和形状完全失真。为了解决这个问题,包括photoshop在内的许多图像处理软件都提供了诸如48bit等高精度图形格式。
3,DC的尺寸是受限的。你可能想处理一个长宽都很大(例如,长宽都超过10k象素)的图像,但是DC的尺寸有它自己的限制,有些情况无法满足要求。
4,DC是设备相关的,在不同的桌面分辨率设置下的表现是不一致的。这个不用多说,256色/16位色/24位色/32位色下,截取同一DC内容得到的结果可能是不同的。你总不能要求使用你软件的用户必须使用你用的桌面设置吧?
这一技巧更重要的用途是在矢量图的绘制,矢量图一般使用浮点类型的数据保存图形细节信息,而以象素坐标为单位的屏幕DC对此无能为力。
技巧三:恰当的UNDO方式。
多数图像算法是不可逆的,例如模糊,为了能够undo每一步的操作,相当多的时候只能把处理前的图片保存一个备份,undo的时候直接恢复。
事实上,由于用户的操作可能非常复杂,那么这种备份的数量极有可能超过磁盘剩余空间。其实有个优化的方式:
原理:用户的操作虽然不能被有效undo,但是却可以被重现。
使用:保存原始的图片,记录每一步用户操作的细节,当需要undo到某一步的时候,从原始图片开始,依次重现用户的操作细节,直到需要的那个步骤。
这一技巧还可以通过在一些重现时间过长的复杂操作前后增加备份次数以改善性能。总的来说这是个时间换磁盘空间的技巧,多数时候也能加快程序的响应速度(毕竟内存计算比读取磁盘快不是一点半点)。
技巧四:必要的时候,汇编。
图像处理多数是耗时运算,即使1024×1024的bmp,总数据量也超过3M,对于一个需要逐象素处理的算法来说,这种数据量会占据大量的CPU时间。
为了改善这种状况,除了改进算法本身外,唯一的方法恐怕就是利用汇编了,可以通过MMX,SSE等特殊指令加快处理速度,多数情况,经过汇编优化的算法会比原始算法快2~3倍。
但是,你也必须保留原始的算法版本以支持不具备那些特有指令的CPU(例如Intel的CPU就不支持3DNow指令),并验证汇编的正确性。
技巧五:多线程和空闲时间利用。
为了在处理图像的同时,及时响应用户的操作,多线程一般而言在所难免,除了多线程本身的复杂性,这里需要提醒:在只有单个CPU的机器上,多线程只会降低你的运行速度而不是加快,如果你的处理不是那么耗时,或者用户界面响应不是那么重要,请慎重考虑为程序付出多线程的代价是否值得。
无论是游戏,还是图像处理程序,总是或多或少有些空闲时间,例如用户停止操作等等,程序可以选择使用这段时间来做一些后台处理的工作,例如把缓冲中的数据写入磁盘等。
技巧六:有计划的内存管理。
图像处理程序耗尽系统可用内存,这并不是什么新鲜事,再优秀的内存管理也不能处理内存需求超过供给的情况。这里有个致命问题,就是当用户的某个操作需要分配大量内存,而系统此时又无法满足的时候,你的程序可能连保存当前编辑状态的内存都拿不出来了。
为了避免这种情况,内存使用上要有一个有效的预算和反馈机制,事先预测可能发生的状况做好恢复准备,而不是等到系统内存告急的时候手忙脚乱。
与此同时,一些常用文件和数据的缓冲是提高效率的途径,也是内存缺乏时可以暂时释放的资源。
技巧七:看懂以上的所有技巧,如果你不能,那么你还没有为你所涉足的这个领域做好最基本的准备。