VB無所不能之二:利用GDI+處理映像格式轉換
——作者:鐘聲
我今天想再續寫一篇關於VB的有關檔案格式轉換的文章。 對於Windows編程來說,除了處理網路通訊協定以外,處理幾種類型的檔案格式更加重要,這些檔案格式的掌握有利於更好的讓自己的程式和Windows系統貼近。 我們程式員們常常被如下格式的檔案所困擾: 1、影像檔格式:如:BMP、JPG、Gif、Png等; 2、音效檔格式:如:Wav、MIDI等; 3、視頻檔案格式:如:AVI、RMVB、RM等; 4、私人的非公開的檔案格式:如:doc、xls等。 其實,任何語言當你瞭解了檔案格式的標準的時候都可以處理,並不是局限於某一種開發語言。因此,在這裡我也想給VB的支援者們鼓鼓勁,VB作為一個強大Windows軟體的開發語言,處理這些檔案格式自然是不在話下了。 今天,我們只給大家介紹圖形格式轉換方面的一些小技巧。
首先,讓我們認識最基本的圖形檔案結構“BMP”。 BMP是一種與硬體裝置無關的影像檔格式,使用非常廣。它不採用任何壓縮,因此,BMP檔案所佔用的空間很大。由於BMP檔案格式是Windows環境中交換與圖有關的資料的一種標準,因此在Windows環境中啟動並執行圖形映像軟體都支援BMP映像格式。BMP檔案格式也被認為是一個基本的影像檔格式。 BMP的檔案結構方式: BMP檔案儲存體資料時,映像的掃描方式是按從左至右、從下到上的順序。 如所示: 我們在繪圖版中畫了一個點,這個點只有3個像素,我們把它染成紅色、紫色、黃色,這時候,將它儲存為BMP檔案。 然後,我們用UltraEdit-32開啟這個BMP,選擇十六進位編輯器,: 然後,我們觀察這個檔案中的格式: 我們分別放進去的三個顏色是: 紅:255、0、0 紫:128、128、255 黃:255、255、0 這時候,我們再對比檔案中的位元組: 這恰恰不就是這三個顏色的值嗎? 所以,BMP格式的圖形檔案是沒有進行任何壓縮的,而是老老實實的將每一個像素點的位置標示出來,告訴圖形軟體哪個像素點應該顯示什麼顏色而已。至於前面的位元組是描述該影像檔類型,映像深度等。 那麼好,因為它太大,所以才有人研究了對BMP壓縮的演算法,有JPEG、GIF、PNG,這幾種壓縮演算法。 大家經常用的看圖軟體ACDSEE,在用的時候心想,好棒啊,這個軟體可以把各種格式的圖形檔案進行轉換。如果做到ACDSEE那樣,甚至是PhotoShop那樣,豈不是得研究壓縮演算法嗎? 我告訴大家,根本就不用研究壓縮演算法,Windows提供了很好的工具函數——GDI+,通過這個函數工具組,便可以完成任意圖形檔案格式之間的轉換。
我們給出轉換的方法:
1、聲明函數和結構 Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Type GdiplusStartupInput
GdiplusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Private Type EncoderParameter
GUID As GUID
NumberOfValues As Long
type As Long
Value As Long
End Type
Private Type EncoderParameters
count As Long
Parameter As EncoderParameter
End TypePrivate Declare Function GdiplusStartup Lib "GDIPlus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Function GdiplusShutdown Lib "GDIPlus" (ByVal token As Long) As Long
Private Declare Function GdipCreateBitmapFromHBITMAP Lib "GDIPlus" (ByVal hbm As Long, ByVal hPal As Long, BITMAP As Long) As Long
Private Declare Function GdipDisposeImage Lib "GDIPlus" (ByVal Image As Long) As Long
Private Declare Function GdipSaveImageToFile Lib "GDIPlus" (ByVal Image As Long, ByVal FileName As Long, clsidEncoder As GUID, encoderParams As Any) As Long
Private Declare Function CLSIDFromString Lib "ole32" (ByVal Str As Long, id As GUID) As Long
Private Declare Function CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Dest As Any, Src As Any, ByVal cb As Long) As Long
2、BMP轉換JPG Dim Quality As Byte
Dim TIFF_ColorDepth As Long
Dim TIFF_Compression As Long
Screen.MousePointer = vbHourglass
Dim tSI As GdiplusStartupInput
Dim lRes As Long
Dim lGDIP As Long
Dim lBitmap As Long
Dim aEncParams() As Byte
Dim pict As StdPicture
On Error GoTo ErrHandle:
Quality=80
TIFF_ColorDepth=24
TIFF_Compression=6
pict=Picture1.Picture
tSI.GdiplusVersion = 1
lRes = GdiplusStartup(lGDIP, tSI)
lRes = GdipCreateBitmapFromHBITMAP(pict.Handle, 0, lBitmap)
Dim tJpgEncoder As GUID
Dim tParams As EncoderParameters
CLSIDFromString StrPtr("{557CF401-1A04-11D3-9A73-0000F81EF32E}"), tJpgEncoder
tParams.count = 1
With tParams.Parameter ' Quality
CLSIDFromString StrPtr("{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"), .GUID
.NumberOfValues = 1
.type = 4
.Value = VarPtr(Quality)
End With
ReDim aEncParams(1 To Len(tParams))
Call CopyMemory(aEncParams(1), tParams, Len(tParams)) 上面的程式是將Picture1中的映像,轉換成JPG的一個方法,最終我們得到了一個JPG的數組,當然,你可以隨便處理,也可以存放為檔案,也可以另作處理。 大家看利用這個方法作圖形格式的轉換和VB本身有關係嗎? 鐘聲2009-7-7