转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> VB.NET程序 >> 正文
用VB写高效的图像处理程序         ★★★★
Windows 98 Windows XP 说 明 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中写能够实时处理的图像处理程序。


二、DIB的结构

  在 Windows 3.0 以前,Windows系统用的是DDB(设备有关位图)。DDB没有调色板,显示的颜色依赖硬件,处理色彩很不方便。所以 Microsoft 在 Windows 3.0中 重新定义了BMP文件格式(BMP 3.0),使其支持设备无关位图——也就是DIB。

  时至今日,BMP的版本号已升至5.0(Windows NT 4.0、Windows95 定义了 BMP 4.0,Windows 98、Windows 2000 定义了 BMP 5.0),但基本结构没有变——仍是 BMP文件头 和 DIB 组成:

BMP文件 BITMAPFILEHEADER BMP文件头 DIB BITMAPINFOHEADER 位图信息头 BITMAPINFO RGBQUAD[] 调色板 位图数据
#代表可以不填(=0)的项目)
原型定义:
typedef struct tagBITMAPFILEHEADER { // bmfh
    WORD    bfType;
    DWORD   bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD   bfOffBits;
} BITMAPFILEHEADER;
VB声明:
Type BITMAPFILEHEADER
    bfType(0 to 1) As Byte
    bfSize As Long
    bfReserved1 As Integer
    bfReserved2 As Integer
    bfOffBits As Long
End Type
说明: bfType 指示文件的类型,必须是“BM” bfSize# 指示文件的大小,包括BITMAPFILEHEADER bfReserved1 保留,=0 bfReserved2 保留,=0 bfOffBits# 从文件头到位图数据的偏移字节数
原型定义:
typedef struct tagBITMAPINFOHEADER{ // bmih
    DWORD  biSize;
    LONG   biWidth;
    LONG   biHeight;
    WORD   biPlanes;
    WORD   biBitCount;
    DWORD  biCompression;
    DWORD  biSizeImage;
    LONG   biXPelsPerMeter;
    LONG   biYPelsPerMeter;
    DWORD  biClrUsed;
    DWORD  biClrImportant;
} BITMAPINFOHEADER;
VB声明:
Type BITMAPINFOHEADER
    biSize As Long
    biWidth As Long
    biHeight As Long
    biPlanes As Integer
    biBitCount As Integer
    biCompression As Long
    biSizeImage As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As Long
    biClrImportant As Long
End Type
说明: 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(BMP 5.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压缩(BMP 5.0)
  BI_PNG:PNG压缩(BMP 5.0) biSizeImage# 实际的位图数据所占字节(biCompression=BI_RGB时可以省略) biXPelsPerMeter# 目标设备的水平分辨率,单位是每米的像素个数 biYPelsPerMeter# 目标设备的垂直分辨率,单位是每米的像素个数 biClrUsed# 使用的颜色数(当biBitCount等于1、4、8时才有效)。如果该项为0,表示颜色数为2^biBitCount biClrImportant# 重要的颜色数。如果该项为0,表示所有颜色都是重要的
原型定义:
typedef struct tagRGBQUAD { // rgbq
    BYTE    rgbBlue;
    BYTE    rgbGreen;
    BYTE    rgbRed;
    BYTE    rgbReserved;
} RGBQUAD;
VB声明:
Private Type RGBQUAD
    rgbBlue As Byte
    rgbGreen As Byte
    rgbRed As Byte
    rgbReserved As Byte
End Type
说明: 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 ... 位 76543210 7 654321076543210 7 6543210 像素 0 1 RGB GB x RGGB x RG RGB位 21043210 0 432104321043210 0 432104324位色:
  用24位表示一个像素,所以三个字节可以表示1个像素。注意它的顺序是BGR,而不是传统的RGB。在内存的摆放形式如下: 字节 0 1 2 3 4 5 ... 像素 0 1 RGB BGRBGR32位色:
  用32位表示一个像素,所以四个字节可以表示1个像素。注意绝大多数的GDI函数不会处理Alpha通道(只有AlphaBlend支持)。在内存的摆放形式如下: 字节 0 1 2 3 4 5 6 7 ... 像素 0 1 RGB BGR A BGR A

三、DIB访问函数

原型定义:
int SetDIBitsToDevice(
  HDC hDC,              // handle to device context
  int XDest,            // x-coordinate of upper-left corner of dest. rect.
  int YDest,            // y-coordinate of upper-left corner of dest. rect.
  DWORD dwWidth,        // source rectangle width
  DWORD dwHeight,       // source rectangle height
  int XSrc,             // x-coordinate of lower-left corner of source rect.
  int YSrc,             // y-coordinate of lower-left corner of source rect.
  UINT uStartScan,      // first scan line in array
  UINT cScanLines,      // number of scan lines
  CONST VOID *lpvBits,  // address of array with DIB bits
  CONST BITMAPINFO *lpbmi,  // address of structure with bitmap info.
  UINT fuColorUse       // RGB or palette indexes
);
VB声明: Declare Function SetDIBitsToDevice Lib "gdi32.dll" (ByVal hDC As Long, ByVal XDest As Long, ByVal YDest As Long, ByVal dwWidth As Long, ByVal dwHeight As Long, ByVal XSrc As Long, ByVal YSrc As Long, ByVal uStartScan As Long, ByVal cScanLines As Long, lpvBits As Any, lpbmi As Any, ByVal fuColorUse As Long) As Long 说明: 将一幅与设备无关位图的全部或部分数据直接复制到一个设备。这个函数在设备中定义了一个目标矩形,以便接收位图数据。它也在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

[1] [2] [3]  下一页


没有相关教程

用VB写高效的图像处理程序

作者:闵涛 文章来源:闵涛的学习笔记 点击数:2292 更新时间:2009/4/23 18:59:35

一、为什么这么慢?

  自盘古开天地以来(好像夸张了点),一直有人抱怨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;单位:毫秒 BMP文件头——BITMAPFILEHEADER 文件信息头——BITMAPINFOHEADER 调色板
  只有biBitCount等于1、4、8时才有调色板。调色板实际上是一个数组,元素的个数由biBitCount和biClrUsed决定。
位图数据 SetDIBitsToDevice
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台