用VB写高效的图像处理程序doc资料.docx
- 文档编号:29783746
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:21
- 大小:27.64KB
用VB写高效的图像处理程序doc资料.docx
《用VB写高效的图像处理程序doc资料.docx》由会员分享,可在线阅读,更多相关《用VB写高效的图像处理程序doc资料.docx(21页珍藏版)》请在冰豆网上搜索。
用VB写高效的图像处理程序doc资料
用VB写高效的图像处理程序
用VB写高效的图像处理程序
自盘古开天地以来(好像夸张了点),一直有人抱怨VB程序速度慢。
特别是图像处理,被认为是VB的禁区。
说起来也是,市面上的关于VB的图像处理的数据都是先讲计算公式,再直接用PSet(或API函数SetPixel)逐点画(至少我见过的书都是这样)。
效果是办到了,但速度慢得离谱:
对一幅640*480的图像进行半透明合并就需要10秒钟;而在PhotoShop中,只要一设置图层的透明度,半透明效果立即呈现。
难怪有人说VB的闲话。
但这并不表示VB不能写高速的图像处理程序,速度慢是因为没有使用正确的方法。
从VB5开始,能以本机代码编译成exe文件,所以不存在代码执行速度的问题。
那么,是什么拖慢了速度呢?
就是PSet和SetPixel!
PSet把浮点形式的坐标转为像素单位,再交给SetPixel处理。
而SetPixel呢,坐标系转化、剪裁区域判断、将颜色匹配为设备支持的最接近的,最后还要根据不同的颜色格式寻址、为将颜色写入其所在位进行位运算。
经过这么多层处理,速度不慢才怪。
那么,怎样才能提高处理速度呢?
使用DIB,直接对位图所在内存进行操作,速度可以大大提高。
现在看看,这只是一个简单的色彩演示程序。
CPU:
赛扬333;内存:
PC100(很老的概念了)的SDRAM,128MB;单位:
毫秒
Windows98
WindowsXP
说 明
VB_PSet
1,199.4553
786.1885
在VB使用PSet画的
VB_SetPixel
872.3621
451.3712
在VB使用SetPixelV画的
VB_DIB
8.2218
8.2226
在VB使用DIB画的
VB_DIB_Ptr
9.6783
9.4420
在VB使用DIBSection+模拟指针画的
VC(Debug)
6.6896
6.6503
VC写的(Debug版)
VC(Release)
3.2736
3.6247
VC写的(Release版)
从这个表中可看出:
1.VC比VB_DIB、VB_DIB_Ptr快两倍,这是因为SafeArray结构的数组比真正的指针慢,但也不是某些人所说的70~100倍;
2.VB_DIB_Ptr比VB_DIB慢一点,这是因为模拟指针本来就是靠SafeArray结构的数组,而且模拟指针需要对两个数组进行操作,所以速度慢一点;
3.真正差了70~100倍是VB_PSet和VB_SetPixel,特别是VB_PSet在Windows98下与VB_DIB差了145倍。
以上可证,速度慢的原因是SetPixel非常低效,而并不是VB的问题。
虽然VC的的确比较快,但是我写这篇文章不是为了讨论速度极限(否则这篇文章会改名为《如何用汇编写高速的图像处理程序》),而是为了告诉大家如何在VB中写能够实时处理的图像处理程序。
在Windows3.0以前,Windows系统用的是DDB(设备有关位图)。
DDB没有调色板,显示的颜色依赖硬件,处理色彩很不方便。
所以Microsoft在Windows3.0中重新定义了BMP文件格式(BMP3.0),使其支持设备无关位图——也就是DIB。
时至今日,BMP的版本号已升至5.0(WindowsNT4.0、Windows95定义了BMP4.0,Windows98、Windows2000定义了BMP5.0),但基本结构没有变——仍是BMP文件头和DIB组成:
BMP文件
BITMAPFILEHEADER
BMP文件头
DIB
BITMAPINFOHEADER
位图信息头
RGBQUAD[]
调色板
位图数据
(#代表可以不填(=0)的项目)
BMP文件头——BITMAPFILEHEADER
原型定义:
typedefstructtagBITMAPFILEHEADER{//bmfhWORDbfType;DWORDbfSize;WORDbfReserved1;WORDbfReserved2;DWORDbfOffBits;}BITMAPFILEHEADER;
VB声明:
TypeBITMAPFILEHEADERbfType(0to1)AsBytebfSizeAsLongbfReserved1AsIntegerbfReserved2AsIntegerbfOffBitsAsLongEndType
说明:
bfType
指示文件的类型,必须是“BM”
bfSize#
指示文件的大小,包括BITMAPFILEHEADER
bfReserved1
保留,=0
bfReserved2
保留,=0
bfOffBits#
从文件头到位图数据的偏移字节数
文件信息头——BITMAPINFOHEADER
原型定义:
typedefstructtagBITMAPINFOHEADER{//bmihDWORDbiSize;LONGbiWidth;LONGbiHeight;WORDbiPlanes;WORDbiBitCount;DWORDbiCompression;DWORDbiSizeImage;LONGbiXPelsPerMeter;LONGbiYPelsPerMeter;DWORDbiClrUsed;DWORDbiClrImportant;}BITMAPINFOHEADER;
VB声明:
TypeBITMAPINFOHEADERbiSizeAsLongbiWidthAsLongbiHeightAsLongbiPlanesAsIntegerbiBitCountAsIntegerbiCompressionAsLongbiSizeImageAsLongbiXPelsPerMeterAsLongbiYPelsPerMeterAsLongbiClrUsedAsLongbiClrImportantAsLongEndType
说明:
biSize
BITMAPINFOHEADER结构的大小。
BMP有多个版本,就靠biSize来区别:
BMP3.0:
BITMAPINFOHEADER(=40)
BMP4.0:
BITMAPV4HEADER(=108)
BMP5.0:
BITMAPV5HEADER(=124)
biWidth
位图的高度,单位是像素
biHeight
位图的宽度,单位是像素
biPlanes
设备的位平面数。
现在都是1
biBitCount
图像的颜色位数
0:
当biCompression=BI_JPEG时必须为0(BMP5.0)
1:
单色位图
4:
16色位图
8:
256色位图
16:
增强色位图,默认为555格式
24:
真彩色位图
32:
32位位图,默认情况下Windows不会处理最高8位,可以将它作为自己的Alpha通道
biCompression
压缩方式
BI_RGB:
无压缩
BI_RLE8:
行程编码压缩,biBitCount必须等于8
BI_RLE4:
行程编码压缩,biBitCount必须等于4
BI_BITFIELDS:
指定RGB掩码,biBitCount必须等于16、32
BI_JPEG:
JPEG压缩(BMP5.0)
BI_PNG:
PNG压缩(BMP5.0)
biSizeImage#
实际的位图数据所占字节(biCompression=BI_RGB时可以省略)
biXPelsPerMeter#
目标设备的水平分辨率,单位是每米的像素个数
biYPelsPerMeter#
目标设备的垂直分辨率,单位是每米的像素个数
biClrUsed#
使用的颜色数(当biBitCount等于1、4、8时才有效)。
如果该项为0,表示颜色数为2^biBitCount
biClrImportant#
重要的颜色数。
如果该项为0,表示所有颜色都是重要的
调色板
只有biBitCount等于1、4、8时才有调色板。
调色板实际上是一个数组,元素的个数由biBitCount和biClrUsed决定。
原型定义:
typedefstructtagRGBQUAD{//rgbqBYTErgbBlue;BYTErgbGreen;BYTErgbRed;BYTErgbReserved;}RGBQUAD;
VB声明:
PrivateTypeRGBQUADrgbBlueAsBytergbGreenAsBytergbRedAsBytergbReservedAsByteEndType
说明:
rgbBlue
蓝色分量
rgbGreen
绿色分量
rgbRed
红色分量
rgbReserved#
保留,=0
位图数据
◆扫描行:
一行的图像数据叫做一个扫描行。
一个扫描行的长度必须是4的倍数(字节),如果不是,则需要补齐。
计算公式:
LineBytes=((biWidth*biBitCount+31)And&HFFFFFFE0)\8
由于BMP设定者认为数学坐标系更总要,所以DIB的扫描行是逆序存储的(相对于屏幕坐标系而言),即屏幕上的第一行是DIB位图数据的最后一行。
◆1位色:
用1位表示一个像素,所以一个字节可以表示8个像素。
坐标是从最左边(最高位)开始的,而不是一般情况下的最低位。
在内存的摆放形式如下:
字节
0
...
位
7
6
5
4
3
2
1
0
像素
0
1
2
3
4
5
6
7
◆4位色:
用4位表示一个像素,所以一个字节可以表示2个像素。
坐标是从最左边(最高位)开始的,而不是一般情况下的最低位。
在内存的摆放形式如下:
字节
0
...
位
7
6
5
4
3
2
1
0
像素
0
1
像素位
3
2
1
0
3
2
1
0
◆8位色:
用8位表示一个像素,所以一个字节刚好只能表示一个像素。
在内存的摆放形式如下:
字节
0
1
...
像素
0
1
◆16位色:
用16位表示一个像素,所以两个字节可以表示1个像素。
默认情况下16位DIB是555格式,最高位无效(这对VB是个福音,因为VB没有16位无符号型)。
在内存的摆放形式如下(PC机是低字节在前):
字节
0
1
2
3
...
位
7
6
5
4
3
2
1
0
7
6
5
4
3
2
1
0
7
6
5
4
3
2
1
0
7
6
5
4
3
2
1
0
像素
0
1
RGB
G
B
x
R
G
G
B
x
R
G
RGB位
2
1
0
4
3
2
1
0
0
4
3
2
1
0
4
3
2
1
0
4
3
2
1
0
0
4
3
2
1
0
4
3
◆24位色:
用24位表示一个像素,所以三个字节可以表示1个像素。
注意它的顺序是BGR,而不是传统的RGB。
在内存的摆放形式如下:
字节
0
1
2
3
4
5
...
像素
0
1
RGB
B
G
R
B
G
R
◆32位色:
用32位表示一个像素,所以四个字节可以表示1个像素。
注意绝大多数的GDI函数不会处理Alpha通道(只有AlphaBlend支持)。
在内存的摆放形式如下:
字节
0
1
2
3
4
5
6
7
...
像素
0
1
RGB
B
G
R
A
B
G
R
A
SetDIBitsToDevice
原型定义:
intSetDIBitsToDevice(HDChDC,//handletodevicecontextintXDest,//x-coordinateofupper-leftcornerofdest.rect.intYDest,//y-coordinateofupper-leftcornerofdest.rect.DWORDdwWidth,//sourcerectanglewidthDWORDdwHeight,//sourcerectangleheightintXSrc,//x-coordinateoflower-leftcornerofsourcerect.intYSrc,//y-coordinateoflower-leftcornerofsourcerect.UINTuStartScan,//firstscanlineinarrayUINTcScanLines,//numberofscanlinesCONSTVOID*lpvBits,//addressofarraywithDIBbitsCONSTBITMAPINFO*lpbmi,//addressofstructurewithbitmapinfo.UINTfuColorUse//RGBorpaletteindexes);
VB声明:
DeclareFunctionSetDIBitsToDeviceLib"gdi32.dll"(ByValhDCAsLong,ByValXDestAsLong,ByValYDestAsLong,ByValdwWidthAsLong,ByValdwHeightAsLong,ByValXSrcAsLong,ByValYSrcAsLong,ByValuStartScanAsLong,ByValcScanLinesAsLong,lpvBitsAsAny,lpbmiAsAny,ByValfuColorUseAsLong)AsLong
说明:
将一幅与设备无关位图的全部或部分数据直接复制到一个设备。
这个函数在设备中定义了一个目标矩形,以便接收位图数据。
它也在DIB中定义了一个源矩形,以便从中提取数据
返回值:
如函数执行成功,返回欲复制的扫描线的数量;如返回常数GDI_ERROR,表示出错
参数:
hDC
一个设备场景的句柄。
该场景用于接收位图数据
XDest
指定绘制区域的左上角X坐标
YDest
指定绘制区域的左上角Y坐标
dwWidth
指定绘制区域的高度
dwHeight
指定绘制区域的宽度
XSrc
矩形在DIB中的起点X坐标
YSrc
矩形在DIB中的起点Y坐标
uStartScan
lpvBits中第一条扫描线的编号。
如lpbmi之BITMAPINFOHEADER部分的biHeight字段是正数,那么这条扫描线就会从位图的底部开始计算;如果是负数,就从顶部开始计算
cScanLines
欲复制的扫描线数量
lpvBits
指向一个缓冲区的指针。
这个缓冲区包含了以DIB格式描述的位图数据;这种格式是由lpbmi指定的
lpbmi
指向BITMAPINFO(为兼容BMP4/5而声明成Any),对DIB的格式和颜色进行描述的一个结构
fuColorUse
DIB_PAL_COLORS
颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS
颜色表包含了RGB颜色
StretchDIBits
原型定义:
intStretchDIBits(HDChDC,//handletodevicecontextintXDest,//x-coordinateofupper-leftcornerofdest.rectangleintYDest,//y-coordinateofupper-leftcornerofdest.rectangleintnDestWidth,//widthofdestinationrectangleintnDestHeight,//heightofdestinationrectangleintXSrc,//x-coordinateofupper-leftcornerofsourcerectangleintYSrc,//y-coordinateofupper-leftcornerofsourcerectangleintnSrcWidth,//widthofsourcerectangleintnSrcHeight,//heightofsourcerectangleCONSTVOID*lpBits,//addressofbitmapbitsCONSTBITMAPINFO*lpBitsInfo,//addressofbitmapdataUINTiUsage,//usageflagsDWORDdwRop//rasteroperationcode);
VB声明:
DeclareFunctionStretchDIBitsLib"gdi32"(ByValhDCAsLong,ByValXDestAsLong,ByValYDestAsLong,ByValnDestWidthAsLong,ByValnDestHeightAsLong,ByValXSrcAsLong,ByValYSrcAsLong,ByValnSrcWidthAsLong,ByValnSrcHeightAsLong,lpBitsAsAny,lpBitsInfoAsAny,ByValwUsageAsLong,ByValdwRopAsLong)AsLong
说明:
根据一幅与设备无关的位图创建一幅与设备有关的位图
返回值:
执行成功返回位图句柄,零表示失败
参数:
hDC
一个设备场景的句柄,该设备场景定义了要创建的与设备有关位图的配置信息
XDest
指定绘制区域的左上角X坐标
YDest
指定绘制区域的左上角Y坐标
nDestWidth
指定绘制区域的高度
nDestHeight
指定绘制区域的宽度
XSrc
矩形在DIB中的起点X坐标
YSrc
矩形在DIB中的起点Y坐标
nSrcWidth
指定原位图绘制区域的左上角X坐标
nSrcHeight
指定原位图绘制区域的左上角Y坐标
lpBits
指向一个缓冲区的指针。
这个缓冲区包含了以DIB格式描述的位图数据;这种格式是由lpBitsInfo指定的
lpBitsInfo
指向BITMAPINFO(为兼容BMP4/5而声明成Any),对DIB的格式和颜色进行描述的一个结构
iUsage
DIB_PAL_COLORS
颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS
颜色表包含了RGB颜色
dwRop
欲进行的光栅运算
CreateDIBitmap
原型定义:
HBITMAPCreateDIBitmap(HDChDC,//handletodevicecontextCONSTBITMAPINFOHEADER*lpbmih,//pointertobitmapsizeandformatdataDWORDfdwInit,//initializationflagCONSTVOID*lpbInit,//pointertoinitializationdataCONSTBITMAPINFO*lpbmi,//pointertobitmapcolor-formatdataUINTfuUsage//color-datausage);
VB声明:
DeclareFunctionCreateDIBitmapLib"gdi32"(ByValhDCAsLong,lpbmihAsAny,ByValfdwInitAsLong,lpbInitAsAny,lpbmiAsAny,ByValfuUsageAsLong)AsLong
说明:
将一幅与设备无关位图的全部或部分数据直接复制到一个设备。
这个函数在设备中定义了一个目标矩形,以便接收位图数据。
它也在DIB中定义了一个源矩形,以便从中提取数据
返回值:
执行成功则返回扫描线的数量,零表示失败。
会设置GetLastError
参数:
hDC
一个设备场景的句柄。
该场景用于接收位图数据
lpbmih
BITMAPINFOHEADER(为兼容BMP4/5而声明成Any),对DIB的格式进行描述的一个结构
fdwInit
如不应对位图数据进行初始化,那么设为零。
如设为CBM_INIT,表示根据lpbInit和lpbmi参数对位图进行初始化
lpbInit
指向一个缓冲区的指针。
这个缓冲区包含了以DIB格式描述的位图数据;这种格式是由lpbmi指定的
lpbmi
指向BITMAPINFO(为兼容BMP4/5而声明成Any),对DIB的格式和颜色进行描述的一个结构
fuUsage
DIB_PAL_COLORS
颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS
颜色表包含了RGB颜色
CreateDIBSection
原型定义:
HBITMAPCreateDIBSection(HDChDC,//handletodevicecontextCONSTBITMAPINFO*lpbmi,//pointertostructurecontainingbitmapsize,format,andcolordataUINTiUsage,//colordatatypeindicator:
RGBvaluesorpaletteindexesVOID*ppvBits,//pointertovariabletoreceiveapointertothebitmap´sbitvaluesHANDLEhSection,//optionalhandletoaf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VB 高效 图像 处理 程序 doc 资料