一直有人抱怨VB程序速度慢,它应用位映射存款和储蓄格式

用VB写高效的图像处理程序 V二.0(200陆-5-贰4)

BMP(全称Bitmap)是Window操作系统中的标准图像文件格式,能够分成两类:设备相关位图(DDB)和设备非亲非故位图(DIB),使用13分广。它应用位映射存款和储蓄格式,除了图像深度可选以外,不选用任何任何压缩,因此,BMP文件所占据的半空中十分的大。BMP文件的图像深度可选lbit、四bit、八bit及二4bit。BMP文件存款和储蓄数据时,图像的围观格局是按从左到右、从下到上的逐条。由于BMP文件格式是Windows环境中交流与图有关的多寡的一种标准,由此在Windows环境中运转的图形图像软件都帮衬BMP图像格式。

作者:zyl910

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

1、为啥那样慢?

  自盘古真人开天地以来(好像夸张了点),一贯有人抱怨VB程序速度慢。尤其是图像处理,被认为是VB的禁区。说到来也是,市面上的关于VB的图像处理的数量都是先讲计算公式,再一向用PSet(或API函数SetPixel)逐点画(至少本身见过的书都以那般)。效果是办到了,但速度慢得不可相信:对壹幅640*480的图像举行半透明合并就供给十分钟;而在PhotoShop中,只要一设置图层的透明度,半透明效果立刻显现。难怪有人说VB的扯淡。

 

  但那并不表示VB无法写高速的图像处理程序,速度慢是因为未有利用正确的方法。

 

  从VB5上马,能以本机代码编写翻译成exe文件,所以不设有代码执行速度的题材。那么,是如何拖慢了快慢吗?正是PSet和SetPixel!PSet把浮点形式的坐标转为像素单位,再交由SetPixel处理。而SetPixel呢,坐标系转化、剪裁区域判断、将颜色非常为装备支撑的最相仿的,最终还要依照分歧的颜料格式寻址、为将颜色写入其所在位进行位运算。经过这么多层处理,速度相当的慢才怪。

 

  那么,怎么样才能进步处理速度呢?使用DIB,直接对位图所在内部存款和储蓄器举行操作,速度能够大大提升。未来探访范例程序,这只是3个简便的色彩演示程序。

 

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结构的数组,而且模拟指针必要对多个数组进行操作,所以速度慢一点;
  三.真的差了70~100倍是VB_PSet和VB_SetPixel,特别是VB_PSet在Windows98下与VB_DIB差了145倍。

 

  以上可证,速度慢的原由是SetPixel非常的低效,而并不是VB的难点。即使VC的确实相比较快,不过本人写那篇小说不是为了研商速度极限(不然那篇小说会改名叫《怎样用汇编写高速的图像处理程序》),而是为了告知大家哪些在VB中写能够实时处理的图像处理程序。

 

目录 [hide]

一、为何那样慢?

  自盘古真人开天地以来(好像夸张了点),平素有人抱怨VB程序速度慢。特别是图像处理,被认为是VB的禁区。提起来也是,市面上的有关VB的图像处理的数额都以先讲总括公式,再一向用PSet(或API函数SetPixel)逐点画(至少我见过的书都以如此)。效果是办到了,但速度慢得离谱:对一幅640*480的图像举行半透明合并就须求十分钟;而在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结构的数组,须要在运作时动态修改数组数据地址,所以速度慢一点;
  三.真的差了70~100倍是1_PSet和2_SetPixelV。
  四.在VB
IDE中解释施行顺序非常慢,三_DIB就存在30倍的快慢差异。所以不时一些无聊的人拿
VC Debug编写翻译的主次 与 VB IDE中解释施行顺序 比较速度。
  5.4_DIB_Ptr、5_DX七Ptr速度一样,那是因为都以选拔模拟指针技术一直访问内部存款和储蓄器来做图像处理的。而陆_DX柒Arr使用的是GetLockedArray重回的贰维数组,贰维数组比壹维数组慢。

 

  以上可证,速度慢的由来是SetPixelV相当低效,而并不是VB的题材。就算VC的的确相比快,可是自个儿写那篇文章不是为着斟酌速度极限(不然那篇文章会改名叫《怎么着用汇编写高速的图像处理程序》),而是为了告诉我们哪些在VB中写能够实时处理的图像处理程序。

 

  同时,决定代码速度的不是编程语言或编写翻译器,而是算法。若是算法写得差的话,无论你用什么样编制程序语言或编写翻译器,那程序速度照旧极慢(你在VC中用SetPixelV写图像处理程序试试)。而后天的硬件配置已经够用好,用VB完全能够写高速的图像处理程序。

 

二、DIB的结构

  在 Windows 三.0
从前,Windows系统用的是DDB(设备有关位图)。DDB没有调色板,展现的颜料注重硬件,处理色彩很不便于。所以
Microsoft 在 Windows 三.0中 重新定义了BMP文件格式(Bmp四.0),使其支持设备非亲非故位图——也便是DIB。

 

  时至明天,BMP的版本号已升至伍.0(Windows NT 四.0、Windows九五 定义了 BMP四.0,Windows 玖八、Windows 2000 定义了 BMP 伍.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#

指令文件的大小,包含BITMAPFILEHEADE中华V

bfReserved1

保留,=0

bfReserved2

保留,=0

bfOffBits#

从文件头到位图数据的偏移字节数

文件新闻头——BITMAPINFOHEADEPAJERO

原型定义:

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

BITMAPINFOHEADEKuga结构的轻重缓急。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 伍.0)
   1:单色位图
   4:16色位图
   8:256色位图
  1陆:增强色位图,私下认可为55五格式
  贰肆:真彩色位图
  32:三十四个人位图,暗许情形下Windows不会处理最高6位,可以将它看做协调的Alpha通道

biCompression

减去方式
  BI_RGB:无压缩
  BI_瑞虎LE八:行程编码压缩,biBitCount必须等于捌
  BI_EvoqueLE4:行程编码压缩,biBitCount必须等于四
  BI_BITFIELDS:钦点索罗德GB掩码,biBitCount必须等于1陆、3贰
  BI_JPEG:JPEG压缩(BMP 5.0)
  BI_PNG:PNG压缩(BMP 5.0)

biSizeImage#

其实的位图数据所占字节(biCompression=BI_QashqaiGB时能够简简单单)

biXPelsPerMeter#

对象设备的水准分辨率,单位是每米的像素个数

biYPelsPerMeter#

指标设备的垂直分辨率,单位是每米的像素个数

biClrUsed#

利用的颜色数(当biBitCount等于壹、四、捌时才有效)。假诺该项为0,表示颜色数为贰^biBitCount

biClrImportant#

重大的颜色数。要是该项为0,表示全数颜色都以非同平常的

调色板
  唯有biBitCount等于一、四、8时才有调色板。调色板实际上是1个数组,元素的个数由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

位图数据

◆扫描行:
  1行的图像数据叫做一个扫描行。3个扫描行的长度必须是四的翻番(字节),要是或不是,则需求补齐。总结公式:LineBytes=((biWidth*biBitCount+31)And
&HFFFFFFE0)/8
  由于BMP设定者认为数学坐标系更总要,所以DIB的扫描行是逆序存款和储蓄的(相对于显示器坐标系而言),即显示器上的第2行是DIB位图数据的末梢1行。

◆1位色:
  用1人表示2个像素,所以2个字节能够象征九个像素。坐标是从最右边(最高位)初叶的,而不是相似情状下的最低位。在内部存款和储蓄器的安插格局如下:

字节

0

7

6

5

4

3

2

1

0

像素

0

1

2

3

4

5

6

7

◆4位色:
  用几人表示三个像素,所以3个字节能够表示1个像素。坐标是从最左边(最高位)起初的,而不是一般景色下的最低位。在内部存款和储蓄器的布阵情势如下:

字节

0

7

6

5

4

3

2

1

0

像素

0

1

像素位

3

2

1

0

3

2

1

0

◆8位色:
  用5位代表1个像素,所以一个字节刚好只可以表示叁个像素。在内部存款和储蓄器的布阵格局如下:

字节

0

1

像素

0

1

◆16位色:
  用拾肆人代表一个像素,所以多少个字节可以代表3个像素。暗许意况下十六人DIB是55伍格式,最高位无效(那对VB是个福音,因为VB未有十几个人无符号型)。在内部存款和储蓄器的安放格局如下(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位色:
  用二十五人代表3个像素,所以四个字节能够象征2个像素。注意它的11是BGTucson,而不是古板的安德拉GB。在内存的布署方式如下:

字节

0

1

2

3

4

5

像素

0

1

RGB

B

G

R

B

G

R

◆32位色:
  用312人表示四个像素,所以八个字节能够代表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 三.0
之前,Windows系统用的是DDB(设备有关位图)。DDB未有调色板,展现的颜色重视硬件,处理色彩很不便于。所以
Microsoft 在 Windows 叁.0中 重新定义了BMP文件格式(BMP4.0),使其支持装备非亲非故位图——也正是DIB。

 

  时至今天,BMP的版本号已升至伍.0(Windows NT 4.0、Windows95 定义了 BMP伍.0,Windows 玖八、Windows 两千 定义了 BMP 伍.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#

指令文件的尺寸,包涵BITMAPFILEHEADE猎豹CS6

bfReserved1

保留,=0

bfReserved2

保留,=0

bfOffBits#

从文件头到位图数据的偏移字节数

文本音信头——BITMAPINFOHEADELX570

原型定义:

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

BITMAPINFOHEADE奥迪Q7结构的深浅。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 五.0)
   一:单色位图
   4:16色位图
   8:256色位图
  1陆:增强色位图,私下认可为555格式
  二四:真彩色位图
  3二:三11个人位图,暗中同意景况下Windows不会处理最高6人,可以将它看作协调的Alpha通道

biCompression

调整和减弱格局
  BI_RGB:无压缩
  BI_大切诺基LE八:行程编码压缩,biBitCount必须等于八
  BI_SportageLE四:行程编码压缩,biBitCount必须等于肆
  BI_BITFIELDS:钦赐库罗德GB掩码,biBitCount必须等于1陆、32
  BI_JPEG:JPEG压缩(BMP 5.0)
  BI_PNG:PNG压缩(BMP 5.0)

biSizeImage#

实质上的位图数据所占字节(biCompression=BI_OdysseyGB时能够总结)

biXPelsPerMeter#

指标设备的品位分辨率,单位是每米的像素个数

biYPelsPerMeter#

对象设备的垂直分辨率,单位是每米的像素个数

biClrUsed#

使用的颜色数(当biBitCount等于1、四、捌时才有效)。若是该项为0,表示颜色数为2^biBitCount

biClrImportant#

重在的颜色数。假诺该项为0,表示全数颜色都以重点的

调色板
  唯有biBitCount等于1、四、捌时才有调色板。调色板实际上是多少个数组,成分的个数由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

位图数据

◆扫描行:
  一行的图像数据叫做五个扫描行。三个扫描行的尺寸必须是四的倍数(字节),若是或不是,则需求补齐。总括公式:LineBytes=((biWidth*biBitCount+31)And
&HFFFFFFE0)/8
  由于BMP设定者认为数学坐标系更总要,所以DIB的扫描行是逆序存款和储蓄的(绝对于显示屏坐标系而言),即荧屏上的首先行是DIB位图数据的终极1行。

◆1位色:
  用一个人表示几个像素,所以三个字节能够表示几个像素。坐标是从最左侧(最高位)起先的,而不是一般景观下的最低位。在内部存款和储蓄器的布阵情势如下:

字节

0

7

6

5

4

3

2

1

0

像素

0

1

2

3

4

5

6

7

◆4位色:
  用2人表示1个像素,所以贰个字节能够代表二个像素。坐标是从最左边(最高位)开始的,而不是形似景况下的最低位。在内部存款和储蓄器的安放情势如下:

字节

0

7

6

5

4

3

2

1

0

像素

0

1

像素位

3

2

1

0

3

2

1

0

◆8位色:
  用伍人代表叁个像素,所以贰个字节刚好只可以表示八个像素。在内部存款和储蓄器的安置方式如下:

字节

0

1

像素

0

1

◆16位色:
  用二十一人表示三个像素,所以七个字节可以象征3个像素。暗中同意情形下十陆个人DIB是55伍格式,最高位无效(那对VB是个福音,因为VB未有拾4人无符号型)。在内部存款和储蓄器的布置格局如下(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位色:
  用二二位代表一个像素,所以七个字节能够象征二个像素。注意它的相继是BG卡宴,而不是观念的奥德赛GB。在内部存款和储蓄器的布阵形式如下:

字节

0

1

2

3

4

5

像素

0

1

RGB

B

G

R

B

G

R

◆32位色:
  用3一个人表示1个像素,所以多少个字节能够代表2个像素。注意绝大部分的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

说明:

将壹幅与设备非亲非故位图的全部或局地数据直接复制到三个装置。这么些函数在装置中定义了1个对象矩形,以便接受位图数据。它也在DIB中定义了二个源矩形,以便从中提取数额

返回值:

如函数执行成功,重临欲复制的扫描线的数量;如重返常数GDI_E福特ExplorerRO宝马X5,表示出错

参数:

hDC

四个配备场景的句柄。这一场景用于吸收接纳位图数据

XDest

钦赐绘制区域的左上角X坐标

YDest

钦定绘制区域的左上角Y坐标

dwWidth

钦定绘制区域的中度

dwHeight

钦定绘制区域的幅度

XSrc

矩形在DIB中的起源X坐标

YSrc

矩形在DIB中的源点Y坐标

uStartScan

lpvBits中首先条扫描线的号子。如lpbmi之BITMAPINFOHEADE帕杰罗部分的biHeight字段是正数,那么那条扫描线就会从位图的平底发轫估算;若是是负数,就从顶部开首总结

cScanLines

欲复制的扫描线数量

lpvBits

本着一个缓冲区的指针。那一个缓冲区包蕴了以DIB格式描述的位图数据;那种格式是由lpbmi钦点的

lpbmi

指向BITMAPINFO(为包容Bmp3/5而注解成Any),对DIB的格式和颜色举行描述的2个布局

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

说明:

听闻一幅与装备非亲非故的位图创制1幅与装备有关的位图

返回值:

推行成功重临位图句柄,零表示退步

参数:

hDC

贰个设施场景的句柄,该设施场景定义了要创立的与设施有关位图的计划新闻

XDest

点名绘制区域的左上角X坐标

YDest

点名绘制区域的左上角Y坐标

nDestWidth

点名绘制区域的莫斯中国科学技术大学学

nDestHeight

点名绘制区域的增长幅度

XSrc

矩形在DIB中的起源X坐标

YSrc

矩形在DIB中的起源Y坐标

nSrcWidth

点名原位图绘制区域的左上角X坐标

nSrcHeight

钦赐原位图绘制区域的左上角Y坐标

lpBits

针对三个缓冲区的指针。这些缓冲区包涵了以DIB格式描述的位图数据;那种格式是由lpBitsInfo钦定的

lpBitsInfo

指向BITMAPINFO(为包容BMP五分三而注脚成Any),对DIB的格式和颜料举办描述的1个组织

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

BITMAPINFOHEADERAV四(为包容Bmp5/5而注解成Any),对DIB的格式实行描述的2个协会

fdwInit

如不应对位图数据举办起先化,那么设为零。如设为CBM_INIT,表示依据lpbInit和
lpbmi参数对位图实行先河化

lpbInit

本着多少个缓冲区的指针。那个缓冲区包涵了以DIB格式描述的位图数据;那种格式是由lpbmi钦命的

lpbmi

指向BITMAPINFO(为包容Bmp3/伍而申明成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),然后重回3个GDI位图的句柄。它提供了DIB和GDI位图的最佳的特色。那样我们可以直接待上访问DIB的内部存款和储蓄器,能够选取位图句柄和内部存款和储蓄器设备条件,大家竟然还可以在DIB中调用GDI函数来绘图

返回值:

履行成功重返DIBSection位图的句柄,零象征战败。会设置GetLastError

参数:

hDC

二个设施场景的句柄。如dw设为DIB_PAL_COLOGL450S,那么DIB颜色表就会用来自逻辑调色板的颜料进行初始化

lpbmi

指向BITMAPINFO(为包容BMP十分六而注解成Any),这些协会起头化成欲成立的那幅位图的布局数据

iUsage

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

ppvBits

用于获取DIBSection数据区的内部存款和储蓄器地址

hSection

针对1个文书映射对象的可选句柄,位图将在里面成立。如设为零,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的格式进行控制,能够制定颜色的位数,而且能够内定是或不是进行削减。假使选择了压缩方式,则必须调用该函数五遍,3遍为了获得所需内部存款和储蓄器,其它1遍为了得到位图数据

返回值:

实践成功则赶回扫描线的数据,零表示失利。会安装GetLastError

参数:

hDC

概念了与设备有关位图hBitmap的配置消息的三个设备场景的句柄

hbmp

源位图的句柄

uStartScan

欲复制到DIB中的第3条扫描线的号码

cScanLines

欲复制的扫描线数量

lpvBits

针对3个缓冲区的指针。那么些缓冲区包蕴了以DIB格式描述的位图数据;那种格式是由lpbmi钦赐的

lpbmi

指向BITMAPINFO(为包容Bmp3/5而声明成Any).对DIB的格式及颜色进行认证的二个布局。在BITMAPINFOHEADE帕杰罗结构中,从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

说明:

未来自与设施非亲非故位图的2进制位复制到1幅与设施有关的位图里

返回值:

推行成功则赶回扫描线的数码,零表示失利。会安装GetLastError

参数:

hDC

概念了与设备有关位图hBitmap的配备新闻的二个设备场景的句柄

hbmp

源位图的句柄

uStartScan

欲复制到DIB中的第二条扫描线的数码

cScanLines

欲复制的扫描线数量

lpvBits

针对3个缓冲区的指针。那个缓冲区蕴含了以DIB格式描述的位图数据;那种格式是由lpbmi钦赐的

lpbmi

指向BITMAPINFO(为包容BMP5/五而申明成Any).对DIB的格式及颜色举办说明的二个构造。在BITMAPINFOHEADE奇骏结构中,从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

以此布局数组用于装载颜色表音讯的第1个条款

文件格式

三、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

说明:

将1幅与设施无关位图的总体或部分数据直接复制到2个配备。那几个函数在装备中定义了2个目的矩形,以便接受位图数据。它也在DIB中定义了一个源矩形,以便从中提取数据

返回值:

如函数执行成功,再次来到欲复制的扫描线的多寡;如再次回到常数GDI_E奥迪Q三RO君越,表示出错

参数:

hDC

2个设施场景的句柄。该现象用于吸纳位图数据

XDest

点名绘制区域的左上角X坐标

YDest

钦命绘制区域的左上角Y坐标

dwWidth

内定绘制区域的莫斯中国科学技术大学学

dwHeight

钦点绘制区域的肥瘦

XSrc

矩形在DIB中的起源X坐标

YSrc

矩形在DIB中的起源Y坐标

uStartScan

lpvBits中率先条扫描线的号码。如lpbmi之BITMAPINFOHEADEXC90部分的biHeight字段是正数,那么那条扫描线就会从位图的最底层伊始总结;假设是负数,就从顶部始发盘算

cScanLines

欲复制的扫描线数量

lpvBits

针对四个缓冲区的指针。那个缓冲区包含了以DIB格式描述的位图数据;那种格式是由lpbmi钦点的

lpbmi

指向BITMAPINFO(为兼容Bmp3/5而评释成Any),对DIB的格式和颜料实行描述的2个布局

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(为包容BMP百分之陆十而注明成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

说明:

将1幅与设施毫不相关位图的全体或部分数据直接复制到多少个配备。那个函数在装备中定义了二个目的矩形,以便接受位图数据。它也在DIB中定义了贰个源矩形,以便从中提取数据

返回值:

施行成功则赶回扫描线的多少,零意味着退步。会安装GetLastError

参数:

hDC

一个配备场景的句柄。这场景用于吸收接纳位图数据

lpbmih

BITMAPINFOHEADE本田UR-V(为兼容Bmp八成而注脚成Any),对DIB的格式举行描述的三个构造

fdwInit

如不应对位图数据举行开始化,那么设为零。如设为CBM_INIT,表示依据lpbInit和
lpbmi参数对位图实行伊始化

lpbInit

针对一个缓冲区的指针。这几个缓冲区包括了以DIB格式描述的位图数据;那种格式是由lpbmi钦定的

lpbmi

指向BITMAPINFO(为包容Bmp3/伍而表明成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),然后回到2个GDI位图的句柄。它提供了DIB和GDI位图的最棒的特点。那样我们可以直接待上访问DIB的内部存款和储蓄器,能够选拔位图句柄和内部存款和储蓄器设备条件,我们依旧还是能够在DIB中调用GDI函数来绘图

返回值:

推行成功重临DIBSection位图的句柄,零代表失利。会设置GetLastError

参数:

hDC

3个装置场景的句柄。如dw设为DIB_PAL_COLO索罗德S,那么DIB颜色表就会用来自逻辑调色板的水彩进行伊始化

lpbmi

指向BITMAPINFO(为包容BMP5/伍而申明成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的格式举行支配,可以制定颜色的位数,而且能够钦定是还是不是实行压缩。若是使用了压缩格局,则必须调用该函数两遍,三遍为了取得所需内部存款和储蓄器,其余2次为了得到位图数据

返回值:

施行成功则赶回扫描线的多寡,零象征战败。会安装GetLastError

参数:

hDC

概念了与装备有关位图hBitmap的安插消息的二个装置场景的句柄

hbmp

源位图的句柄

uStartScan

欲复制到DIB中的第壹条扫描线的号码

cScanLines

欲复制的扫描线数量

lpvBits

针对一个缓冲区的指针。那个缓冲区包蕴了以DIB格式描述的位图数据;那种格式是由lpbmi钦定的

lpbmi

指向BITMAPINFO(为包容Bmp3/伍而注脚成Any).对DIB的格式及颜色举行认证的两个布局。在BITMAPINFOHEADEENCORE结构中,从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的布置新闻的2个配备场景的句柄

hbmp

源位图的句柄

uStartScan

欲复制到DIB中的第三条扫描线的数码

cScanLines

欲复制的扫描线数量

lpvBits

针对三个缓冲区的指针。那么些缓冲区包罗了以DIB格式描述的位图数据;那种格式是由lpbmi钦定的

lpbmi

指向BITMAPINFO(为兼容Bmp五分之四而注明成Any).对DIB的格式及颜色实行表达的四个组织。在BITMAPINFOHEADE福特Explorer结构中,从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

已选入了1个DIBSection对象的配备场景

uStartIndex

颜色表中欲取回的首先个条款的目录

cEntries

欲取回的条规数量

pColors

以此组织数组用于装载颜色表消息的第贰个条文

四、实战练兵

  用DIB写图像处理程序的时候,首先要分飞鹤点:DIB并不是图像处清理计算法,而是一种绘图方法。处清理计算法比DIB高一流,管理坐标和颜料的运算;而DIB只是为了绘制。所以那时处清理计算法的频率是速度的首要。

 

  利用DIB绘制图像并从未比用PSet/SetPixel绘制差多少,它只是把坐标运算改成地方运算而已。很三人领略指针是多少个高危的事物,正是因为它能一直访问内部存款和储蓄器,要是指针十分的大心指错地点的话,Windows即刻告诉一般敬爱性错误。所以,在地点运算的时候一定要小心,同时要注意每一日保存,因为这时的违法操作的爆发率万分高,不然辛费力苦写的代码1须臾间没了可别怪笔者没提醒啊。

 

  好了,今后初步!

 

  由于拍卖算法起指点意义,所以今后先讲解VB_PSet。全体的代码都在FrmMain.frm中。别的的进程的代码能够不看,今后将集中力集中在“DrawIt”中,它正是管绘制的。

 

  其实自个儿这几个演示程序蛮简单的:PRADO分量延着水平方向扩充,G分量延着垂直方向扩充,B分量则从右往左滚动。什么?!“And
&HFF”是何等看头?!那但是基础啊……(下略&HFFFF…字)。“&H”表示十6进制数,而And表示按位与。&HFF是2进制的“1111
111一”,正好覆盖了低七位,那时用And进行按位与,只会博得低六个人,与奥迪Q5GB分量须要的伍人刚刚适合(对于“(J

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

 

  If Not 看通晓了 Then Goto 前两段

 

  好!未来开拓VB_DIB。(由于2三个人能平素钦命PRADOGB分量,所以这边是用的是二二个人DIB)

 

  看了后面包车型大巴“DIB的组织”,是或不是有点昏呢?其实DIB也没怎么,就是3个揭橥位图新闻的BITMAPINFO结构 和
贰个囤积位图数据的数额缓冲区,顶多再用SetDIBitsToDevice绘制,所以VB_DIB与VB_PSet相比较只是多了SetDIBitsToDevice、BITMAPINFOHEADE悍马H二(22人DIB未有调色板,所以用BITMAPINFOHEADE昂科威就行)和部分常数的宣示而已。由于这么些演示程序不须求变更图像大小和色深,所以能够把关于变量作为窗体级变量,再在Form_Load中开始化。由于DIB并从未向系统报名财富(数组的内部存储器是VB分配的,会自动释放),所以不必要写释放代码。

 

  今后来看DrawIt。
  壹.虽说能够逐点把坐标映射成地址再写,可是如此效能太低了,能够应用坐标处理的一而再性举办优化。
  贰.由于自家那边用的是数组,所以那里用(数组成分)索引代替地址。
  三.最早先要留意DIB是逆序存储的,要将索引设为最终1行第3个像素的目录。
  4.由于DIB的CRUISERGB顺序是B、G、冠道,所以“MapData(CurIdx +
?)”的依次是二、一、0。
  5.设置好1个像素的颜料后,要留意把索引改为下个像素的目录。
  陆.由于DIB是逆序存款和储蓄的,移到下1个扫描行是“LineIdx = LineIdx –
LineBytes”

 


  “好了,代码看懂了,按F伍运转看看效果。”
  “咦?速度好像没快多少呀?”


  那是由于程序在VB环境下是以分解形式运转的,而解释格局对做图像处理所必要广泛循环和大度的算术运算的履行功用十分的低,所以要编译成(本机代码)exe再运营。此时还要小心编写翻译优化,能够把“高级优化”的装有勾打上,速度可提升伍分一左右。

 

格式组成

独立的BMP图像文件由4局部组成:

  • 位图头文件数据结构,它含有BMP图像文件的门类、突显内容等消息;
  • 位图音讯数据结构,它包罗有BMP图像的宽、高、压缩方法,以及定义颜色等音信;
  • 调色板,这么些片段是可选的,有些位图供给调色板,有个别位图,比如真彩色图(二二个人的BMP)就不须求调色板;
  • 位图数据,这部分的内容听闻BMP位图使用的位数不一致而分歧,在二十四个人图中央直机关接行使QX56GB,而任何的小于二十四个人的选拔调色板中颜色索引值。

肆、实战演练

  用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

  其实自身这些演示程序蛮简单的:Rubicon分量延着水平方向扩大,G分量延着垂直方向扩大,B分量则从右往左滚动。什么?!“And
&HFF”是怎么着看头?!那只是基础啊……(下略&HFFFF…字)。“&H”表示十六进制数,而And表示按位与。&HFF是二进制的“1111
111一”,正好覆盖了低六人,那时用And举行按位与,只会博得低七位,与奥德赛GB分量须要的7个人刚刚符合(对于“(J

  • K) And &HFF”来说,能够完结滚动作效果应)。

 

  If Not 看明白了 Then Goto 前两段

 

  好!今后打开叁_DIB。(由于二十三人能直接钦定PAJEROGB分量,所以那边是用的是二十三人DIB)

 

  看了前方的“DIB的组织”,是否有点昏呢?其实DIB也没怎么,就是二个表述位图新闻的BITMAPINFO结构 和
2个储存位图数据的数额缓冲区,顶多再用SetDIBitsToDevice绘制,所以3_DIB与1_PSet相比只是多了SetDIBitsToDevice、BITMAPINFOHEADE凯雷德(24人DIB未有调色板,所以用BITMAPINFOHEADE昂Cora就行)和局地常数的宣示而已。由于那么些演示程序不须求变更图像大小和色深,所以能够把关于变量作为窗体级变量,再在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

  一.尽管能够逐点把坐标映射成地址再写,但是这么效用太低了,能够使用坐标处理的一而再性实行优化。
  二.是因为自身这里用的是数组,所以那边用(数组成分)索引代替地址。
  叁.最初阶要留心DIB是逆序存款和储蓄的,要将索引设为尾声一行第三个像素的目录。
  4.由于DIB的RGB顺序是B、G、R,所以“m_MapData(CurIdx +
?)”的一一是二、一、0。
  5.设置好3个像素的颜料后,要留意把索引改为下个像素的目录。
  6.由于DIB是逆序存储的,移到下一个扫描行是“iLinePtr = iLinePtr –
m_LineBytes”

 


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


  那是出于程序在VB环境下是以表明形式运行的,而解释格局对做图像处理所急需广泛循环和大度的算术运算的实践功效相当低,所以要编写翻译成(本机代码)exe再运营。此时还要小心编写翻译优化,可以把“高级优化”的具备勾打上,速度可升级十分二左右。

 

5、使用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改的)。而在图像处理中,由于点运算的再叁,“像真的的指针1样随便改动地址”的效劳很关键。

 

  其实“像真的的指针一样自由改变地址”并未技术难度(对于曾经学会模拟指针的人来说),就看想博得不:再用多个数组(设pDataPtr)控制模拟指针(设pData)的地点,那样能够用pDataPtr控制地点,用pData访问数据。

 

  由于需求树立八个模拟指针,导致代码写起来相比较烦,于是作者想写个“模拟指针代码生成器”(在(ImgTest.zip的)MakeSAPtr目录中)。固然模拟指针建立艺术有成都百货上千种,然则大多须求暂且变量来保存地址,不吻合批量浮动,所以笔者只有改成那种方法(指“模拟指针代码生成器”自动生成的那种)。那种办法大概对
通过看AdamBear的篇章学模拟指针的人
会招致质疑,这是因为AdamBear在认证VarPtrArray再次回到的值是SafeArray的地方的地方时没讲全:VarPtrArray重回的值

VB存款和储蓄数组音讯的变量的地址,可通过改变该变量的值使数组用另一个SafeArray。

 

  以后来看VB_DIB_Ptr:
  一.为了演示DIBSection能够像HBITMAP1样,作者在Form_Load中开创了DC、将DIBSection选入DC。同时为了释放,Form_UnLoad中写了释放代码。
  贰.在DrawIt中,注意处理局地的代码并不曾与VB_DIB差多少,只可是把索引总结改为地点运算而已。

 

格式类型

位图壹共有二种档次,即:设备相关位图(DDB)和装置非亲非故位图(DIB)。DDB位图在最初的Windows系统(Windows
3.0此前)中是很普遍的,事实上它也是唯一的。但是,随着显示屏创建技能的上进,以及突显设备的多种化,DDB位图的有的本来的标题起首显示出来了。比如,它不可能存储(或然说获取)创立那张图片的本来设备的分辨率,那样,应用程序就无法高效的判定客户机的来得设备是不是适合呈现那张图纸。为了缓解那壹难题,微软成立了DIB位图格式。
设备非亲非故位图 (Device-Independent Bitmap)
DIB位图包罗下列的颜色和尺寸音信:

  • 原始设备(即创设图片的装置)的颜色格式。
  • 原来设备的分辨率。
  • 原有设备的调色板
  • 二个位数组,由红、绿、蓝(PRADOGB)四个值代表贰个像素。
  •  叁个数组压缩标志,用于表明数据的削减方案(假设需求的话)。

上述这个音信用保证存在BITMAPINFO结构中,该组织由BITMAPINFOHEADE福特Explorer结构和三个或更四个LX570GBQUAD结构所构成。BITMAPINFOHEADE福特Explorer结构所蕴藏的分子注脚了图像的尺寸、原始设备的水彩格式、以及数据压缩方案等音信。猎豹CS六GBQUAD结构标识了像素所用到的颜色数据。
DIB位图也有二种样式,即:底到上型DIB(bottom-up),和顶到下型DIB(top-down)。底到上型DIB的原点(origin)在图像的左下角,而顶到下型DIB的原点在图像的左上角。如果DIB的中度值(由BITMAPINFOHEADESportage结构中的biHeight成员标识)是多个正值,那么就标明这几个DIB是多少个底到上型DIB,即便中度值是三个负值,那么它正是二个顶到下型DIB。注意:顶到下型的DIB位图是无法被收缩的。
位图的水彩格式是通过颜色面板值(planes)和颜色位值(bitcount)计算得来的,颜色面板值永远是壹,而颜色位值则足以是一、四、八、1六、二四、32中间的三个。尽管它是一,则表示位图是一张单色位图(译者注:经常是黑白位图,唯有黑和白二种颜色,当然它也能够是随便二种钦点的颜料),若是它是4,则意味那是一张VGA位图,假若它是八、1陆、二肆、或是3二,则象征该位图是别的装备所发生的位图。倘使应用程序想赢得当前来得设备(或打字与印刷机)的水彩位值(或称位深度),可调用API函数GetDeviceCaps(),并将首个参数设为BITSPIXEL即可。

展现设备的分辨率是以每米几个像一直注明的,应用程序能够经过以下七个步骤来赢得展现设备或打印机的品位分辨率:

  • 调用GetDeviceCaps()函数,内定第3个参数为HOLX570ZRES。
  • 再度调用GetDeviceCaps()函数,钦命第四个参数为HO牧马人ZSIZE。
  • 用第多个再次来到值除以第叁个重回值。即:GetDeviceCaps(hDC,HOMuranoZRES)/GetDeviceCaps(hDC,HOLX570ZSIZE);

应用程序也能够行使相同的八个步骤来收获装备的垂直分辨率,分歧之处只是要将HOQX56ZRES替换为VESportageTRES,把HOLacrosseZSIZE替换为VECR-VTSIZE,即可。
调色板是被保存在叁个LX570GBQUAD结构的数组中,该组织提议了每壹种颜色的红、绿、蓝的重量值。位数组中的每一个索引都对应于1个调色板项(即三个纳瓦拉GBQUAD结构),应用程序将依据那种对应关系,将像素索引值转换为像素汉兰达GB值(真实的像素颜色)。应用程序也能够通过调用GetDeviceCaps()函数来取妥帖前来得设备的调色板尺寸(将该函数的第二个参数设为NUMCOLO奥德赛S即可)。
Win3二API匡助位数据的削减(只对8个人和三人的底到上型DIB位图)。压缩方法是接纳运营长度编码方案(MuranoLE),悍马H2LE使用四个字节来叙述贰个句法,第3个字节表示重复像素的个数,第2个字节表示重复像素的索引值。有关压缩位图的详细音信请参见对BITMAPINFOHEADE瑞虎结构的诠释。
应用程序能够从1个DDB位图创造出2个DIB位图,步骤是,先开头化一些必不可少的协会,然后再调用GetDIBits()函数。但是,有个别显得设备有不小概率不协助那几个函数,你能够经过调用GetDeviceCaps()函数来鲜明一下(GetDeviceCaps()函数在调用时钦命LANDC_DI_BITMAP作为RASTERCAPS的标志)。
应用程序能够用DIB去设置显示设备上的像素(译者注:也正是展现DIB),方法是调用SetDIBitsToDevice()函数或调用StretchDIBits()函数。同样,某些显得设备也有十分大大概不帮助上述那多个函数,那时你能够钦点PRADOC_DIBTODEV作为RASTEQX56CAPS标志,然后调用GetDeviceCaps()函数来判定该装置是或不是接济SetDIBitsToDevice()函数。也能够钦赐帕杰罗C_STRETCHDIB作为RASTETiggoCAPS标志来调用GetDeviceCaps()函数,来判断该设施是或不是援助StretchDIBits()函数。
万一应用程序只是要不难的来得1个已经存在的DIB位图,那么它1旦调用SetDIBitsToDevice()函数就可以。比如1个电子表格软件,它可以打开1个图形文件,在窗口中简易的调用SetDIBitsToDevice()函数,将图片展现在窗口中。但只要应用程序要双重的绘图位图的话,则应该使用BitBlt()函数,因为BitBlt()函数的施行进度要比SetDIBitsToDevice()函数快很多。
配备相关位图 (Device-Dependent Bitmaps)
配备相关位图(DDB)之所以今后还被系统支持,只是为着合营旧的Windows
3.0软件,假使程序员将来要付出多个与位图有关的次序,则应该尽大概利用或生成DIB格式的位图。
DDB位图是被五个单个结构BITMAP所描述,那一个结构的成员标明了该位图的幅度、高度、设备的颜色格式等消息。
DDB位图也有二种档次,即:可放任的(discardable)DDB和不得扬弃的(nondiscardable)DDB。可舍弃的DDB位图就是一种当系统内存贫乏,并且该位图也绝非被选入设备描述表(DC)的时候,系统就会把该DDB位图从内部存款和储蓄器中排除(即屏弃)。不可放任的DDB则是随便系统内部存款和储蓄器多少都不会被系统清除的DDB。API函数CreateDiscardableBitmap()函数可用来创立可遗弃位图。而函数CreateBitmap()、CreateCompatibleBitmap()、和CreateBitmapIndirect()可用于创制不可吐弃的位图。
应用程序可以透过二个DIB位图而创设多少个DDB位图,只要先初步化一些必需的布局,然后再调用CreateDIBitmap()函数就能够。借使在调用该函数时钦定了CBM_INIT标志,那么这一遍调用就相当于于先调用CreateCompatibleBitmap()创立当前设施格式的DDB位图,然后又调用SetDIBits()函数转换DIB格式到DDB格式。(只怕有个别设备并不援助SetDIBits()函数,你能够钦命安德拉C_DI_BITMAP作为RASTEPRADOCAPS的标志,然后调用GetDeviceCaps()函数来判定一下)。
对应数据结构

  • BMP文件组成

BMP文件由文件头、位图消息头、颜色新闻和图表数据四部分构成。

  • BMP文件头(14字节)

BMP文件头数据结构含有BMP文件的品种、文件大小和位图开端地点等新闻。
其结构定义如下:
typedef struct tagBITMAPFILEHEADER
{
WOLX570D bfType; // 位图像和文字件的品类,必须为BM(一-2字节)
DWOWranglerD bfSize; // 位图像和文字件的大小,以字节为单位(三-6字节)
WOTucsonD bfReserved一; // 位图像和文字件保留字,必须为0(7-捌字节)
WOEscortD bfReserved2; // 位图像和文字件保留字,必须为0(九-十字节)
DWORubiconD bfOffBits; // 位图数据的开始地点,以相对于位图(1壹-1四字节)
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;

  • 位图消息头(40字节)

BMP位图音信头数据用于申明位图的尺码等新闻。
typedef struct tagBITMAPINFOHEADER{
DWOBMWX五D biSize; // 本结构所占用字节数(15-1捌字节)
LONG biWidth; // 位图的大幅,以像素为单位(1九-22字节)
LONG biHeight; // 位图的莫斯中国科学技术大学学,以像素为单位(二三-二6字节)
WOSportageD biPlanes; // 指标设备的级别,必须为一(27-2八字节)
WOOdysseyD biBitCount;// 每种像素所需的位数,必须是1(双色),(2九-30字节)
// 4(16色),8(256色)或24(真彩色)之一
DWO冠道D biCompression; // 位图压缩类型,必须是
0(不收缩),(3壹-3肆字节)
// 1(BI_RubiconLE八压缩类型)或2(BI_猎豹CS陆LE四压缩类型)之一
DWOPRADOD biSizeImage; // 位图的深浅,以字节为单位(3五-3八字节)
LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(3九-42字节)
LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(肆三-4陆字节)
DWO福特ExplorerD biClrUsed;// 位图实际使用的颜色表中的颜色数(47-50字节)
DWOHighlanderD biClrImportant;// 位图显示进度中主要性的颜色数(5一-54字节)
} BITMAPINFOHEADER;

  • 颜色表

颜色表用于表明位图中的颜色,它有多少个表项,每二个表项是三个LX570GBQUAD类型的组织,定义一种颜色。XC90GBQUAD结构的概念如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;// 品绿的亮度(值范围为0-25伍)
BYTE rgbGreen; // 红色的亮度(值范围为0-25伍)
BYTE rgbRed; // 土黑的亮度(值范围为0-255)
BYTE rgbReserved;// 保留,必须为0
} RGBQUAD;
颜色表中GL450GBQUAD结构数据的个数有biBitCount来规定:
当biBitCount=1,4,8时,分别有2,16,256个表项;
当biBitCount=2四时,未有颜色表项。
位图新闻头和颜色表组成位图新闻,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADE奇骏 bmiHeader; // 位图消息头
RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;

  • 位图数据

位图数据记录了位图的每叁个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的四个像素值所占的字节数:
当biBitCount=一时,柒个像素占三个字节;
当biBitCount=4时,二个像素占三个字节;
当biBitCount=八时,2个像素占贰个字节;
当biBitCount=24时,二个像素占一个字节;
Windows规定3个扫描行所占的字节数必须是
四的倍数(即以long为单位),不足的以0填充,
biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) *
bi.biHeight;
现实数目举例:
如某BMP文件开头:
424D 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000
0100*1000 0300 0000 0090 0000 A00F 0000 A00F 0000 0000 0000 0000
0000*00F8 E007 1F00 0000*02F1 84F1 04F1 84F1 84F1 06F2 84F1 06F2 04F2
86F2 06F2 86F2 86F2 …. ….
读取方法

1 /*
2 功能:在图片的第50行画一条黑线
3 为简化代码,只支持24位色的图片
4 codeblocks下正确运行。VC下需要将二维数组img改为malloc动态分配。
5 */
6 #include
7 #include
8 typedef struct{
9 BYTE b;
10 BYTE g;
11 BYTE r;
12 }RGB;
13 int main( void )
14 {
15 BITMAPFILEHEADER fileHeader;
16 BITMAPINFOHEADER infoHeader;
17 FILE* pfin =fopen("原始图像.bmp","rb");
18 FILE* pfout = fopen( "修改后的图像.bmp" , "wb");
19 //Read the Bitmap file header;
20 fread(&fileHeader,sizeof(BITMAPFILEHEADER),1,pfin);
21 //Read the Bitmap info header;
22 fread(&infoHeader,sizeof(BITMAPINFOHEADER),1,pfin);
23 //为简化代码,只处理24位彩色
24 if( infoHeader.biBitCount == 24 )
25 {
26 int size = infoHeader.biWidth*infoHeader.biHeight;
27 RGB img[infoHeader.biHeight][infoHeader.biWidth];
28 fread( img , sizeof(RGB) , size , pfin );
29 //把第50行染成黑色
30 int i = 0;
31 for( ; i < infoHeader.biWidth ; i++ )
32 {
33 img[50][i].b =img[50][i].g=img[50][i].r= 0;
34 }
35 //将修改后的图片保存到文件
36 fwrite( &fileHeader , sizeof(fileHeader) , 1 , pfout );
37 fwrite( &infoHeader , sizeof(infoHeader) , 1 , pfout );
38 fwrite( img , sizeof(RGB) , size , pfout );
39 }
40 }

伍、使用DIBSection和模仿指针

  就算有GetDIBits/SetDIBits函数,不过DIB与GDI位图之间的数据沟通依旧很不便利,尤其处理进度中要求调用GDI函数来处理的时候。而且正是你即便麻烦,但如此做的处理功效非常的低。所以Windows为大家提供了DIBSection。DIBSection是一种特殊的DIB,它除了可以像DIB1样一向对位图数据所占内部存款和储蓄器举办操作,它还是可以选入DC、能用GDI函数绘制,十三分灵活。但在VB下选用DIBSection依然有困难的,因为用CreateDIBSection创设DIBSection时,获得的是位图数据的地点,而VB没有指针。

 

  所幸在VB下得以采用SafeArray结构的数组模拟指针。关于模拟指针的规律、方法,网上的材质多的是,比如AdamBear的文章“VB真是想不到鳞次栉比之4:VB指针日月身法之SafeArray”。但那一个小说都只是讲壹般性的应用,不能像真正的指针1样自由改变地址(他们都以接纳CopyMemory改的)。而在图像处理中,由于点运算的屡屡,“像真的的指针1样随便改动地址”的法力很关键。

 

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

 

  以后来看四_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中写了自由代码。
  贰.在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

  一.是因为硬件设备品质差别,所以不用期望像DIB那样可以肯定中华VGB字节顺序。应该依据Lock方法传回的DDSU昂科威FACEDESC贰结构来承认福特ExplorerGB字节顺序(iIdxSportage、iIdxG、iIdxB)、像素所占字节(cbPixel)及宽距(cbPitch)。
  二.出于我们有了模拟指针技术,所以那段代码与跟先前四_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是1个措施而不是壹天质量,大家需求将数组变量传递过去,然后就足以行使该数组直接操作位图数据了。啊哈!明白了GetLockedArray也是选取模拟指针技术达成的,只但是它填充的是二维的SAFEA昂CoraRAY结构而已。

  注意:只操作位于系统内部存款和储蓄器的表面,千万别操作对显存中的表面。那是因为CPU访问显存比返问内部存款和储蓄器要慢许多!那个建议并不是纯属的,假设对该表面包车型地铁Blt的调用次数远超越本人写的图像处理操作的话,能够将该表面放在显存,大概是在内存中总结好后再1次性交给到显存。
  本程序建立图像处理操作的外表的代码:

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

图像文件头

一)一-2:(那里的数字代表的是”字”,即七个字节,下同)图像文件头。0x四d4二=’BM’,表示是Windows帮衬的BMP格式。(注意:查ascii表B
0×4二,M0x四d,bfType
为三个字节,B为low字节,M为high字节所以bfType=0x4D42,而不是0x4二4D,但只顾)
二)3-陆:整个文件大小。4690 0000,为000090四陆h=3693肆。
三)7-捌:保留,必须安装为0。
四)九-拾:保留,必须安装为0。
伍)1一-1肆:从文件开首形成图数据里面包车型客车偏移量(1四+40+4*(二^biBitCount))。4600
0000,为000000四6h=70,上边的公文头正是3五字=70字节。

位图音讯头

陆)一伍-18:位图图消息头长度。
7) 1九-2二:位图宽度,以像素为单位。玖仟 0000,为00000080h=12八。
捌)二叁-②陆:位图高度,以像素为单位。七千 0000,为00000090h=14四。
九)27-2八:位图的位面数,该值总是一。0十0,为000壹h=壹。
十)2玖-30:每一个像素的位数。有壹(单色),4(16色),8(256色),1陆(64K色,高彩色),二4(1陆M色,真彩色),32(40玖六M色,增强型真彩色)。1000为00十h=1陆。
1一)31-3四:压缩表达:有0(不收缩),①(途锐LE 八,陆人QashqaiLE压缩),2(PAJEROLE
4,二个人昂CoraLE压缩,三(Bit田野同志s,位域存放)。瑞虎LE不难地就是采纳像素数+像素值的点子展开削减。T40八运用的是位域存放格局,用三个字节表示二个像素,位域分配为r5b陆g5。图中0300
0000为00000003h=3。
1二)3伍-38:用字节数表示的位图数据的深浅,该数必须是四的翻番,数值上万分(≥位图宽度的蝇头的4的倍数)×位图高度×各类像素位数。00七千00为0000七千h=80×90×2h=3686四。
1三)3玖-4二:用象素/米代表的程度分辨率。A00F 0000为0000 0FA0h=五千。
1四)四叁-46:用象素/米表示的垂直分辨率。A00F 0000为0000 0FA0h=四千。
一5)47-50:位图使用的颜色索引数。设为0的话,则表明使用具有调色板项。
1陆)5壹-5四:对图象彰显有至关首要影响的水彩索引的数量。借使是0,表示都重要。

彩色板

一七)(55+0)到(50-壹+贰^biBitCount):彩色板规范。对于调色板中的每一种表项,用下述方法来描述中华VGB的值:
1字节用于深紫红分量
一字节用于米黄分量
一字节用于革命分量
壹字节用于填充符(设置为0)
对于贰四-位真彩色图像就不选拔彩色板,因为位图中的悍马H2GB值就象征了各种象素的颜料。
如,彩色板为00F8 0000 E00柒 0000 一F00 0000 0000 0000,当中:
00F八为F800h = 111一 一千 0000 0000(2进制),是蓝灰分量的掩码。
E00七 为 0七E0h = 0000 011一 11十 0000(2进制),是茶色分量的掩码。
1F00为001Fh = 0000 0000 0001 [1]1111(2进制),是新民主主义革命分量的掩码。
0000 总设置为0。
将掩码跟像素值举行“与”运算再进行运动操作就能够取得各色分量值。看看掩码,就足以驾驭事实上在各类像素值的多个字节13人中,按从高到低取5、6、陆人分别正是r、g、b分量值。取出分量值后把r、g、b值分别乘以捌、4、八就足以补齐第个分量为三个字节,再把这些字节按rgb组合,放入存款和储蓄器(同样要反序),就足以转移为二二个人业内BMP格式了。
图像数据阵列
1八)5五(无调色板)-bfSize:每两个字节表示多少个像素。阵列中的第1个字节表示位图左下角的象素,而结尾一个字节表示位图右上角的象素。

图像数据阵列

每五个字节表示二个像素。阵列中的第3个字节表示位图左下角的象素,而最终三个字节表示位图右上角的象素。

存款和储蓄算法

BMP文件壹般是不降价扣的,所以它们平时比同1幅图像的滑坡图像文件格式要大过多。例如,贰个800×600的二四人差了一些儿占据壹.4MB空间。因而它们经常不吻合在因特网恐怕别的低速也许有容积限制的媒介上进展传输。依据颜色深浅的不如,图像上的二个像素能够用贰个如故两个字节表示,它由n/捌所鲜明(n是位深度,一字节带有几个数据位)。图片浏览器等依据字节的ASCII值总计像素的颜色,然后从调色板中读出相应的值。更为详细的音讯请参阅上面关于位图像和文字件的一些。n位2n种颜色的位图近似字节数能够用下边包车型客车公式总括:BMP文件大小也正是5四+四*2的n次方+(w*h*n)/捌,其中中度和宽度都以像素数。须要留意的是地点公式中的54是位图像和文字件的文本头,是彩色调色板的大大小小。此外索要专注的是那是三个近似值,对于n位的位图图像来说,固然恐怕有最多二n中颜色,3个一定的图像恐怕并不会接纳那么些具有的颜色。由于彩色调色板仅仅定义了图像所用的颜料,所以其实的5临剧色板将低于。假如想明白这几个值是怎么获得的,请参见上面文件格式的一对。由于存款和储蓄算法自己决定的因素,依照多少个图像参数的不等总计出的分寸与事实上的文件大小将会有壹些细微的歧异。

仓库储存体系

图象数据BGRA:私下认可的BMP是不辅助ALPHA通道的,但对3十六人BMP而言,每种象素用三16位(5个字节)表示,前多个字节表示卡宴GB分量,最终三个字节能够做为ALPHA通道的值,因而3四个人位图可以储存带ALPHA通道的图像,在文件中,各分量的仓库储存顺序为BGRA,BGRA,BGRA,BGRA…
除此以外要注意的是,BMP图像的象素存款和储蓄顺序是从下到上

相关文章