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 Type
Private 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