VB - How to compress a buffer with ZLIB.dll
If you want to compress data without saving to the drive, for example if you want to compress, and send it right away on a socket over the net. NOTE, you need to send/save the original size of the data, with the compressed data.
VB Code:
Private Declare Function Compress Lib "zlib.dll" Alias "compress" (dest As Any, destLen As Any, src As Any, ByVal srcLen As Long) As Long
Private Declare Function Uncompress Lib "zlib.dll" Alias "uncompress" (dest As Any, destLen As Any, src As Any, ByVal srcLen As Long) As Long
Private Sub Form_Load()
Dim Str As String, CompStr As String
Dim InData() As Byte, OutData() As Byte, DecompData() As Byte, OriginalSize As Long
Str = "Testing... blah blah blah ..... " & String(40, "A") & String(55, "B")
InData = StrConv(Str, vbFromUnicode)
OriginalSize = UBound(InData) + 1
If CompressData(InData, OutData) Then
' save the data or something, you have to save the OriginalSize also
' you need it when decompressing...
End If
Debug.Print "Original: " & UBound(InData) + 1 & " Bytes", "Compressed: " & UBound(OutData) + 1 & " Bytes"
Debug.Print "Compression rate: " & Format((1 - (CDbl(UBound(OutData)) / UBound(InData))) * 100#, "##0.00")
Erase InData
' read the data in OutData (in our case right now is actually the IN data)
ReDim DecompData(OriginalSize - 1)
Uncompress DecompData(0), OriginalSize, OutData(0), UBound(OutData) + 1
Debug.Print "Decompressed string:"
Debug.Print StrConv(DecompData, vbUnicode)
End Sub
Public Function CompressData(InData() As Byte, OutData() As Byte) As Boolean
Dim BufferSize As Long
BufferSize = (UBound(InData) + 1) * 1.01 + 12
ReDim OutData(BufferSize)
CompressData = Compress(OutData(0), BufferSize, InData(0), UBound(InData) + 1) = 0
ReDim Preserve OutData(BufferSize - 1)
End Function
Re: VB - How to compress a buffer with ZLIB.dll
How to compress a file:
VB Code:
Option Explicit
Private Declare Function compress Lib "zlib.dll" (ByVal dest As String, destLen As Long, ByVal source As String, ByVal sourceLen As Long) As Long
Private Const PacketSize As Long = 1024& * 256& ' 256 KBytes buffer size
Private Const InFile As String = "C:\Test.txt" ' File name to compress
Private Const OutFile As String = "C:\Test.cmp" ' File name compressed
Private Sub cmdCompress_Click() ' Command button to compress data
Dim InFL As Integer, OutFL As Integer
Dim InBuff As String, OutBuff As String
Dim InBuffSize As Long, OutBuffSize As Long
InFL = FreeFile
Open InFile For Binary Access Read Lock Read Write As InFL
OutFL = FreeFile
Open OutFile For Binary Access Write Lock Read Write As OutFL
' Do until end of file
Do Until Loc(InFL) >= LOF(InFL)
' Compress PacketSize at one time (if file is very big, 1 Gig for example,
' you would not want to load that much in memory)
' or however much is left in the file
InBuffSize = lngMIN(LOF(InFL) - Loc(InFL), PacketSize)
' read data from file
InBuff = String(InBuffSize, 0)
Get InFL, , InBuff
' calculate maximum size for output
OutBuffSize = InBuffSize * 1.01 + 12
OutBuff = String(OutBuffSize, 0)
' do the actual compression
compress OutBuff, OutBuffSize, InBuff, Len(InBuff)
' resize the output buffer to the compressed size
OutBuff = Left(OutBuff, OutBuffSize)
' Write the size of compressed buffer
Put OutFL, , OutBuffSize
' Write the size of original (uncompressed) buffer
Put OutFL, , InBuffSize
' Write the compressed data
Put OutFL, , OutBuff
Loop
Close InFL, OutFL
End Sub
Private Function lngMIN(ByVal N1 As Long, ByVal N2 As Long) As Long
If N1 < N2 Then
lngMIN = N1
Else
lngMIN = N2
End If
End Function
How to decompress the file we just compressed:
VB Code:
Option Explicit
Private Declare Function uncompress Lib "zlib.dll" (ByVal dest As String, destLen As Long, ByVal source As String, ByVal sourceLen As Long) As Long
Private Const InFile As String = "C:\Test.cmp" ' File name compressed
Private Const OutFile As String = "C:\Test out.txt" ' File name decompressed
Private Sub cmdDecompress_Click() ' Command button to decompress data
Dim InFL As Integer, OutFL As Integer
Dim InBuff As String, OutBuff As String
Dim InBuffSize As Long, OutBuffSize As Long
InFL = FreeFile
Open InFile For Binary Access Read Lock Read Write As InFL
OutFL = FreeFile
Open OutFile For Binary Access Write Lock Read Write As OutFL
' Do until end of file
Do Until Loc(InFL) >= LOF(InFL)
Get InFL, , InBuffSize ' Compressed buffer size
Get InFL, , OutBuffSize ' Decompressed buffer size
InBuff = String(InBuffSize, 0)
Get InFL, , InBuff ' Compressed data
OutBuff = String(OutBuffSize, 0) ' allocate buffer
' Decompress data
uncompress OutBuff, OutBuffSize, InBuff, Len(InBuff)
' Write decompressed data to file
Put OutFL, , OutBuff
Loop
Close InFL, OutFL
End Sub
Re: VB - How to compress a buffer with ZLIB.dll
I have downloaded the latest version of zlib.dll from http://www.zlib.net/, and tied the example from the first post, CompressData, but I get the error "Bad DLL calling convention". Any idea how I can fix it?
Re: VB - How to compress a buffer with ZLIB.dll
Probably you did not download the correct dll for your computer.
So, form here: http://www.winimage.com/zLibDll/index.html
Download "zlib123dll.zip - pre-built zlib DLL, compiled with the Microsoft Visual studio 2003 compiler"
I don't know what version I used when I created this thread...
Re: VB - How to compress a buffer with ZLIB.dll
Thanks CVMichael, I also used the 123 version of the dll, but downloaded from another site, apparently they were different. It works now.
Re: VB - How to compress a buffer with ZLIB.dll
Thanks for this code, it was helpful. I propose a slight "improvement" to your sample code.
In the CompressDate() routine you estimate the size needed for an output buffer using this line of code:
Code:
BufferSize = (UBound(InData) + 1) * 1.01 + 12
I'm not sure where you got this calculation from but there's no need to manually calculate this value since zLib provides a function "CompressBound" which does this work for us. Here's the VB6 declaration and a revised version of your CommitData function:
Code:
Private Declare Function CompressBound Lib "zlib.dll" Alias "compressBound" (ByVal srcLen As Long) As Long
Public Function CompressData(InData() As Byte, OutData() As Byte) As Boolean
Dim BufferSize As Long
BufferSize = CompressBound (UBound(InData) + 1)
ReDim OutData(BufferSize)
CompressData = Compress(OutData(0), BufferSize, InData(0), UBound(InData) + 1) = 0
ReDim Preserve OutData(BufferSize - 1)
End Function
Re: VB - How to compress a buffer with ZLIB.dll
Quote:
Originally Posted by AAraya
I'm not sure where you got this calculation from ...
http://www.gzip.org/zlib/manual.html#compress
Looks like CompressBound() is large than a previous recommendation:
Code:
uLong ZEXPORT compressBound (sourceLen)
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13;
}
Re: VB - How to compress a buffer with ZLIB.dll
Dragokas - thanks for sharing that.
I don't know C# so perhaps you can help me. I see that compressBound returns a uLong data type. So what data type should I used in VB to correctly handle the return from this function - a Currency? Which of these two declarations is correct?
Code:
Private Declare Function CompressBound Lib "zlib.dll" Alias "compressBound" (ByVal srcLen As Long) As Long
OR
Code:
Private Declare Function CompressBound Lib "zlib.dll" Alias "compressBound" (ByVal srcLen As Currency) As Currency
Re: VB - How to compress a buffer with ZLIB.dll
It's C, not C#.
Code:
typedef unsigned long uLong; /* 32 bits or more */
You can cast it to/from VB6 Long (signed long) without data loss.
1-st variant is correct.
Re: VB - How to compress a buffer with ZLIB.dll