新普金娱乐网址


天文2017自我之以平等不成挑战

数学说那些年,你所吃过的劳顿

若的人生自由为

  • 九月 13, 2018
  • 数学
  • 没有评论

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

1

“我怀念回报工商管理”我外甥头等同横,来了平句子。

“不行,你省人家大夫,拿在比大之薪资,两伤口都在医院上班,要房来房,要车来车,你看,多舒服。做工作有啊好之?你看而舅舅,多辛苦呀!你想这样麻烦吗?你想四处漂泊吗?”大姐苦口婆心的劝导。

“报考该校是本身的事,不用你们管”

“是您的事体,也是阖家的盛事,你未来生活不下去,我们能够不随便吗?你本尚聊,根本未晓社会及啊好什么坏?没想过之尚是惬意,不要听别人一样说,就热血沸腾!”大姐没丝毫投降,耐心的累解劝。

外甥今年测验大学,成绩就出去了,在填报志愿之时节,他好的意见跟家中之眼光,截然相反。他期待选择一个业内去特别城市去异地闯荡一久经考验,而家里人还期望选择有较稳妥的正式,以后在逾舒适一些。

透过四五上之争论,最后,孩子要妥协了,放弃了锻炼的梦想,报考了平等所高校的医药专业。面对在压力,面对在劝说,面对父母社会更的明,自己挑选了放弃,选择了曲于压力。

作者:zyl910

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

2

我们单位于小李将结婚了,她说其结婚以后归看看老人。

“我们如果结合,他们不容许,没有主意,我哪怕与他走了下,来北京早就三年了,今年咱们打算将证领了,过年的时候,我们共同转老家看望,告诉父母一样名誉。”小李幽幽地游说,她发到头昏很掉价,她是同别人私奔出来的。

“这来啊?这说明您胆敢选择好的终身大事,私奔逃婚这都认证老人思想观念陈旧,其实,只要你们了得好,他们见面容许的,不用顾虑,没什么丢人的,而且老人要看你们幸福,也无见面指向你们生气的”我们安她说。

说句实话,我真正特别崇拜她,敢于做出自己之选取,敢于选择好的爱,追求婚姻之擅自,他她是一个好勇敢的人。心底里呢她祝福。

同、为什么这样慢?

  自盘古开天地以来(好像夸张了点),一直有人抱怨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完全可以描绘高速的图像处理程序。

 

3

第二抖让了一个话题,你的人生自由为?怎样才能做到自由的人生?看到了外甥大学正式的挑选随机,看到小李婚姻选择随机,突然看自由是同样种植浪费,我耶想提一提。

对这话题,很多总人口还在谈,我的答复一定是:我的人生不轻易,我当追求简单自由之人生。

投考大学,报考专业,都是大人帮忙自己选择的,我从小就软,也从没什么意见,父母协助自己选,我去学就是了。结果选的正统是本人成绩最差的赛璐珞专业,当时己疼物理和数学,物理和数学之成就从是,化学是自个儿成最差之平等门,后来透过大力,虽然好有的了,可是我真切不欣赏异。

新兴,很多同室在他流浪,自由地挑自己之事,可是我任起了老人家之操纵,回家做了公务员。这都非是自己控制的。

打自常年始发,我说之成年大约到了二十五六,我摆脱了上下一心之软,多少敢做点主了,有矣一些叛离,可能本身则长相成熟,但是心智发育比后,叛逆来的后矣一点,青春梦想后了好几。

还吓情人是自家好选择的,虽然未是一个特别美人,但是温柔体贴,性格好,不急不躁,和自己如此的驴脾气搭配,倒是真的互补。能够走至首都来,能够设置自己的公司,说起来,这个中的功德至少发生内的一半。

公务员辞职,是自我要好选的,为了这自由的选取,我背后的具有的苦,所有吃了之切肤之痛都是以此自由选择的结果。这是自身工作的亚破定位。

投入的商业之中,很多哪怕非擅自了。我属于臭知识分子型,内心里又多喜爱教,做培训起码可以吃别人尊重,可是我创业前三年的创作了成千上万祥和之争鸣,却几乎输掉了本人在之有着硬通货。不得不投入到自莫喜的人际关系中,虽然到现行凡相近十年了,我还是以人际关系中无是游刃有余,但是至少公司化几十总人口,没有死,在行业里呢享有盛誉。

说到了今自我之人生自由为?可以说自家之商人生,是一点一滴不轻易的,导致我万分懊恼,很多工作身不由自身,很多提到难以打理。说交此处,我非常感激今年之跑步群,和写作群,起码让自家之心灵找到了随便,让自身之私家精神找到自由,这是如出一辙切片我要好之社会风气,我可以努力去重新远,精心地失去养。

二、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写图像处理程序的时候,首先要简明一点: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改的)。而当图像处理面临,由于触及运算的累累,“像真的指针一样随便变动地址”的作用十分关键。

 

  其实“像真的指针一样随便改动地址”并从未技术难度(对于曾经学会模拟指针的人口来说),就看朝思暮想赢得不:直接以一个动态数组(设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

4

肆意,未必每个人还亟需,其实我还没抱怨父母也自身选的业内、为本人选择的首先份工作。

说句实话,我真正不亮堂怎么去挑选?小时候,我是一个并未意见的口,一个尚无主意的食指,你给了外即兴,等于给他饿死。例如,家庭驯养的鸡同猪,你管其内置森林里面去,你看他得独立在呢?你当他可不受外海洋生物吃少吧?

擅自之选料是建于出独立判断及负责后果的能力之上的。我坚持这观点。

发生了独自判断与承担后果的力,自由的挑三拣四只能管你的随机,却未可知确保你的甜蜜。

自己出三年之早晚,我的部下都提示了依单位的入局长,我创业七年之上,和镇领导聚会的时段,他咨询我“这么辛苦,你后悔吗?”我淡淡一笑,说句实话,我莫晓!

前同段,国家级科研院所培训中心官员建议我拿公司关了,他们的高级班的教程都深受自家塑造,我以冰冷一乐。

生个朋友为是一个创业者,一起用,他说特别佩服,没悟出他佩服的竟是自当斯行当里坚持了十年,没有放弃。我或淡淡一乐。

自由是朝气蓬勃独立的结局。你可以擅自之失拣,你得无限制之去生活,当然你要担负自由选择的结果。

朝气蓬勃的任意,是索要之。我生投机独立视角的随意,不是人云亦云;我有独立判断的自由,判断事情的好及生,有己要好的思考;我产生取舍的人身自由,选择面前执行要落后,这亟需不懈的人生。

还吓,我还维持正和谐琢磨之深度,我还维持着做人之良知,我还保持在加油之激情,我还保持着前行的欲望,虽然时间扫了了风霜,我既见了秋天的面目,虽然本人一度没有了少年的漂浮,但是于向上的路上,我早已瞧清了系列化,展开翅膀,自由的飞。

非知底是鹰,还是鸡,不亮堂会飞多远?但是就世界,我一度来过。

相关文章

No Comments, Be The First!
近期评论
    分类目录
    功能
    网站地图xml地图