| 
TA的每日心情|  | 2025-6-23 21:25
 | 
|---|
 签到天数: 126 天 [LV.7]常住居民III | 
 
| 
 
首先要下载一个IStream库,用该库可以减少代码量,如果直接全部用API也同样可以。
×
欢迎您注册加入!这里有您将更精采!您需要 登录 才可以下载或查看,没有账号?注册 
  
  IStream.rar
(7.07 KB, 下载次数: 341) 
 下载好上面的IStream库后,我们来看下魏滔序的一个模块:
 [mw_shl_code=vb,true]
 ' By 魏滔序
 '常量声明
 Private Const ClsidJPEG As String = "{557CF401-1A04-11D3-9A73-0000F81EF32E}"
 Private Const EncoderParameterValueTypeLong As Long = 4&
 Private Const EncoderQuality As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"
 Private Const GdiPlusVersion As Long = 1&
 
 '结构声明
 Private Type GUID
 Data1 As Long
 Data2 As Integer
 Data3 As Integer
 Data4(0 To 7) As Byte
 End Type
 
 Private Type IID
 Data1 As Long
 Data2 As Integer
 Data3 As Integer
 Data4(0 To 7) As Byte
 End Type
 
 Private Type PICTDESC
 cbSizeOfStruct As Long
 picType As Long
 hgdiObj As Long
 hPalOrXYExt 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(15) As EncoderParameter
 End Type
 
 Private Type GDIPlusStartupInput
 GdiPlusVersion As Long
 DebugEventCallback As Long
 SuppressBackgroundThread As Long
 SuppressExternalCodecs As Long
 End Type
 
 Private Type GdiplusStartupOutput
 NotificationHook As Long
 NotificationUnhook As Long
 End Type
 
 '枚举声明
 Private Enum Status
 OK = 0
 GenericError = 1
 InvalidParameter = 2
 OutOfMemory = 3
 ObjectBusy = 4
 InsufficientBuffer = 5
 NotImplemented = 6
 Win32Error = 7
 WrongState = 8
 Aborted = 9
 FileNotFound = 10
 ValueOverflow = 11
 AccessDenied = 12
 UnknownImageFormat = 13
 FontFamilyNotFound = 14
 FontStyleNotFound = 15
 NotTrueTypeFont = 16
 UnsupportedGdiplusVersion = 17
 GdiplusNotInitialized = 18
 PropertyNotFound = 19
 PropertyNotSupported = 20
 ProfileNotFound = 21
 End Enum
 
 'API声明
 Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long, ByVal hpal As Long, ByRef bitmap As Long) As Status
 Private Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal bitmap As Long, ByRef hbmReturn As Long, ByVal Background As Long) As Status
 Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Status
 Private Declare Function GdipLoadImageFromStream Lib "gdiplus" (ByVal Stream As IUnknown, ByRef image As Long) As Status
 Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Status
 Private Declare Function GdiplusStartup Lib "gdiplus" (ByRef token As Long, ByRef lpInput As GDIPlusStartupInput, ByRef lpOutput As GdiplusStartupOutput) As Status
 Private Declare Function GdipSaveImageToStream Lib "gdiplus" (ByVal image As Long, ByVal Stream As IStream, ByRef clsidEncoder As GUID, ByRef encoderParams As Any) As Status
 Private Declare Function CLSIDFromString Lib "ole32" (ByVal Str As Long, ByRef id As GUID) As Long
 Private Declare Function CreateStreamOnHGlobal Lib "ole32.dll" (ByRef hGlobal As Any, ByVal fDeleteOnRelease As Long, ByRef ppstm As Any) As Long
 Private Declare Sub OleCreatePictureIndirect Lib "oleaut32.dll" (ByRef lpPictDesc As PICTDESC, ByRef riid As IID, ByVal fOwn As Boolean, ByRef lplpvObj As Object)
 
 
 '根据版本初始化GDI+
 Private Function StartUpGDIPlus(ByVal GdipVersion As Long) As Long
 Dim GdipToken As Long
 Dim GdipStartupInput As GDIPlusStartupInput
 Dim GdipStartupOutput As GdiplusStartupOutput
 GdipStartupInput.GdiPlusVersion = GdipVersion
 If GdiplusStartup(GdipToken, GdipStartupInput, GdipStartupOutput) = OK Then
 StartUpGDIPlus = GdipToken
 End If
 End Function
 
 '从图像转换为流
 Public Function PictureToStream(ByVal Picture As StdPicture, Optional ByVal JpegQuality As Long = 85) As IStream
 Dim picStream As IStream
 Dim lBitmap As Long
 Dim tGUID As GUID
 Dim bytBuff() As Byte
 Dim tParams As EncoderParameters
 Dim lngGdipToken As Long
 
 lngGdipToken = StartUpGDIPlus(GdiPlusVersion)
 
 '检查JPG压缩比率
 If JpegQuality > 100 Then JpegQuality = 100
 If JpegQuality < 0 Then JpegQuality = 0
 
 '创建Bitmap
 If GdipCreateBitmapFromHBITMAP(Picture.Handle, 0, lBitmap) = OK Then
 '创建Stream
 If CreateStreamOnHGlobal(ByVal 0, False, picStream) = 0 Then
 '转换GUID
 If CLSIDFromString(StrPtr(ClsidJPEG), tGUID) = 0 Then
 '设置JPG相关参数值
 tParams.Count = 1
 With tParams.Parameter(0)
 CLSIDFromString StrPtr(EncoderQuality), .GUID
 .NumberOfValues = 1
 .Type = EncoderParameterValueTypeLong
 .Value = VarPtr(JpegQuality)
 End With
 '将Bitmap数据保存到流(JPG格式)
 If GdipSaveImageToStream(lBitmap, picStream, tGUID, tParams) = OK Then
 Set PictureToStream = picStream
 End If
 End If
 Set picStream = Nothing
 End If
 End If
 GdipDisposeImage lBitmap '本行代码乃后期修正
 GdiplusShutdown lngGdipToken
 End Function
 
 '从流转换为图像
 Public Function StreamToPicture(ByVal Stream As IStream) As StdPicture
 Dim picStream As IStream
 Dim lBitmap As Long
 Dim hBitmap As Long
 Dim lngGdipToken As Long
 Dim tPictDesc As PICTDESC
 Dim IID_IPicture As IID
 Dim oPicture As IPicture
 
 lngGdipToken = StartUpGDIPlus(GdiPlusVersion)
 
 Set picStream = Stream
 '从Stream加载Bitmap
 If GdipLoadImageFromStream(picStream, lBitmap) = OK Then
 '根据Bitmap创建hBitbmp
 If GdipCreateHBITMAPFromBitmap(lBitmap, hBitmap, 0) = OK Then
 With tPictDesc
 .cbSizeOfStruct = Len(tPictDesc)
 .picType = vbPicTypeBitmap
 .hgdiObj = hBitmap
 .hPalOrXYExt = 0
 End With
 
 ' 初始化IPicture
 With IID_IPicture
 .Data1 = &H7BF80981
 .Data2 = &HBF32
 .Data3 = &H101A
 .Data4(0) = &H8B
 .Data4(1) = &HBB
 .Data4(3) = &HAA
 .Data4(5) = &H30
 .Data4(6) = &HC
 .Data4(7) = &HAB
 End With
 
 Call OleCreatePictureIndirect(tPictDesc, IID_IPicture, True, oPicture)
 Set StreamToPicture = oPicture
 End If
 End If
 
 Set picStream = Nothing
 GdipDisposeImage lBitmap '本行代码乃后期修正
 GdiplusShutdown lngGdipToken
 End Function
 [/mw_shl_code]示例代码: [mw_shl_code=vb,true]'示例
 ' By 魏滔序
 Private Sub Command1_Click()
 Dim s As IStream
 Set s = PictureToStream(Me.Picture1.Picture)
 Set Me.Picture2.Picture = StreamToPicture(s)
 End Sub[/mw_shl_code]
 
 从上面的代码不难看出原作者利用 GDI 和 Istream 库巧妙的实现了在VB6中从图像转换为流及从流转换为图像。
 
 原作者代码已经实现了StdPicture和IStream的互转,下面这里使用了GlobalAlloc、GlobalLock、GlobalUnlock、GlobalFree等函数创建一个缓冲区(指针为hGlobal),将魏滔序代码中CreateStreamOnHGlobal(ByVal 0&, False, picStream)改成CreateStreamOnHGlobal(ByVal hGlobal, False, picStream),这样我们便可根据hGlobal来读写picStream的内容了,具体代码如下: [mw_shl_code=vb,true]Option Explicit
 
 'StdPicture、IStream、Byte() 互转
 '作者:TZWSOHO
 
 Private Const GMEM_MOVEABLE As Long = &H2
 
 '常量声明
 Private Const ClsidJPEG As String = "{557CF401-1A04-11D3-9A73-0000F81EF32E}"
 Private Const EncoderParameterValueTypeLong As Long = 4&
 Private Const EncoderQuality As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"
 Private Const GdiPlusVersion As Long = 1&
 
 '结构声明
 Private Type GUID
 Data1 As Long
 Data2 As Integer
 Data3 As Integer
 Data4(0 To 7) As Byte
 End Type
 
 Private Type IID
 Data1 As Long
 Data2 As Integer
 Data3 As Integer
 Data4(0 To 7) As Byte
 End Type
 
 Private Type PICTDESC
 cbSizeOfStruct As Long
 picType As Long
 hgdiObj As Long
 hPalOrXYExt 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(15) As EncoderParameter
 End Type
 
 Private Type GDIPlusStartupInput
 GdiPlusVersion As Long
 DebugEventCallback As Long
 SuppressBackgroundThread As Long
 SuppressExternalCodecs As Long
 End Type
 
 Private Type GdiplusStartupOutput
 NotificationHook As Long
 NotificationUnhook As Long
 End Type
 
 '枚举声明
 Private Enum Status
 OK = 0
 GenericError = 1
 InvalidParameter = 2
 OutOfMemory = 3
 ObjectBusy = 4
 InsufficientBuffer = 5
 NotImplemented = 6
 Win32Error = 7
 WrongState = 8
 Aborted = 9
 FileNotFound = 10
 ValueOverflow = 11
 AccessDenied = 12
 UnknownImageFormat = 13
 FontFamilyNotFound = 14
 FontStyleNotFound = 15
 NotTrueTypeFont = 16
 UnsupportedGdiplusVersion = 17
 GdiplusNotInitialized = 18
 PropertyNotFound = 19
 PropertyNotSupported = 20
 ProfileNotFound = 21
 End Enum
 
 'API声明
 Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long, ByVal hpal As Long, ByRef bitmap As Long) As Status
 Private Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal bitmap As Long, ByRef hbmReturn As Long, ByVal Background As Long) As Status
 Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Status
 Private Declare Function GdipLoadImageFromStream Lib "gdiplus" (ByVal Stream As IStream, ByRef image As Long) As Status
 Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Status
 Private Declare Function GdiplusStartup Lib "gdiplus" (ByRef token As Long, ByRef lpInput As GDIPlusStartupInput, ByRef lpOutput As GdiplusStartupOutput) As Status
 Private Declare Function GdipSaveImageToStream Lib "gdiplus" (ByVal image As Long, ByVal Stream As IStream, ByRef clsidEncoder As GUID, ByRef encoderParams As Any) As Status
 Private Declare Function CLSIDFromString Lib "ole32" (ByVal Str As Long, ByRef id As GUID) As Long
 Private Declare Function CreateStreamOnHGlobal Lib "ole32.dll" (ByRef hGlobal As Any, ByVal fDeleteOnRelease As Long, ByRef ppstm As Any) As Long
 Private Declare Sub OleCreatePictureIndirect Lib "oleaut32.dll" (ByRef lpPictDesc As PICTDESC, ByRef riid As IID, ByVal fOwn As Boolean, ByRef lplpvObj As Object)
 
 Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
 
 Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
 Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
 'Private Declare Function GlobalSize Lib "kernel32.dll" (ByVal hMem As Long) As Long
 Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
 Private Declare Function GlobalFree Lib "kernel32.dll" (ByVal hMem As Long) As Long
 'Private Declare Function GetHGlobalFromStream Lib "ole32.dll" (ByVal pstm As IStream, ByRef phglobal As Long) As Long
 
 'By Modest
 '根据版本初始化GDI+
 Private Function StartUpGDIPlus(ByVal GdipVersion As Long) As Long
 Dim GdipToken As Long
 Dim GdipStartupInput As GDIPlusStartupInput
 Dim GdipStartupOutput As GdiplusStartupOutput
 GdipStartupInput.GdiPlusVersion = GdipVersion
 If GdiplusStartup(GdipToken, GdipStartupInput, GdipStartupOutput) = OK Then
 StartUpGDIPlus = GdipToken
 End If
 End Function
 
 'By Modest
 '从图像转换为流
 Public Function PictureToStream(ByVal Picture As StdPicture, Optional ByVal JpegQuality As Long = 85) As IStream
 Dim picStream As IStream
 Dim lBitmap As Long
 Dim tGUID As GUID
 Dim bytBuff() As Byte
 Dim tParams As EncoderParameters
 Dim lngGdipToken As Long
 
 lngGdipToken = StartUpGDIPlus(GdiPlusVersion)
 
 '检查JPG压缩比率
 If JpegQuality > 100 Then JpegQuality = 100
 If JpegQuality < 0 Then JpegQuality = 0
 
 '创建Bitmap
 If GdipCreateBitmapFromHBITMAP(Picture.Handle, 0, lBitmap) = OK Then
 '创建Stream
 If CreateStreamOnHGlobal(ByVal 0&, False, picStream) = 0 Then
 '转换GUID
 If CLSIDFromString(StrPtr(ClsidJPEG), tGUID) = 0 Then
 '设置JPG相关参数值
 tParams.Count = 1
 With tParams.Parameter(0)
 CLSIDFromString StrPtr(EncoderQuality), .GUID
 .NumberOfValues = 1
 .Type = EncoderParameterValueTypeLong
 .Value = VarPtr(JpegQuality)
 End With
 '将Bitmap数据保存到流(JPG格式)
 If GdipSaveImageToStream(lBitmap, picStream, tGUID, tParams) = OK Then
 Set PictureToStream = picStream
 End If
 End If
 Set picStream = Nothing
 End If
 End If
 GdipDisposeImage lBitmap
 GdiplusShutdown lngGdipToken
 End Function
 
 'By Modest
 '从流转换为图像
 Public Function StreamToPicture(ByVal Stream As IStream) As StdPicture
 Dim picStream As IStream
 Dim lBitmap As Long
 Dim hBitmap As Long
 Dim lngGdipToken As Long
 Dim tPictDesc As PICTDESC
 Dim IID_IPicture As IID
 Dim oPicture As IPicture
 
 lngGdipToken = StartUpGDIPlus(GdiPlusVersion)
 
 Set picStream = Stream
 '从Stream加载Bitmap
 If GdipLoadImageFromStream(picStream, lBitmap) = OK Then
 '根据Bitmap创建hBitbmp
 If GdipCreateHBITMAPFromBitmap(lBitmap, hBitmap, 0) = OK Then
 With tPictDesc
 .cbSizeOfStruct = Len(tPictDesc)
 .picType = vbPicTypeBitmap
 .hgdiObj = hBitmap
 .hPalOrXYExt = 0
 End With
 
 ' 初始化IPicture
 With IID_IPicture
 .Data1 = &H7BF80981
 .Data2 = &HBF32
 .Data3 = &H101A
 .Data4(0) = &H8B
 .Data4(1) = &HBB
 .Data4(3) = &HAA
 .Data4(5) = &H30
 .Data4(6) = &HC
 .Data4(7) = &HAB
 End With
 
 Call OleCreatePictureIndirect(tPictDesc, IID_IPicture, True, oPicture)
 Set StreamToPicture = oPicture
 End If
 End If
 
 Set picStream = Nothing
 GdipDisposeImage lBitmap
 GdiplusShutdown lngGdipToken
 End Function
 
 'By TZWSOHO
 '从图像转换为流再转为字节数组
 Public Function PictureToByteArray(ByVal Picture As StdPicture, Optional ByVal JpegQuality As Long = 85) As Byte()
 Dim picStream As IStream
 Dim lBitmap As Long
 Dim tGUID As GUID
 Dim bytBuff() As Byte
 Dim tParams As EncoderParameters
 Dim lngGdipToken As Long
 
 Dim hGlobal As Long, lpBuffer As Long, dwSize As Long, Buff() As Byte
 
 lngGdipToken = StartUpGDIPlus(GdiPlusVersion)
 
 '检查JPG压缩比率
 If JpegQuality > 100 Then JpegQuality = 100
 If JpegQuality < 0 Then JpegQuality = 0
 
 '创建Bitmap
 If GdipCreateBitmapFromHBITMAP(Picture.Handle, 0, lBitmap) = OK Then
 hGlobal = GlobalAlloc(GMEM_MOVEABLE, Picture.Width * Picture.Height / 256) '创建缓冲区
 '创建Stream
 If CreateStreamOnHGlobal(ByVal hGlobal, False, picStream) = 0 Then
 '转换GUID
 If CLSIDFromString(StrPtr(ClsidJPEG), tGUID) = 0 Then
 '设置JPG相关参数值
 tParams.Count = 1
 With tParams.Parameter(0)
 CLSIDFromString StrPtr(EncoderQuality), .GUID
 .NumberOfValues = 1
 .Type = EncoderParameterValueTypeLong
 .Value = VarPtr(JpegQuality)
 End With
 '将Bitmap数据保存到流(JPG格式)
 If GdipSaveImageToStream(lBitmap, picStream, tGUID, tParams) = OK Then
 'GetHGlobalFromStream picStream, hGlobal
 
 picStream.Seek 0, STREAM_SEEK_CUR, dwSize '获取图像大小
 lpBuffer = GlobalLock(hGlobal) '获取缓冲区读写指针
 ReDim Buff(dwSize - 1): CopyMemory Buff(0), ByVal lpBuffer, dwSize '读取图像
 GlobalUnlock hGlobal: GlobalFree hGlobal '释放分配的缓冲区空间
 PictureToByteArray = Buff
 End If
 End If
 Set picStream = Nothing
 End If
 End If
 GdipDisposeImage lBitmap
 GdiplusShutdown lngGdipToken
 End Function
 
 'By TZWSOHO
 '从字节数组转换为流再转换为图像
 Public Function ByteArrayToPicture(sBuf() As Byte) As StdPicture
 Dim picStream As IStream
 Dim lBitmap As Long
 Dim hBitmap As Long
 Dim lngGdipToken As Long
 Dim tPictDesc As PICTDESC
 Dim IID_IPicture As IID
 Dim oPicture As IPicture
 Dim hGlobal As Long, lpBuffer As Long
 
 lngGdipToken = StartUpGDIPlus(GdiPlusVersion)
 
 hGlobal = GlobalAlloc(GMEM_MOVEABLE, UBound(sBuf) + 1) '创建缓冲区
 lpBuffer = GlobalLock(hGlobal) '获取缓冲区读写指针
 CopyMemory ByVal lpBuffer, sBuf(0), UBound(sBuf) + 1 '复制字节数组内容到缓冲区
 '创建Stream
 If CreateStreamOnHGlobal(ByVal hGlobal, False, picStream) = 0 Then
 '从Stream加载Bitmap
 If GdipLoadImageFromStream(picStream, lBitmap) = OK Then
 '根据Bitmap创建hBitbmp
 If GdipCreateHBITMAPFromBitmap(lBitmap, hBitmap, 0) = OK Then
 With tPictDesc
 .cbSizeOfStruct = Len(tPictDesc)
 .picType = vbPicTypeBitmap
 .hgdiObj = hBitmap
 .hPalOrXYExt = 0
 End With
 
 ' 初始化IPicture
 With IID_IPicture
 .Data1 = &H7BF80981
 .Data2 = &HBF32
 .Data3 = &H101A
 .Data4(0) = &H8B
 .Data4(1) = &HBB
 .Data4(3) = &HAA
 .Data4(5) = &H30
 .Data4(6) = &HC
 .Data4(7) = &HAB
 End With
 
 Call OleCreatePictureIndirect(tPictDesc, IID_IPicture, True, oPicture)
 Set ByteArrayToPicture = StreamToPicture(picStream)
 End If
 End If
 GlobalUnlock hGlobal: GlobalFree hGlobal '释放分配的缓冲区空间
 Set picStream = Nothing
 End If
 GdipDisposeImage lBitmap
 GdiplusShutdown lngGdipToken
 End Function[/mw_shl_code]上面的代码也不难看出了,若要把Byte()转化为StdPicture,方法是先用CreateStreamOnHGlobal把Byte()转化为IStream,然后再调用魏滔序代码里面的StreamToPicture函数最终转化为StdPicture。
 
 参考上面的代码后可以把图片数据的字节数组输出了,示例代码如下:
 
 [mw_shl_code=vb,true]
 Private Sub cmdCommand1_Click()
 
 Dim bmpData() As Byte
 Dim myStream As IStream
 Dim DataSize As Long
 Dim i As Integer
 
 'bmp图片转换为数据流
 Set myStream = PictureToStream(Me.Picture1.Picture)
 'bmp图片数据流转换为图片
 Me.Picture2.Picture = StreamToPicture(myStream)
 'bmp图片转换为字节数组
 bmpData = PictureToByteArray(Me.Picture1.Picture)
 DataSize = UBound(bmpData)
 'For i = 0 To DataSize - 1'这里速度太慢了,所以用了下面做测试。
 '另外发现我用hex看了示例图片字节数数据并不是下面输出的,或许是上面先转换为jpg的原因,有兴趣的朋友可以找找原因……
 For i = 0 To 100
 txtText1.Text = txtText1.Text & "&H" & Hex(bmpData(i)) & ","
 Next
 
 End Sub[/mw_shl_code]
 
 图片转换流及字节数组   
 参考文章:
 VB6结合GDI+实现内存(Stream)压缩/解压缩JPG(JPEG)图像
 GDI+ IStream、StdPicture、Byte() 互转
 
 
 来自圈子: VB6&VB.Net编程
 | 
 |