VB圖像處理之像素的獲取和輸出

發表于:2007-07-14來源:作者:點擊數: 標簽:
要處理一個圖像,首先要獲得該圖像的像素值,而 VB 本身提供的PICTURE控件雖然可以打開很多類型的圖片,但是它提供的那個POINT方法讀取像素實在是太慢。而使用GetPixel這個API的速度也快不到哪里去,因為PIONT方法本身就是對于GetPixel的一個包裝。 在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不是就可以了嗎?

  不錯,如果只是要貼個圖,確實不用這么麻煩,可是,我們后面要說的圖像處理部分將會用到前門得到的像素值。所以,這只是一個開始,我真正要講的東西還在后面呢。請大家繼續關注。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97