manbetx官方网站

据此VB写高效之图像处理程序 V2.0(2006-5-24)用VB写高效的图像处理程序 V1.0

十月 12th, 2018  |  manbet体育登录

为此VB写高效的图像处理程序 V2.0(2006-5-24)

作者:zyl910

一、为什么这么慢?
二、DIB的结构
三、DIB访问函数
四、实战练习
五、使用DIBSection和模拟指针
六、结合DirectX

相同、为什么这样慢?

  自盘古开天地吧(好像夸张了碰),一直有人抱怨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;单位:毫秒
  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中描写能实时处理的图像处理程序。

 

平等、为什么如此慢?

  自盘古开天地吧(好像夸张了接触),一直有人抱怨VB程序速度缓慢。特别是图像处理,被看是VB的禁区。说起来也是,市面上的关于VB的图像处理的多少都是优先出言计算公式,再一直用PSet(或API函数SetPixel)逐点画(至少我见了的书还是这样)。效果是办到了,但速度迟滞得离谱:对同轴640*480之图像进行半晶莹剔透合并就需要10秒钟;而当PhotoShop中,只要同设置图层的透明度,半透明效果就表现。难怪有人说VB的拉扯。

 

  但就并无意味着VB不克写高速的图像处理程序,速度放缓是以无动对的艺术。

 

  从VB5初始,能以本机代码编译成exe文件,所以不设有代码执行速度的题目。那么,是呀拖慢了快也?就是PSet和SetPixel!PSet把浮点形式的坐标转为像素单位,再付诸SetPixel处理。而SetPixel呢,坐标系转化、剪裁区域判断、将颜色相当也装备支持的不过接近的,最后还要依据不同之水彩格式寻址、为以颜色写副其所在位进行各类运算。经过这么多层处理,速度不慢才生。

 

  那么,怎样才能提高处理速度呢?使用DIB,直接针对位图所在内存进行操作,速度好大大提高。现在探视本文提供的范例程序的实行进度,这单是一个简的色彩演示程序。

 

图像尺寸:640*480*24b。单位:毫秒
  Debug Relase 说 明
1_PSet 1156.7042 936.2807 在VB使用 PSet 画的
2_SetPixelV 484.7545 460.5382 在VB使用 SetPixelV 画的
3_DIB 118.6978 3.8317 在VB使用 DIB 画的
4_DIB_Ptr 107.5791 4.3545 在VB使用 DirectDraw + 模拟指针 画的
5_DX7Ptr 108.1261 4.5503 在VB使用 DirectDraw + 模拟指针 画的
6_DX7Arr 131.8148 7.5506 在VB使用 DIBSection + GetLockedArray 画的
VC 2.8535 1.8994 用Visual C++ 6.0写的
我的电脑配置
CPU AMD Athlon XP 1700+(实际频率:1463 MHz (11 x 133))
内存 Kingston DDR266 256MB *2(两根)
显卡 nVIDIA GeForce2 MX/MX 400(AGP 4X,显存32MB)
测试环境 Windows XP sp2

图片 1
  从之表中而看到:
  1.VC比3_DIB、4_DIB_Ptr快一些,这是因SafeArray结构的数组比真正的指针慢,但为不是一些人所说之70~100倍;
  2.4_DIB_Ptr比3_DIB慢一点,这是坐学指针本来就是是依SafeArray结构的高频组,需要在运转时动态修改数组数地址,所以速度缓慢一点;
  3.真正差了70~100倍是1_PSet和2_SetPixelV。
  4.于VB
IDE中说明实施顺序非常慢,3_DIB就存在30倍的进度差距。所以不时有俗之丁用
VC Debug编译的次序 与 VB IDE中说施行顺序 比较快。
  5.4_DIB_Ptr、5_DX7Ptr速度一样,这是盖都是下模拟指针技术一直访问内存来做图像处理的。而6_DX7Arr使用的凡GetLockedArray返回的二维数组,二维数组比一维数组慢。

 

  以上可证,速度放缓的由是SetPixelV非常低效,而并无是VB的题目。虽然VC的确实较快,但是自勾勒这首文章不是为讨论速度极(否则就篇稿子会改名为《如何用汇编描绘高速的图像处理程序》),而是为告诉大家怎么以VB中描绘会实时处理的图像处理程序。

 

  同时,决定代码速度之匪是编程语言或编译器,而是算法。如果算法写得差之语,无论你用什么编程语言还是编译器,那次速度还大缓慢(你当VC中之所以SetPixelV写图像处理程序试试)。而如今的硬件配置都足够好,用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)的种)

BMP文件头——BITMAPFILEHEADER

原型定义:

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#

于文本头至位图数据的偏移字节数

文件信息头——BITMAPINFOHEADER

原型定义:

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,表示有颜色都是重大的

调色板
  只有biBitCount等被1、4、8时才出调色板。调色板实际上是一个频组,元素的个数由biBitCount和biClrUsed决定。

原型定义:

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

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

二、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)的品种)

BMP文件头——BITMAPFILEHEADER

原型定义:

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#

打文本头至位图数据的偏移字节数

文件信息头——BITMAPINFOHEADER

原型定义:

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,表示有颜色都是第一的

调色板
  只有biBitCount等被1、4、8时才来调色板。调色板实际上是一个再三组,元素的个数由biBitCount和biClrUsed决定。

原型定义:

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机使用小端规则(little
endian),是低字节在前方):

字节

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

老三、DIB访问函数

SetDIBitsToDevice

原型定义:

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

指向BITMAPINFO(为兼容BMP4/5只要声明成Any),对DIB的格式和颜料进行描述的一个构造

fuColorUse

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

StretchDIBits

原型定义:

int StretchDIBits(
  HDC hDC,                // handle to device context
  int XDest,              // x-coordinate of upper-left corner of dest. rectangle
  int YDest,              // y-coordinate of upper-left corner of dest. rectangle
  int nDestWidth,         // width of destination rectangle
  int nDestHeight,        // height of destination rectangle
  int XSrc,               // x-coordinate of upper-left corner of source rectangle
  int YSrc,               // y-coordinate of upper-left corner of source rectangle
  int nSrcWidth,          // width of source rectangle
  int nSrcHeight,         // height of source rectangle
  CONST VOID *lpBits,            // address of bitmap bits
  CONST BITMAPINFO *lpBitsInfo,  // address of bitmap data
  UINT iUsage,                   // usage flags
  DWORD dwRop                    // raster operation code
);

VB声明:

Declare Function StretchDIBits Lib “gdi32” (ByVal hDC As Long, ByVal
XDest As Long, ByVal YDest As Long, ByVal nDestWidth As Long, ByVal
nDestHeight As Long, ByVal XSrc As Long, ByVal YSrc As Long, ByVal
nSrcWidth As Long, ByVal nSrcHeight As Long, lpBits As Any, lpBitsInfo
As Any, ByVal wUsage As Long, ByVal dwRop As Long) As Long

说明:

冲同样轴及设施无关之位图创建同幅及设备有关的位图

返回值:

执行成功返回位图句柄,零意味着失败

参数:

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

原型定义:

HBITMAP CreateDIBitmap(
  HDC hDC,                  // handle to device context
  CONST BITMAPINFOHEADER *lpbmih,  // pointer to bitmap size and format data
  DWORD fdwInit,            // initialization flag
  CONST VOID *lpbInit,      // pointer to initialization data
  CONST BITMAPINFO *lpbmi,  // pointer to bitmap color-format data
  UINT fuUsage              // color-data usage
);

VB声明:

Declare Function CreateDIBitmap Lib “gdi32” (ByVal hDC As Long, lpbmih
As Any, ByVal fdwInit As Long, lpbInit As Any, lpbmi As Any, ByVal
fuUsage As Long) As Long

说明:

用一如既往轴及设施无关位图的通还是局部数据直接复制到一个装备。这个函数在设施中定义了一个靶矩形,以便接受各类图数据。它呢当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

原型定义:

HBITMAP CreateDIBSection(
  HDC hDC,          // handle to device context
  CONST BITMAPINFO *lpbmi,
                    // pointer to structure containing bitmap size, format, and color data
  UINT iUsage,      // color data type indicator: RGB values or palette indexes
  VOID *ppvBits,    // pointer to variable to receive a pointer to  the bitmap's bit values
  HANDLE hSection,  // optional handle to a file mapping object
  DWORD dwOffset    // offset to the bitmap bit values within the file mapping object
);

VB声明:

Declare Function CreateDIBSection Lib “gdi32” (ByVal hDC As Long, lpbmi
As Any, ByVal iUsage As Long, ByRef ppvBits As Long, ByVal hSection As
Long, ByVal dwOffset As Long) As Long

说明:

CreateDIBSection能缔造同栽特别的DIB,称为DIB项(DIBSection),然后回到一个GDI位图的句柄。它提供了DIB和GDI位图的太好之性状。这样我们好直接访问DIB的内存,可以用各类图句柄和内存设备条件,我们竟然还足以于DIB中调用GDI函数来绘图

返回值:

履行成功返回DIBSection位图的句柄,零意味着失败。会安装GetLastError

参数:

hDC

一个设备景的句柄。如dw设为DIB_PAL_COLORS,那么DIB颜色表就见面就此自逻辑调色板的颜色进行初始化

lpbmi

指向BITMAPINFO(为兼容BMP4/5一旦声明成Any),这个组织初始化成欲创建的那么幅位图的部署数据

iUsage

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

ppvBits

用于取DIBSection数据区的内存地址

hSection

对一个文本映射对象的可选句柄,位图将在其中创建。如一旦为零星,Windows会自动分配内存

dwOffset

要指定了句柄,就因故是参数指定位图数据在文件映射对象中之偏移量

GetDIBits

原型定义:

int GetDIBits(
  HDC hDC,           // handle to device context
  HBITMAP hbmp,      // handle to bitmap
  UINT uStartScan,   // first scan line to set in destination bitmap
  UINT cScanLines,   // number of scan lines to copy
  LPVOID lpvBits,    // address of array for bitmap bits
  LPBITMAPINFO lpbmi,// address of structure with bitmap data
  UINT uUsage        // RGB or palette index
);

VB声明:

Declare Function GetDIBits Lib “gdi32” (ByVal hDC As Long, ByVal hbmp As
Long, ByVal uStartScan As Long, ByVal cScanLines As Long, lpvBits As
Any, lpbmi As Any, ByVal uUsage As Long) As Long

说明:

欠函数利用申请及的内存,由GDI各图取DIB个图数据。通过该函数,可以针对DIB的格式进行控制,可以制定颜色的位数,而且好指定是否开展削减。如果以了滑坡方式,则须调用该函数点滴浅,一浅为拿走所需要内存,另外一破为得到位图数据

返回值:

实践成功则归扫描线的多寡,零代表失败。会装GetLastError

参数:

hDC

概念了和装备有关各图hBitmap的布置信息的一个装备景的句柄

hbmp

源位图的句柄

uStartScan

用复制到DIB中的首先修扫描线的号

cScanLines

待复制的扫描线数量

lpvBits

针对一个缓冲区的指针。这个缓冲区包含了坐DIB格式描述的位图数据;这种格式是出于lpbmi指定的

lpbmi

指向BITMAPINFO(为兼容BMP4/5如果声明成Any).对DIB的格式和颜色进行认证的一个结构。在BITMAPINFOHEADER结构面临,从biSize到biCompression之间的具有字段都必须初始化

uUsage

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

SetDIBits

原型定义:

int SetDIBits(
  HDC hDC,                  // handle to device context
  HBITMAP hbmp,             // handle to bitmap
  UINT uStartScan,          // starting scan line
  UINT cScanLines,          // number of scan lines
  CONST VOID *lpvBits,      // array of bitmap bits
  CONST BITMAPINFO *lpbmi,  // address of structure with bitmap data
  UINT uUsage               // type of color indexes to use
);

VB声明:

Declare Function SetDIBits Lib “gdi32” (ByVal hDC As Long, ByVal hbmp As
Long, ByVal uStartScan As Long, ByVal cScanLines As Long, lpvBits As
Any, lpbmi As Any, ByVal uUsage As Long) As Long

说明:

以自和设施无关位图的二进制位复制到平等幅及装备有关的位图里

返回值:

执行成功则赶回扫描线的数量,零意味着失败。会设置GetLastError

参数:

hDC

概念了与设施有关各图hBitmap的安排信息的一个装备景的句柄

hbmp

源位图的句柄

uStartScan

得复制到DIB中的率先漫长扫描线的号子

cScanLines

待复制的扫描线数量

lpvBits

针对一个缓冲区的指针。这个缓冲区包含了坐DIB格式描述的位图数据;这种格式是由于lpbmi指定的

lpbmi

指向BITMAPINFO(为兼容BMP4/5而声明成Any).对DIB的格式和颜色进行验证的一个结构。在BITMAPINFOHEADER结构面临,从biSize到biCompression之间的有字段都必须初始化

uUsage

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

GetDIBColorTable

原型定义:

UINT GetDIBColorTable(
  HDC hDC,          // handle to device context whose DIB is of interest
  UINT uStartIndex, // color table index of first entry to retrieve
  UINT cEntries,    // number of color table entries to retrieve
  RGBQUAD *pColors  // pointer to buffer that receives color table entries
);

VB声明:

Declare Function GetDIBColorTable Lib “gdi32” (ByVal hDC As Long, ByVal
uStartIndex As Long, ByVal cEntries As Long, pColors As RGBQUAD) As Long

说明:

起选入设备景的DIBSection中得颜色表信息

返回值:

抱回之颜色条目数量,零表示失败。会装GetLastError

参数:

hDC

现已选入了一个DIBSection对象的装备景

uStartIndex

颜色表中待抱回的第一独章的目

cEntries

消抱回之条文数量

pColors

是布局数组用于装载颜色表信息之第一只章

SetDIBColorTable

原型定义:

UINT SetDIBColorTable(
  HDC hDC,                // handle to device context whose DIB is of interest
  UINT uStartIndex,       // color table index of first entry to set
  UINT cEntries,          // number of color table entries to set
  CONST RGBQUAD *pColors  // pointer to array of color table entries
);

VB声明:

Declare Function SetDIBColorTable Lib “gdi32” (ByVal hDC As Long, ByVal
uStartIndex As Long, ByVal cEntries As Long, pColors As RGBQUAD) As Long

说明:

自打选入设备景的DIBSection中取颜色表信息

返回值:

抱回之颜料条目数量,零代表失败。会设置GetLastError

参数:

hDC

现已选入了一个DIBSection对象的设备景

uStartIndex

颜色表中需抱回之第一独章的目录

cEntries

消抱回之条规数量

pColors

以此组织数组用于装载颜色表信息之第一只条目

老三、DIB访问函数

SetDIBitsToDevice

原型定义:

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

指向BITMAPINFO(为兼容BMP4/5要声明成Any),对DIB的格式和颜色进行描述的一个结构

fuColorUse

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

StretchDIBits

原型定义:

int StretchDIBits(
  HDC hDC,                // handle to device context
  int XDest,              // x-coordinate of upper-left corner of dest. rectangle
  int YDest,              // y-coordinate of upper-left corner of dest. rectangle
  int nDestWidth,         // width of destination rectangle
  int nDestHeight,        // height of destination rectangle
  int XSrc,               // x-coordinate of upper-left corner of source rectangle
  int YSrc,               // y-coordinate of upper-left corner of source rectangle
  int nSrcWidth,          // width of source rectangle
  int nSrcHeight,         // height of source rectangle
  CONST VOID *lpBits,            // address of bitmap bits
  CONST BITMAPINFO *lpBitsInfo,  // address of bitmap data
  UINT iUsage,                   // usage flags
  DWORD dwRop                    // raster operation code
);

VB声明:

Declare Function StretchDIBits Lib “gdi32” (ByVal hDC As Long, ByVal
XDest As Long, ByVal YDest As Long, ByVal nDestWidth As Long, ByVal
nDestHeight As Long, ByVal XSrc As Long, ByVal YSrc As Long, ByVal
nSrcWidth As Long, ByVal nSrcHeight As Long, lpBits As Any, lpBitsInfo
As Any, ByVal wUsage As Long, ByVal dwRop As Long) As Long

说明:

依据同样轴及设施无关的位图创建同幅及设备有关的位图

返回值:

履行成功返回位图句柄,零意味着失败

参数:

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

原型定义:

HBITMAP CreateDIBitmap(
  HDC hDC,                  // handle to device context
  CONST BITMAPINFOHEADER *lpbmih,  // pointer to bitmap size and format data
  DWORD fdwInit,            // initialization flag
  CONST VOID *lpbInit,      // pointer to initialization data
  CONST BITMAPINFO *lpbmi,  // pointer to bitmap color-format data
  UINT fuUsage              // color-data usage
);

VB声明:

Declare Function CreateDIBitmap Lib “gdi32” (ByVal hDC As Long, lpbmih
As Any, ByVal fdwInit As Long, lpbInit As Any, lpbmi As Any, ByVal
fuUsage As Long) As Long

说明:

拿同样帧及装备无关位图的布满或者部分数据直接复制到一个装置。这个函数在装置遭遇定义了一个目标矩形,以便接受各类图数据。它为在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

原型定义:

HBITMAP CreateDIBSection(
  HDC hDC,          // handle to device context
  CONST BITMAPINFO *lpbmi,
                    // pointer to structure containing bitmap size, format, and color data
  UINT iUsage,      // color data type indicator: RGB values or palette indexes
  VOID *ppvBits,    // pointer to variable to receive a pointer to  the bitmap's bit values
  HANDLE hSection,  // optional handle to a file mapping object
  DWORD dwOffset    // offset to the bitmap bit values within the file mapping object
);

VB声明:

Declare Function CreateDIBSection Lib “gdi32” (ByVal hDC As Long, lpbmi
As Any, ByVal iUsage As Long, ByRef ppvBits As Long, ByVal hSection As
Long, ByVal dwOffset As Long) As Long

说明:

CreateDIBSection能创同种特有的DIB,称为DIB项(DIBSection),然后回来一个GDI位图的句柄。它提供了DIB和GDI位图的绝好的性状。这样咱们得以直接访问DIB的内存,可以采用各类图句柄和内存设备条件,我们居然还足以当DIB中调用GDI函数来绘图

返回值:

行成功返回DIBSection位图的句柄,零表示失败。会安装GetLastError

参数:

hDC

一个装备景的句柄。如dw设为DIB_PAL_COLORS,那么DIB颜色表就会见用来自逻辑调色板的颜料进行初始化

lpbmi

指向BITMAPINFO(为兼容BMP4/5万一声明成Any),这个组织初始化成欲创建的那幅位图的布局数据

iUsage

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

ppvBits

用来取DIBSection数据区的内存地址

hSection

对一个文书映射对象的可选句柄,位图将当中间创建。如一旦为零星,Windows会自动分配内存

dwOffset

而指定了句柄,就因故这个参数指定位图数据以文书映射对象中的偏移量

GetDIBits

原型定义:

int GetDIBits(
  HDC hDC,           // handle to device context
  HBITMAP hbmp,      // handle to bitmap
  UINT uStartScan,   // first scan line to set in destination bitmap
  UINT cScanLines,   // number of scan lines to copy
  LPVOID lpvBits,    // address of array for bitmap bits
  LPBITMAPINFO lpbmi,// address of structure with bitmap data
  UINT uUsage        // RGB or palette index
);

VB声明:

Declare Function GetDIBits Lib “gdi32” (ByVal hDC As Long, ByVal hbmp As
Long, ByVal uStartScan As Long, ByVal cScanLines As Long, lpvBits As
Any, lpbmi As Any, ByVal uUsage As Long) As Long

说明:

欠函数利用申请到的内存,由GDI位图取DIB号图数据。通过该函数,可以本着DIB的格式进行支配,可以制定颜色之位数,而且可以指定是否进行压缩。如果用了压缩方式,则必须调用该函数鲜不成,一次于以博所要内存,另外一坏为拿走位图数据

返回值:

履成功则回扫描线的多寡,零意味着失败。会装GetLastError

参数:

hDC

概念了和装备有关各图hBitmap的配置信息的一个配备景的句柄

hbmp

源位图的句柄

uStartScan

消复制到DIB中的率先长长的扫描线的号码

cScanLines

用复制的扫描线数量

lpvBits

对一个缓冲区的指针。这个缓冲区包含了为DIB格式描述的位图数据;这种格式是由于lpbmi指定的

lpbmi

指向BITMAPINFO(为兼容BMP4/5如果声明成Any).对DIB的格式和颜色进行说明的一个组织。在BITMAPINFOHEADER结构面临,从biSize到biCompression之间的所有字段都必初始化

uUsage

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

SetDIBits

原型定义:

int SetDIBits(
  HDC hDC,                  // handle to device context
  HBITMAP hbmp,             // handle to bitmap
  UINT uStartScan,          // starting scan line
  UINT cScanLines,          // number of scan lines
  CONST VOID *lpvBits,      // array of bitmap bits
  CONST BITMAPINFO *lpbmi,  // address of structure with bitmap data
  UINT uUsage               // type of color indexes to use
);

VB声明:

Declare Function SetDIBits Lib “gdi32” (ByVal hDC As Long, ByVal hbmp As
Long, ByVal uStartScan As Long, ByVal cScanLines As Long, lpvBits As
Any, lpbmi As Any, ByVal uUsage As Long) As Long

说明:

用自和设备无关位图的二进制位复制到同样帧及装备有关的位图里

返回值:

推行成功则归扫描线的多少,零象征失败。会设置GetLastError

参数:

hDC

概念了和设备有关各图hBitmap的布信息之一个设备景的句柄

hbmp

源位图的句柄

uStartScan

要复制到DIB中之首先修扫描线的数码

cScanLines

欲复制的扫描线数量

lpvBits

针对一个缓冲区的指针。这个缓冲区包含了因DIB格式描述的位图数据;这种格式是出于lpbmi指定的

lpbmi

指向BITMAPINFO(为兼容BMP4/5设声明成Any).对DIB的格式和颜色进行验证的一个构造。在BITMAPINFOHEADER结构中,从biSize到biCompression之间的装有字段都得初始化

uUsage

DIB_PAL_COLORS 颜色表是一个整数数组,其中包含了与目前选入hDC设备场景的调色板相关的索引
DIB_RGB_COLORS 颜色表包含了RGB颜色

GetDIBColorTable

原型定义:

UINT GetDIBColorTable(
  HDC hDC,          // handle to device context whose DIB is of interest
  UINT uStartIndex, // color table index of first entry to retrieve
  UINT cEntries,    // number of color table entries to retrieve
  RGBQUAD *pColors  // pointer to buffer that receives color table entries
);

VB声明:

Declare Function GetDIBColorTable Lib “gdi32” (ByVal hDC As Long, ByVal
uStartIndex As Long, ByVal cEntries As Long, pColors As RGBQUAD) As Long

说明:

自打选入设备景的DIBSection中得到颜色表信息

返回值:

得回的颜料条目数量,零代表失败。会设置GetLastError

参数:

hDC

既选入了一个DIBSection对象的设备景

uStartIndex

颜色表中需抱回之第一个条文的目

cEntries

需要抱回的条款数量

pColors

以此组织数组用于装载颜色表信息的第一独章

SetDIBColorTable

原型定义:

UINT SetDIBColorTable(
  HDC hDC,                // handle to device context whose DIB is of interest
  UINT uStartIndex,       // color table index of first entry to set
  UINT cEntries,          // number of color table entries to set
  CONST RGBQUAD *pColors  // pointer to array of color table entries
);

VB声明:

Declare Function SetDIBColorTable Lib “gdi32” (ByVal hDC As Long, ByVal
uStartIndex As Long, ByVal cEntries As Long, pColors As RGBQUAD) As Long

说明:

自选入设备景的DIBSection中得到颜色表信息

返回值:

收获回的颜料条目数量,零意味着失败。会设置GetLastError

参数:

hDC

既选入了一个DIBSection对象的装置景

uStartIndex

颜色表中要抱回的率先独章的目

cEntries

内需抱回之条款数量

pColors

这个组织数组用于装载颜色表信息之率先独章

季、实战演习

  用DIB写图像处理程序的时,首先要明了一点:DIB并无是图像处理算法,而是同栽绘图方法。处理算法比DIB高一级,管理坐标和颜色之演算;而DIB只是为绘制。所以此时处理算法的效率是速度的重要。

 

  以DIB绘制图像并无比用PSet/SetPixel绘制差多少,它只是把坐标运算改化地方运算而已。很多人知指针是一个危险的事物,就是为她能直接访问内存,如果指针不小心指错地方吧,Windows立即报一般保护性错误。所以,在地点运算的时光势必要小心,同时假设小心天天保存,因为这底非法操作的发生率非常强,否则辛辛苦苦写的代码一瞬间没了但生成慌我从不提醒什么。

 

  好了,现在开!

 

  由于拍卖算法起指导作用,所以现在先行讲解VB_PSet。所有的代码都以FrmMain.frm中。其他的进程的代码可以无看,现在用注意力集中在“DrawIt”中,它就是是无绘制的。

 

  其实自己此演示程序非常简单的:R分量延着水平方向多,G分量延着垂直方向多,B分量则于右侧为左滚动。什么?!“And
&HFF”是什么意思?!这可是基础啊……(下略&HFFFF…字)。“&H”表示十六前进制数,而And表示按位与。&HFF是二进制的“1111
1111”,正好覆盖了低8员,这时用And进行按位与,只会获取低8号,与RGB分量需要的8号刚刚符合(对于“(J

  • K) And &HFF”来说,可以兑现滚动效应)。

 

  If Not 看明白了 Then Goto 前少段落

 

  好!现在打开VB_DIB。(由于24号会一直指定RGB分量,所以这里是用底凡24各项DIB)

 

  看了面前的“DIB的组织”,是无是起接触昏呢?其实DIB也从未什么,就是
一个发表位图信息之BITMAPINFO结构 和
一个储存各项图数据的数目缓冲区,顶多更就此SetDIBitsToDevice绘制,所以VB_DIB与VB_PSet相比就是差不多了SetDIBitsToDevice、BITMAPINFOHEADER(24号DIB没有调色板,所以用BITMAPINFOHEADER就行)和部分常数的扬言而已。由于此演示程序不需变更图像大小及质生,所以可以拿有关变量作为窗体级变量,再在Form_Load中初始化。由于DIB并无为系统报名资源(数组的内存是VB分配的,会自动释放),所以无需写释放代码。

 

  现在来拘禁DrawIt。
  1.则可以逐点把坐标映射成地址再写,但是如此效率太没有了,可以动用坐标处理的连续性进行优化。
  2.由于自身这里用的是累累组,所以这里用(数组元素)索引代替地址。
  3.极端开头要留意DIB是逆序存储的,要拿索引设为最后一行第一个像从的目录。
  4.出于DIB的RGB顺序是B、G、R,所以“MapData(CurIdx +
?)”的逐一是2、1、0。
  5.装置好一个像素的水彩后,要注意把索引改呢产只像从的目录。
  6.是因为DIB是逆序存储的,移到下一个扫描行是“LineIdx = LineIdx –
LineBytes”

 


  “好了,代码看懂了,按F5周转看效果。”
  “咦?速度好像没有抢多少啊?”


  这是由于程序于VB环境下是盖分解道运行的,而说方式对做图像处理所需要大循环和大量之算术运算的尽效率很没有,所以要造译成(本机代码)exe重新运行。此时还要注意编译优化,可以拿“高级优化”的装有勾打上,速度只是提升20%左右。

 

季、实战练兵

  用DIB写图像处理程序的上,首先使明了一点:DIB并无是图像处理算法,而是同种绘图方法。图像处理算法是DIB高级,管理坐标和颜色之演算;而DIB只是为绘制。所以此时处理算法的效率是速度的基本点。

 

  以DIB绘制图像并从未比用PSet/SetPixel绘制差多少,它只是将坐标运算改化地方运算而已。很多人知指针是一个惊险的事物,就是盖其会直接看内存,如果指针不小心指错地方吧,Windows立即告诉一般保护性错误。所以,在地方运算的上势必要是小心,同时要小心天天保存,因为此时的非法操作的发生率非常高,否则辛辛苦苦写的代码一瞬间没了而是生成老我从未提醒什么。

 

  好了,现在始于!

 

  由于处理算法起指导作用,所以现在事先称解1_PSet。所有的代码都在FrmMain.frm中。其他的长河的代码可以免扣,现在拿注意力集中在“DrawIt”中,它就是是无绘制的。

 

vb6/1_PSet/FrmMain.frm中DrawIt
'绘制
Private Sub DrawIt()
    Dim I As Long, J As Long
    Static K As Long

    For I = 0 To ImgHeight - 1 'Y
        For J = 0 To ImgWidth - 1 'X
            PicView.PSet (J, I), RGB(J And &HFF, I And &HFF, (J + K) And &HFF)
        Next J
    Next I

    K = (K + 1) And &HFF

End Sub

  其实我是演示程序非常简单的:R分量延着水平方向多,G分量延着垂直方向加,B分量则从右边为左滚动。什么?!“And
&HFF”是啊意思?!这不过基础啊……(下略&HFFFF…字)。“&H”表示十六前进制数,而And表示按位与。&HFF是二进制的“1111
1111”,正好覆盖了低8员,这时用And进行按位与,只见面收获低8位,与RGB分量需要之8号正适合(对于“(J

  • K) And &HFF”来说,可以兑现滚动效应)。

 

  If Not 看明白了 Then Goto 前片段子

 

  好!现在开拓3_DIB。(由于24号能够直接指定RGB分量,所以这边是为此的是24各项DIB)

 

  看了前的“DIB的布局”,是无是发出硌昏呢?其实DIB也从不什么,就是
一个发挥位图信息的BITMAPINFO结构 和
一个仓储各项图数据的数量缓冲区,顶多还就此SetDIBitsToDevice绘制,所以3_DIB与1_PSet相比就是基本上了SetDIBitsToDevice、BITMAPINFOHEADER(24号DIB没有调色板,所以用BITMAPINFOHEADER就行)和一部分常数的宣示而已。由于这个演示程序不待改图像大小和质量生,所以可以将有关变量作为窗体级变量,再当Form_Load中初始化。由于DIB并没有向网报名资源(数组的内存是VB分配的,会自行释放),所以不待写释放代码。

 

  现在来拘禁DrawIt。

vb6/3_DIB/FrmMain.frm中DrawIt
'绘制
Private Sub DrawIt()
    Dim I As Long, J As Long
    Static K As Long
    Dim iLinePtr As Long, iCurPtr As Long

    iLinePtr = (m_BI.biHeight - 1) * m_LineBytes 'DIB是逆序存储的
    For I = 0 To ImgHeight - 1 'Y
        iCurPtr = iLinePtr
        For J = 0 To ImgWidth - 1 'X
            'PicView.PSet (J, I), RGB(J And &HFF, I And &HFF, (J + K) And &HFF)
            m_MapData(iCurPtr + 2) = J And &HFF       'Red
            m_MapData(iCurPtr + 1) = I And &HFF       'Green
            m_MapData(iCurPtr + 0) = (J + K) And &HFF 'Blue
            iCurPtr = iCurPtr + 3 '24位
        Next J
        iLinePtr = iLinePtr - m_LineBytes
    Next I

    K = (K + 1) And &HFF

End Sub

  1.虽可逐点把坐标映射成地址再写,但是如此效率太没有了,可以以坐标处理的连续性进行优化。
  2.是因为自身此用底是数组,所以这里用(数组元素)索引代替地址。
  3.太开始要留心DIB是逆序存储的,要以索引设为终极一履行第一只像从的目录。
  4.由于DIB的RGB顺序是B、G、R,所以“m_MapData(CurIdx +
?)”的依次是2、1、0。
  5.安好一个像素的颜色后,要顾将索引改吗下单如从的目。
  6.出于DIB是逆序存储的,移到下一个扫描行是“iLinePtr = iLinePtr –
m_LineBytes”

 


  “好了,代码看懂了,按F5运作看效果。”
  “咦?速度好像没有抢多少呀?”


  这是由程序于VB环境下是盖分解道运行的,而说方式对做图像处理所待广泛循环和大气底算术运算的尽效率非常没有,所以如果造译成(本机代码)exe还运行。此时还要注意编译优化,可以将“高级优化”的拥有勾打上,速度可提升20%横。

 

五、使用DIBSection和仿指针

  虽然发GetDIBits/SetDIBits函数,但是DIB与GDI位图之间的数据交换还是特别无便于,特别处理过程中需调用GDI函数来拍卖的时刻。而且不怕你虽累,但这么做的拍卖效率特别没有。所以Windows为咱提供了DIBSection。DIBSection是同样种植异常的DIB,它除了可像DIB一样一直指向各类图数据所占内存进行操作,它还可选入DC、能因此GDI函数绘制,非常灵活。但在VB下使用DIBSection还是发出不便的,因为用CreateDIBSection创建DIBSection时,得到的是各类图数据的地方,而VB没有指针。

 

  所幸在VB下可以使用SafeArray结构的数组模拟指针。关于模拟指针的原理、方法,网上的资料多之凡,比如AdamBear的文章“VB真是想不交千家万户的四:VB指针葵花宝典之SafeArray”。但这些章都仅仅是摆一般性的使,不可知像真的的指针一样自由改变地址(他们还是利用CopyMemory改的)。而于图像处理面临,由于触及运算的屡屡,“像真正的指针一样自由更改地址”的效用非常重要。

 

  其实“像真的的指针一样随便更改地址”并没技术难度(对于早已学会模拟指针的人来说),就扣留想获取不:再就此一个数组(设pDataPtr)控制模拟指针(设pData)的地方,这样可就此pDataPtr控制地方,用pData访问数。

 

  由于要建立两个拟指针,导致代码写起来比麻烦,于是自己思念写个“模拟指针代码生成器”(在(ImgTest.zip的)MakeSAPtr目录中)。虽然模拟指针建立艺术发生成百上千种,但是多需要现变量来保存地址,不入批量变化,所以自己只有改化这种办法(指“模拟指针代码生成器”自动生成的那种)。这种艺术或者对
通过看AdamBear的篇章学模拟指针的人
会导致困惑,这是为AdamBear在认证VarPtrArray返回的价是SafeArray的地址之地址时不曾提全:VarPtrArray返回的值

VB存储数组信息之变量的地址,可通过转移该变量的值如果数组用另一个SafeArray。

 

  现在来拘禁VB_DIB_Ptr:
  1.为演示DIBSection能够如HBITMAP一样,我于Form_Load中开创了DC、将DIBSection选入DC。同时为了释放,Form_UnLoad中描写了自由代码。
  2.在DrawIt中,注意处理局部的代码并没有跟VB_DIB差多少,只不过把索引计算改为地方运算而已。

 

五、使用DIBSection和拟指针

  虽然发出GetDIBits/SetDIBits函数,但是DIB与GDI位图之间的数据交换还是十分不便民,特别处理过程中得调用GDI函数来处理的当儿。而且就你就算累,但这么做的拍卖效率非常没有。所以Windows为咱提供了DIBSection。DIBSection是一模一样栽特殊之DIB,它除了可像DIB一样直接对各类图数据所占用内存进行操作,它还得选入DC、能因此GDI函数绘制,非常灵活。但以VB下行使DIBSection还是有诸多不便的,因为用CreateDIBSection创建DIBSection时,得到的凡个图数据的地方,而VB没有指针。

 

  所幸以VB下得以SafeArray结构的数组模拟指针。关于模拟指针的规律、方法,网上的材料多的凡,比如AdamBear的文章“VB真是怀念不至鳞次栉比的四:VB指针葵花宝典之SafeArray”。但这些文章都仅仅是说道一般性的施用,不能够如真正的指针一样随便变更地址(他们还是利用CopyMemory改的)。而于图像处理中,由于触及运算的往往,“像真的的指针一样随便变更地址”的效力特别重大。

 

  其实“像真正的指针一样随便改动地址”并从未技术难度(对于曾经学会模拟指针的人头的话),就扣留想博得非:直接将一个动态数组(设pByte)指向一个SAFEARRAY结构体变量(设pBytePtr)。模拟指针模块的代码在mPoint.bas。

 

  现在来拘禁4_DIB_Ptr:

vb6/4_DIB_Ptr/FrmMain.frm中DrawIt
'绘制
Private Sub DrawIt()
    Dim I As Long, J As Long
    Static K As Long
    Dim pByte() As Byte, pBytePtr As SAFEARRAY1D
    Dim iLinePtr As Long

    ' check Image
    Debug.Assert m_pDIB <> 0

    '建立模拟指针
    MakePoint VarPtrArray(pByte), pBytePtr, 1

    Ptr(pBytePtr) = m_pDIB + (m_BI.biHeight - 1) * m_LineBytes 'DIB是逆序存储的
    iLinePtr = pBytePtr.pvData
    For I = 0 To ImgHeight - 1 'Y
        pBytePtr.pvData = iLinePtr
        For J = 0 To ImgWidth - 1 'X
            'PicView.PSet (J, I), RGB(J And &HFF, I And &HFF, (J + K) And &HFF)
            pByte(2) = J And &HFF       'Red
            pByte(1) = I And &HFF       'Green
            pByte(0) = (J + K) And &HFF 'Blue
            pBytePtr.pvData = pBytePtr.pvData + 3 '24位
        Next J
        iLinePtr = iLinePtr - m_LineBytes
    Next I

    '释放模拟指针
    FreePoint VarPtrArray(pByte)

    K = (K + 1) And &HFF

End Sub

  1.为了演示DIBSection能够像HBITMAP一样,我在Form_Load中开创了DC、将DIBSection选入DC。同时为了释放,Form_UnLoad中描写了释放代码。
  2.每当DrawIt中,注意处理部分的代码并没有同VB_DIB差多少,只不过把索引计算改为地方运算而已。

 

  再来比较vc的代码,感觉跟真正的指针用法差不多嘛:

vc/ImgTestDlg.cpp中CImgTestDlg::DrawIt
void CImgTestDlg::DrawIt() 
{
    int i=0,j=0;
    static int k=0;
    BYTE *pByte, *pLinePtr;

    pLinePtr = (BYTE*)pDIB + (bi.biHeight-1)*LineBytes;
    for(i=0; i<IMGHEIGHT; i++)
    {
        pByte = pLinePtr;
        for(j=0; j<IMGWIDTH; j++)
        {
            pByte[2] = j & 0xff;
            pByte[1] = i & 0xff;
            pByte[0] = (j+k) & 0xff;
            pByte = pByte + 3;
        }
        pLinePtr = pLinePtr - LineBytes;
    }

    k = (k+1) & 0xff;

}

六、结合DirectX

  以GDI中,我们好据此DIB直接操作图像数据,那么号称能够直接访问显存的DirectX呢?

 

  一查DirectX
SDK,发现IDirectDrawSurface接口的Lock函数可以锁定表面,从而直接访问该位图数据。再以VB的对象浏览器中精心察看“DirectX
7 for Visual Basic Type Library”,发现DirectDrawSurface7对象啊有该措施。

 

  看看5_DX7Ptr:

vb6/5_DX7Ptr/FrmMain.frm中Render
'渲染
Private Sub Render()
    Dim I As Long, J As Long
    Static K As Long
    Dim ddsdInfo As DDSURFACEDESC2
    Dim IsOK As Boolean
    Dim cbPitch As Long
    Dim cbPixel As Long
    Dim iIdxR As Long
    Dim iIdxG As Long
    Dim iIdxB As Long
    Dim iMaxX As Long, iMaxY As Long
    Dim pByte() As Byte, pBytePtr As SAFEARRAY1D
    Dim iLinePtr As Long

    ' check Image
    'Debug.Assert m_pDIB <> 0
    Debug.Assert Not m_ddsRender Is Nothing

    ' Main
    With m_ddsRender
        'Render
        Call .Lock(m_rctSurf, ddsdInfo, DDLOCK_SURFACEMEMORYPTR Or DDLOCK_WRITEONLY Or DDLOCK_NOSYSLOCK Or DDLOCK_WAIT, 0)
        IsOK = CheckPixelFormat(ddsdInfo.ddpfPixelFormat)
        If IsOK Then
            With ddsdInfo
                Debug.Assert .lpSurface
                cbPitch = .lPitch
                With .ddpfPixelFormat
                    cbPixel = (.lRGBBitCount) / 8
                    iIdxR = MaskToRShift(.lRBitMask) / 8
                    iIdxG = MaskToRShift(.lGBitMask) / 8
                    iIdxB = MaskToRShift(.lBBitMask) / 8
                End With
                iMaxX = .lWidth - 1
                iMaxY = .lHeight - 1
            End With

            '建立模拟指针
            MakePoint VarPtrArray(pByte), pBytePtr, 1

            Ptr(pBytePtr) = ddsdInfo.lpSurface
            iLinePtr = pBytePtr.pvData
            For I = 0 To iMaxY 'Y
                pBytePtr.pvData = iLinePtr
                For J = 0 To iMaxX 'X
                    'PicView.PSet (J, I), RGB(J And &HFF, I And &HFF, (J + K) And &HFF)
                    pByte(iIdxR) = J And &HFF       'Red
                    pByte(iIdxG) = I And &HFF       'Green
                    pByte(iIdxB) = (J + K) And &HFF 'Blue
                    pBytePtr.pvData = pBytePtr.pvData + cbPixel '下一个像素
                Next J
                iLinePtr = iLinePtr + cbPitch '下一个扫描行
            Next I

            '释放模拟指针
            FreePoint VarPtrArray(pByte)

        End If
        Call .Unlock(m_rctSurf)

        'Error Pixel Format
        If IsOK = False Then
            Call .BltColorFill(m_rctSurf, vbBlack)
            Call .SetForeColor(vbWhite)
            Call .DrawText(0, &H20, "Error Pixel Format!", False)
        End If

    End With

    K = (K + 1) And &HFF

End Sub

  1.由于硬件装置性能差,所以不用期待像DIB那样可以确认RGB字节顺序。应该因Lock方法传回之DDSURFACEDESC2结构来确认RGB字节顺序(iIdxR、iIdxG、iIdxB)、像从所占据字节(cbPixel)及宽距(cbPitch)。
  2.是因为我们来矣仿指针技术,所以就段代码和跟先前4_DIB_Ptr差不多,特别是和当VC中应用IDirectDrawSurface::Lock的处理代码差不多。

  仔细观察对象浏览器的人口会晤发现,DirectDrawSurface7对象GetLockedArray可以拿走锁定后底位图数据:

vb6/6_DX7Arr/FrmMain.frm中Render
'渲染
Private Sub Render()
    Dim I As Long, J As Long
    Static K As Long
    Dim ddsdInfo As DDSURFACEDESC2
    Dim IsOK As Boolean
    Dim cbPitch As Long
    Dim cbPixel As Long
    Dim iIdxR As Long
    Dim iIdxG As Long
    Dim iIdxB As Long
    Dim iMaxX As Long, iMaxY As Long
    Dim pByte() As Byte
    Dim iCurPtr As Long

    ' check Image
    'Debug.Assert m_pDIB <> 0
    Debug.Assert Not m_ddsRender Is Nothing

    ' Main
    With m_ddsRender
        'Render
        Call .Lock(m_rctSurf, ddsdInfo, DDLOCK_SURFACEMEMORYPTR Or DDLOCK_WRITEONLY Or DDLOCK_NOSYSLOCK Or DDLOCK_WAIT, 0)
        IsOK = CheckPixelFormat(ddsdInfo.ddpfPixelFormat)
        If IsOK Then
            With ddsdInfo
                Debug.Assert .lpSurface
                cbPitch = .lPitch
                With .ddpfPixelFormat
                    cbPixel = (.lRGBBitCount) / 8
                    iIdxR = MaskToRShift(.lRBitMask) / 8
                    iIdxG = MaskToRShift(.lGBitMask) / 8
                    iIdxB = MaskToRShift(.lBBitMask) / 8
                End With
                iMaxX = .lWidth - 1
                iMaxY = .lHeight - 1
            End With

            Call .GetLockedArray(pByte)

            For I = 0 To iMaxY 'Y
                iCurPtr = 0
                For J = 0 To iMaxX 'X
                    'PicView.PSet (J, I), RGB(J And &HFF, I And &HFF, (J + K) And &HFF)
                    pByte(iCurPtr + iIdxR, I) = J And &HFF      'Red
                    pByte(iCurPtr + iIdxG, I) = I And &HFF      'Green
                    pByte(iCurPtr + iIdxB, I) = (J + K) And &HFF 'Blue
                    iCurPtr = iCurPtr + cbPixel '下一个像素
                Next J
            Next I

        End If
        Call .Unlock(m_rctSurf)

        'Error Pixel Format
        If IsOK = False Then
            Call .BltColorFill(m_rctSurf, vbBlack)
            Call .SetForeColor(vbWhite)
            Call .DrawText(0, &H20, "Error Pixel Format!", False)
        End If

    End With

    K = (K + 1) And &HFF

End Sub

  这个就算是官方推荐做法,使用一个二维数组来拍卖各项图数据。但是就算是以其利用的凡二维数组,所以它们比较同等维数组的学指针慢有。如果您不思用特殊技术(模拟指针),可以采取GetLockedArray。
  注意到当下点并未,GetLockedArray是一个方而非是一个属性,我们需要用数组变量传递过去,然后便可动用该数组直接操作各图数据了。啊哈!明白了GetLockedArray也是以模拟指针技术实现之,只不过它填充的凡2维之SAFEARRAY结构而已。

  注意:只操作位于系统内存的表,千万别操作对显存中的标。这是因CPU看显存比返问内存要慢许多!这个提议并无是绝的,如果对拖欠表的Blt的调用次数多跳自己写的图像处理操作的话,可以以欠表在显存,或者是于内存中计算好后再也一次性交给至显存。
  本程序建立图像处理操作的外部的代码:

vb6/5_DX7Ptr/FrmMain.frm中CreateSurfaces
    ' init Image
    With ddsdInfo
        .lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH Or DDSD_PIXELFORMAT
        With .ddsCaps
            .lCaps = DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_SYSTEMMEMORY 'CPU访问内存比访问显存快
        End With
        .lWidth = ImgWidth
        .lHeight = ImgHeight
        .ddpfPixelFormat = m_ddsdInfo.ddpfPixelFormat
    End With
    Set m_ddsRender = m_dxDraw.CreateSurface(ddsdInfo)

(全文完)

无知道怎么上污染文书,下载请到这里:
http://blog.gameres.com/thread.asp?BlogID=2143&threadid=55903

相关文章

Your Comments

近期评论

    功能


    网站地图xml地图