在VB(.Net)中如何存成JPEG(jpg)圖形檔?
因為JPEG圖形檔的檔案大小不大,常常見到在網路上傳送,而且方便透過隨身碟來攜帶。在程式中,如果能將處理好的圖形資料直接存成JPEG圖形檔,真的是好酷喔!在本文中,將介紹數種存成JPEG圖形檔的方法和讀者分享。
使用VB.Net的類別或內建控制項VB.Net的Bitmap類別和Image類別,可以直接將圖形存成JPEG圖形檔。下列的程式碼會以內定的75%品質(Quality或稱為壓縮比)來儲存JPEG圖形檔。
' 載入圖形檔
Dim bmpPic As New Bitmap("指定圖形檔的路徑和檔名")
或
Dim bmpPic As Image = Image.FromFile("指定圖形檔的路徑和檔名")
...
' 存成JPEG圖形檔,內定為75%的品質。
bmpPic.Save("指定jpg檔的路徑和檔名", ImageFormat.Jpeg)
|
同樣我們也可將VB.Net的PictureBox控制項中圖形,直接存成JPEG圖形檔。
' 載入圖形檔
PictureBox1.Image=New Bitmap("指定圖形檔的路徑和檔名")
或
PictureBox1.Image=Image.FromFile("指定圖形檔的路徑和檔名")
...
' 存成JPEG(jpg)圖形檔,內定為75%的品質。
PictureBox1.Image.Save("指定jpg檔的路徑和檔名", ImageFormat.Jpeg)
|
另外在儲存JPEG圖形檔時,可以使用EncoderParameters和EncoderParameter兩個類別,來改變其儲存的品質。
使用.Net Framework的類別我們可以搭配FileStream、JpegBitmapEncoder和BitmapSource等三個類別,來儲存JPEG圖形檔。
其中JpegBitmapEncoder類別和BitmapSource類別的命名空間(Namespace)為
System.Windows.Media.Imaging
,並且必須參考PresentationCore.dll和WindowsBase.dll兩個dll檔,他們在
C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0
路徑中。
Imports System.IO
Imports System.Windows.Media.Imaging
Imports System.Drawing.Imaging
...
' 使用Bitmap類別或Image類別來載入圖形檔
' 當然亦可用PictureBox控制項來載入圖形檔
Dim bmpPic As New Bitmap("指定圖形檔的路徑和檔名")
或
Dim image As Image = System.Drawing.Image.FromFile("指定圖形檔的路徑和檔名")
Dim bmpPic As Bitmap = CType(image, Bitmap)
或
PictureBox1.Image = System.Drawing.Image.FromFile("指定圖形檔的路徑和檔名")
Dim bmpPic As Bitmap = CType(PictureBox1.Image, Bitmap)
...
' 設定相關資訊
Dim width As Integer = bmpPic.Width
Dim height As Integer = bmpPic.Height
Dim stride As Integer = (32 / 8) * width
' 取得指向圖形位元資料的指標
Dim srcRect As New Rectangle(0, 0, width, height)
Dim bmpSrcData As BitmapData = bmpPic.LockBits( _
srcRect, _
ImageLockMode.ReadOnly, _
System.Drawing.Imaging.PixelFormat.Format32bppRgb)
Dim bmpSrcPtr As IntPtr = bmpSrcData.Scan0
' 使用FileStream類別來儲存jpg檔
Dim imageStreamTarget As New FileStream( _
"指定jpg檔的路徑和檔名", _
FileMode.Create)
' 使用BitmapSource類別來建立圖形資訊
Dim bmpSource As BitmapSource = BitmapSource.Create( _
width, _
height, _
96, _
96, _
System.Windows.Media.PixelFormats.Bgr32, _
Nothing, _
bmpSrcPtr, _
height * stride, _
stride)
' 使用JpegBitmapEncoder來進行編碼
' 並且指定75%的儲存品質
Dim encoder As New JpegBitmapEncoder()
encoder.QualityLevel = 75
encoder.Frames.Add(BitmapFrame.Create(bmpSource))
encoder.Save(imageStreamTarget)
' 釋放imageStreamTarget物件
imageStreamTarget.Close()
imageStreamTarget.Dispose()
' 釋放bmpPic物件
bmpPic.UnlockBits(bmpSrcData)
bmpPic.Dispose()
|
讀者們或許已注意到,以上的程式碼在System.Drawing.Imaging和System.Windows.Media.Imaging兩個命名空間之間共用圖形的位元資料。
使用Intel JPEG Library (IJL)在VB(.Net)中可以透過Intel的JPEG程式庫(IJL),將圖形儲存成JPEG圖形檔。但必須要有此程式庫的DLL動態連結檔,如ijl11.dll、ijl15.dll或ijl20.dll等。
首先要初始化Intel的JPEG程式庫。
Dim jcprops As JPEG_CORE_PROPERTIES
Dim jerr As IJLERR
jerr = ijlInit(jcprops)
|
載入圖形檔,並取得圖形的相關資訊。
' 使用PictureBox控制項或Image控制項來載入圖形檔
' 當然亦可用來StdPicture物件載入圖形檔
Picture1.Picture = LoadPicture("指定圖形檔的路徑和檔名")
或
Image1.Picture = LoadPicture("指定圖形檔的路徑和檔名")
或
Dim stdPic As StdPicture
Set stdPic = LoadPicture("指定圖形檔的路徑和檔名")
...
' 取得圖形的相關資訊
Dim bmp As BITMAP
GetObject Picture1.Picture, Len(bmp), bmp
或
GetObject Image1.Picture, Len(bmp), bmp
或
GetObject stdPic.Handle, Len(bmp), bmp
...
Dim picWidth As Long, picHeight As Long
picWidth = bmp.bmWidth
picHeight = bmp.bmHeight
|
將圖形的位元資料,載入配置的緩衝區中。
' 配置緩衝區
Dim NumBits As Long
Dim hMemBitsData As Long, lpBitsData As Long
NumBits = ((picWidth * (bmp.bmBitsPixel / 8) + 3) _
And &HFFFFFFFC) * picHeight
hMemBitsData = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, NumBits)
lpBitsData = GlobalLock(hMemBitsData)
' 取得圖形位元資料
Dim bmpInfo As BITMAPINFO
With bmpInfo.bmiHeader
.biSize = Len(bmpInfo.bmiHeader)
.biWidth = bmp.bmWidth
.biHeight = bmp.bmHeight
.biPlanes = bmp.bmPlanes
.biBitCount = bmp.bmBitsPixel
.biCompression = BI_RGB
End With
GetDIBits Picture1.hDC, _
Picture1.Image, _
0, _
picHeight, _
lpBitsData, _
bmpInfo, _
DIB_RGB_COLORS
或
Dim hDCmem As Long
hDCmem = CreateCompatibleDC(Me.hDC)
SelectObject hDCmem, Image1.Picture
GetDIBits hDCmem, Image1, 0, picHeight, lpBitsData, bmpInfo, DIB_RGB_COLORS
DeleteDC hDCmem
或
Dim hDCmem As Long
hDCmem = CreateCompatibleDC(Me.hDC)
SelectObject hDCmem, stdPic.Handle
GetDIBits hDCmem, _
stdPic.Handle, _
0, _
picHeight, _
lpBitsData, _
bmpInfo, _
DIB_RGB_COLORS
DeleteDC hDCmem
|
設定壓縮JPEG圖形檔的相關資訊,並且進行壓縮處理。
' 設定DIB資訊
jcprops.DIBWidth = picWidth
jcprops.DIBHeight = -picHeight
jcprops.DIBPadBytes = ((picWidth * (bmp.bmBitsPixel / 8) + 3) _
And &HFFFFFFFC) - picWidth * 3
' 取得指向圖形位元資料的指標
jcprops.DIBBytes = lpBitsData
' 設定JPEG資訊
jcprops.JPGWidth = picWidth
jcprops.JPGHeight = picHeight
' 設定儲存時的品質百分比
jcprops.jquality = 75
' 設定JPEG緩衝區,存放壓縮後的結果。
Dim buf() As Byte, lBufSize As Long, lBufPtr As Long
lBufSize = jcprops.JPGWidth * jcprops.JPGHeight * 4
ReDim buf(0 To lBufSize - 1) As Byte
lBufPtr = VarPtr(buf(0))
jcprops.JPGBytes = lBufPtr
jcprops.JPGSizeBytes = lBufSize
' 進行壓縮處理
jerr = ijlWrite(jcprops, IJL_JBUFF_WRITEWHOLEIMAGE)
|
壓縮後,進行存檔處理。
' 取得壓縮後的資料
Dim fb() As Byte
lBufSize = jcprops.JPGSizeBytes
ReDim fb(0 To lBufSize - 1) As Byte
CopyMemory fb(0), ByVal lBufPtr, lBufSize
' 進行存檔處理
Dim iFile As Long, sFile As String
sFile = "指定jpg檔的路徑和檔名"
iFile = FreeFile()
Open sFile For Binary Access Write As #iFile
Put #iFile, , fb()
Close #iFile
|
最後記得釋放緩衝區。
...
GlobalUnlock hMemBitsData
GlobalFree hMemBitsData
|
也要記得釋放Intel的JPEG程式庫。
使用GDI Plus在VB(.Net)中透過呼叫GDI+(gdiplus.dll)的API,我們也可將圖形儲存成JPEG圖形檔。
首先要初始化GDI+l程式庫。
Dim GDIpInit As GdiplusStartupInput
Dim Token As Long
...
GDIpInit.GdiplusVersion = 1
GdiplusStartup Token, GDIpInit, ByVal 0&
|
載入圖形檔。
' 使用PictureBox控制項或Image控制項來載入圖形檔
' 當然亦可用來StdPicture物件載入圖形檔
Picture1.Picture = LoadPicture("指定圖形檔的路徑和檔名")
或
Image1.Picture = LoadPicture("指定圖形檔的路徑和檔名")
或
Dim stdPic As StdPicture
Set stdPic = LoadPicture("指定圖形檔的路徑和檔名")
...
|
現在就可以將圖形存成JPEG圖形檔了。
Dim Img As Long
' 將GDI的hBitmap轉為GDI+的Image
GdipCreateBitmapFromHBITMAP Picture1.Picture, 0&, img
或
GdipCreateBitmapFromHBITMAP Image1.Picture, 0&, img
或
GdipCreateBitmapFromHBITMAP stdPic.Handle, 0&, img
' 取得JPEG編碼的CLSID
Dim encoderCLSID As CLSID
GetEncoderClsid "image/jpeg", encoderCLSID
' 設定儲存時的品質百分比
Dim encoderParams As EncoderParameters
' 參數陣列中只有一個元素
encoderParams.Count = 1
With encoderParams.Parameter
.NumberOfValues = 1 ' 設定為1
.Type = EncoderParameterValueTypeLong ' 資料型態為32位元Unsigned Integer
GetParameterGUID EncoderQuality, .Guid ' 設定參數為EncoderQuality
.Value = VarPtr(75) ' 參數的值為75,但為指標。
End With
' 進行存檔
GdipSaveImageToFile img, _
StrConv("指定jpg檔的路徑和檔名", vbUnicode), _
encoderCLSID, _
encoderParams)
|
最後要記得釋放Image物件。
也要記得釋放GDI+l程式庫。
...
GdiplusShutdown Token
|
瞭解JPEG檔如果我們能夠充分的瞭解JPEG檔的壓縮原理和JPEG檔的檔案格式,我們就可以自行撰寫程式來儲存JPEG檔。在
Wikipedia網站中就有詳細
介紹JPEG檔的網頁,另外由
korejwa撰寫的
JPEG Encoder類別模組(VB6),在未使用Intel的JPEG程式庫(IJL)狀況下,直接將圖形存成JPEG圖形檔。
' 載入圖形檔
Dim MyPic As StdPicture
Set MyPic = LoadPicture("指定圖形檔的路徑和檔名")
...
' 存成JPEG圖形檔
Dim m_Image As New cImage
m_Image.CopyStdPicture MyPic
Dim m_Jpeg As New cJpeg
m_Jpeg.Quality = 75
m_Jpeg.SampleHDC m_Image.hDC, m_Image.Width, m_Image.Height
m_Jpeg.SaveFile "指定jpg檔的路徑和檔名"
' 清除物件
Set m_Image = Nothing
Set m_Jpeg = Nothing
|
問題延伸...
相關網頁連結...