(翻译了个大概,略过了一些无关紧要的句子,原文)
@H_502_2@使用API调用是一种比使用VB内置图像函数更快速的方法.例如,使用GetPixel和SetPixel要比VB的PSet和Point快3倍左右.但是如果使用直接内存访问(DMA)将得到更高的效率.
那么,用DirectX怎么样?当然DirectX是相当快的,但它的速度来自于显卡,如果你不幸地没有那么一块好显卡,或者你只是想处理简单的图像,(比如画点和线),那么DMA已经够快的了,并且能把你从麻烦的DirectX版本中解放出来.
基本思想就是直接访问图像组成,你可能会想到使用GetDibits和SetDibits去费力地把图像从位图提取到数组,再把数组塞进图像.而实际上,你可以将一个数组直接指向位图的内存.
要实现这样的数组当然需要用到一些API,见下:
@H_404_154@
使用@H_404_154@VarPtr函数可以得到一个变量的内存地址@H_404_154@,在此@H_404_154@,我也引用了一个可以指向数组的函数@H_404_154@VarPtrArray.
使用@H_404_154@CopyMemory则可以将数据从一块内存复制到另一块内存@H_404_154@.
使用@H_404_154@GetObj则可以获得一个对象的内存@H_404_154@,在例子中我们用它来得到@H_404_154@StdPicture对象的信息@H_404_154@.因此@H_404_154@,我们需要定义一个位图结构@H_404_154@.
最后我们定义了一个安全数组结构@H_404_154@,我们用它来替换实际工作的数组@H_404_154@.
我们先定义@H_404_154@StdPicture对象@H_404_154@,并且假设它已经加载了一个图像@H_404_154@.再定义一个动态数组而不初始化@H_404_154@.我们使用@H_404_154@API来将这个数组@H_404_154@"分配@H_404_154@"到图像的内存@H_404_154@,这样@H_404_154@,我们在数组上的任何改动就能显示在图像上了@H_404_154@.代码@H_404_154@:
看看发生了什么@H_404_154@?首先我们用@H_404_154@GetObj来获取了位图的信息@H_404_154@,然后使用这个信息来构造了@H_404_154@SafeArray2d结构@H_404_154@,特别注意这句@H_404_154@:
@H_404_154@.pvdata=bmp.bmbits
它将位图位图所在的内存指向了结构@H_404_154@.
简单把@H_404_154@,不尽然@H_404_154@,这里有些需要注意的地方@H_404_154@:
1:图像对象必须预先载入一个图片才能建立一个位图结构@H_404_154@,否则它是没有意义的@H_404_154@.
2:安全数组对象必须和数组的生存周期一致@H_404_154@,如果你在数组被回收之前就释放了安全数组对象@H_404_154@,那么数组将无处可指@H_404_154@(导致@H_404_154@VB崩溃@H_404_154@)
3:而在释放数组之前@H_404_154@,又必须将数组还原@H_404_154@,否则程序会因为内存泄漏而崩溃@H_404_154@.
4:一个@H_404_154@256色的位图中@H_404_154@,每个像素占用@H_404_154@1个字节@H_404_154@,但是这个字节只是对应了一个调色板索引而并非一个实际的颜色值@H_404_154@.所以你必须在建立数组之前先把索引转换成时机颜色@H_404_154@.(这里不讨论16位色)@H_404_154@幸运的是@H_404_154@24位色图像中存放的是真正的颜色值@H_404_154@,但你依然需要颜色对应到@H_404_154@RGB字节中
5:通常来说@H_404_154@,位图对应的数组是从左下角开始的@H_404_154@,因此数组@H_404_154@(0,0)对应图像的最左下角的点
在你弄完之后@H_404_154@,你必须复位数组@H_404_154@,见下@H_404_154@:
@H_404_154@
那么现在这个数组是什么呢@H_404_154@?它变成了一个@H_404_154@2维数组@H_404_154@(X,Y),X代表横坐标@H_404_154@,Y代表纵坐标@H_404_154@,每一个数组元素是一个字节@H_404_154@.对于@H_404_154@256色位图来说@H_404_154@,这个字节是一个颜色索引@H_404_154@,但对于@H_404_154@24位色图像来说@H_404_154@,它是一个颜色值@H_404_154@.每个字节对应了颜色值中的@H_404_154@RGB中的一个@H_404_154@,所以每个像素是有@H_404_154@3个个数组元素组成的@H_404_154@.例如@H_404_154@:一个@H_404_154@100X100的图像对应一个@H_404_154@300X100大小的数组@H_404_154@.
数组的大小相对于像素是不同的@H_404_154@,因此你当你读写某个像素的时候必须自己计算@H_404_154@:
这里给出一个速度对比@H_404_154@:
加载一个@H_404_154@100X100的@H_404_154@24位图像@H_404_154@,我把每个像素都设置为红色@H_404_154@,使用@H_404_154@DMA,SetPixel和@H_404_154@PSet时间分别为@H_404_154@:5ms,60ms,550ms.编译之后@H_404_154@,分别为@H_404_154@:4ms,50ms,70ms.DMA比@H_404_154@SetPixel快@H_404_154@12倍
附上封装好的模块@H_404_154@,只要把它编译为@H_404_154@ActiveXDLL然后就可以在你自己的工程中引用它@H_404_154@.
下面是我的测试工程@H_404_154@,演示了使用方法@H_404_154@:
@H_404_154@