王朝网络
分享
 
 
 

VB图像处理,(一)像素的获取和输出

王朝c#·作者佚名  2006-12-17
宽屏版  字体: |||超大  

一直想自己写一个图像处理的软件。在网络上找各种图像处理方面的技术文章。

但是找到的往往不是高深的理论,就是用C++等语言写出来的例程,非常不便。

其实很多时候,我想找的只是一种描述,或者是伪代码,既有利于理解,也有利于改写成任何语言的版本。

近日,我把自己学到的一些图像处理方面的知识写了一个ImageCast的小程序。把自己所掌握的处理技巧作了一个“包装”,感慨于资料收集的不便和学习VB中的点点滴滴。特将算法提供给大家以作参考。希望对于一些和我一样在网上寻觅不获的朋友有所帮主。

要处理一个图像,首先要获得该图像的像素值,而VB本身提供的PICTURE控件虽然可以打开很多类型的图片,但是它提供的那个POINT方法读取像素实在是太慢。而使用GetPixel这个API的速度也快不到哪里去,因为PIONT方法本身就是对于GetPixel的一个包装。

在VB中要快速获取一幅在PICTURE中打开的图像比较快速的方法是使用DIB方法,当然还有DDB方法,不过使用DDB方法还需要考虑不同颜色深度的图像的分别处理,在程序的实现上要相对复杂,而使用DIB方法则不必,并且在处理速度上比DDB方法也慢的有限。

过程一:获得一个在PICTURE控件中打开的图像的所有像素。

Public Sub DibGet(ByVal IdSource As Long, XBegin As Long, ByVal YBegin As Long, ByVal XEnd As Long, ByVal YEnd As Long)

Dim iBitmap As Long

Dim iDC As Long

Dim I As LongDim

Dim W As Long

Dim H As Long

On Error GoTo ErrLine

Done = False

TimeGet = timeGetTime

InPutWid = XEnd - XBegin

InPutHei = YEnd - YBegin

W = InPutWid + 1

H = InPutHei + 1

I = (Bits \ 8) - 1

ReDim ColVal(I, InPutWid, InPutHei)

With bi24BitInfo.bmiHeader

.biBitCount = Bits

.biCompression = 0&

.biPlanes = 1

.biSize = Len(bi24BitInfo.bmiHeader)

.biWidth = W

.biHeight = H

End With

iBitmap = GetCurrentObject(IdSource, 7&)

GetDIBits IdSource, iBitmap, 0&, H, ColVal(0, 0, 0), bi24BitInfo, 0&

DeleteObject iBitmap

Done = True

TimeGet = timeGetTime - TimeGetExit Sub

ErrLine:

MsgBox "错误号:" & Err.Number & ":" & Err.Description

End Sub

在这个过程中所用到的只是一些参数的设定和API的调用,不涉及算法。

过程二:图像输出的过程:

Public Sub DIBPut(ByVal IdDestination As Long)

Dim W As Long

Dim H As Long

On Error GoTo ErrLine

Done = False

TimePut = timeGetTime

W = OutPutWid + 1

H = OutPutHei + 1

With bi24BitInfo.bmiHeader

.biWidth = W

.biHeight = H

LineBytes = ((W * Bits + 31) And &HFFFFFFE0) \ 8

.biSizeImage = LineBytes * H

End With

SetDIBitsToDevice IdDestination, 0, 0, W, H, 0, 0, 0, H, ColOut(0, 0, 0), bi24BitInfo.bmiHeader, 0

Done = True

TimePut = timeGetTime - TimePut

Exit Sub

ErrLine:

MsgBox Err.Description

End Sub

下面解释一下在过程中到的全局变量和数据结构,以及API的定义。

API定义:

删除一个DC

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

删除一个对象

Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

选择当前对象

Private Declare Function GetCurrentObject Lib "gdi32" (ByVal hdc As Long, ByVal uObjectType As Long) As Long

获取DIB

Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BitMapInfo, ByVal wUsage As Long) As Long

获取系统时间

Private Declare Function timeGetTime Lib "winmm.dll" () As Long

数据结构定义:

Private Type BitMapInfoHeader '文件信息头——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

Private Type RGBQuad

rgbBlue As Byte

rgbGreen As Byte

rgbRed As Byte

'rgbReserved As Byte

End Type

Private Type BitMapInfo

bmiHeader As BitMapInfoHeader

bmiColors As RGBQuad

End Type

这三个数据结构都是在DIB中不可缺少的。我们不必深究,只是按照顺序复制粘贴直接使用就是了。

过程中用到的全局变量:

Private Const Bits As Long = 32 '颜色深度,这里把所有图像都按照32位来处理

Public Done As Boolean '用于标记一个过程是否结束

Public TimeGet As Long '用于记录输入过程处理所花费的时间

Public TimePut As Long '用于记录输出过程处理所花费的时间

Dim ColVal() As Byte '用于存放从DIB输入的像素值

Dim ColOut() As Byte '用于存放向DIB输出的像素值

Dim InPutHei As Long '用于记录输入图像的高度

Dim InPutWid As Long '用于记录输入图像的宽度

Dim bi24BitInfo As BitMapInfo '定义BMP信息

可以看出,我在输入和输出中使用了两个不同的动态数组ColVal()和ColOut()

这么做是有道理的,因为我们不只是为了输入和输出图像,中间还要对像素进行处理。

包括图像缩放、色彩调整、锐化、柔化等等处理,使用两个不同的数组来分别存放数据更有利于程序的实现。

有些性急的朋友说不定已经把程序贴到工程里试用了,可是会发现根本不能输出图像。

这是因为当你用DIBGET获得的图像还在ColVal() 中呢,需要把它们放到ColOut()这个数组中去,DIBPUT这个过程才能起作用。

这里再给出一个用于数组整体移动数据的过程:

Public Sub CopyData(ByVal W As Long, ByVal H As Long)

Dim Length As Long

Dim I As Long

Dim L As Long

I = Bits \ 8

L = I - 1

Length = (W + 1&) * (H + 1&) * I

ReDim ColOut(L, W, H)

CopyMemory ColOut(0, 0, 0), ColVal(0, 0, 0), Length

End sub

API定义:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)

这时,我们就可以来试一下效果了:

把你的显示器调到32位色。

将前面的所有API和变量定义全部贴到一个新建的模块里

新建一个窗体,加两个PICTURE控件:pictrue1 ,picture2 一个按钮command1

在pictrue1中加载一个图片

在command1中写如下代码:

sub command1_click()

With picture1

.ScaleMode=3

.BorderStyle=0

DibGet .hdc,0,0,.scalewidth,.scaleheight

End With

CopyData InPutHei ,InPutWid

picture2.AutoRedraw=True

DibPut picture2.hdc

picture2.refresh

end sub

运行一下,按钮按下,pictreu1中的图片就立刻显示到了picture2中。

这时,你可能会说,弄了这么半天就贴个图?用PaintPicture不是就可以了吗?

不错,如果只是要贴个图,确实不用这么麻烦,可是,我们后面要说的图像处理部分将会用到前门得到的像素值。所以,这只是一个开始,我真正要讲的东西还在后面呢。请大家继续关注。

(这里只是说了我自己在写程序的时候用到的方法,存在很多的不足。并且因为在贴上来的时候作了部分修改,可能会存在部分错误,请各位高手不吝赐教,将您用到的更好的方法提供一下,我将不胜感激。)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有