Results 1 to 10 of 10

Thread: VB - How to compress a buffer with ZLIB.dll

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    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:
    1. Private Declare Function Compress Lib "zlib.dll" Alias "compress" (dest As Any, destLen As Any, src As Any, ByVal srcLen As Long) As Long
    2. Private Declare Function Uncompress Lib "zlib.dll" Alias "uncompress" (dest As Any, destLen As Any, src As Any, ByVal srcLen As Long) As Long
    3.  
    4. Private Sub Form_Load()
    5.     Dim Str As String, CompStr As String
    6.     Dim InData() As Byte, OutData() As Byte, DecompData() As Byte, OriginalSize As Long
    7.    
    8.     Str = "Testing... blah blah blah .....   " & String(40, "A") & String(55, "B")
    9.     InData = StrConv(Str, vbFromUnicode)
    10.    
    11.     OriginalSize = UBound(InData) + 1
    12.    
    13.     If CompressData(InData, OutData) Then
    14.         ' save the data or something, you have to save the OriginalSize also
    15.         ' you need it when decompressing...
    16.     End If
    17.    
    18.     Debug.Print "Original: " & UBound(InData) + 1 & " Bytes", "Compressed: " & UBound(OutData) + 1 & " Bytes"
    19.     Debug.Print "Compression rate: " & Format((1 - (CDbl(UBound(OutData)) / UBound(InData))) * 100#, "##0.00")
    20.    
    21.     Erase InData
    22.    
    23.     ' read the data in OutData (in our case right now is actually the IN data)
    24.    
    25.     ReDim DecompData(OriginalSize - 1)
    26.     Uncompress DecompData(0), OriginalSize, OutData(0), UBound(OutData) + 1
    27.    
    28.     Debug.Print "Decompressed string:"
    29.     Debug.Print StrConv(DecompData, vbUnicode)
    30. End Sub
    31.  
    32. Public Function CompressData(InData() As Byte, OutData() As Byte) As Boolean
    33.     Dim BufferSize As Long
    34.     BufferSize = (UBound(InData) + 1) * 1.01 + 12
    35.  
    36.     ReDim OutData(BufferSize)
    37.  
    38.     CompressData = Compress(OutData(0), BufferSize, InData(0), UBound(InData) + 1) = 0
    39.  
    40.     ReDim Preserve OutData(BufferSize - 1)
    41. End Function

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: VB - How to compress a buffer with ZLIB.dll

    How to compress a file:
    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function compress Lib "zlib.dll" (ByVal dest As String, destLen As Long, ByVal source As String, ByVal sourceLen As Long) As Long
    4.  
    5. Private Const PacketSize As Long = 1024& * 256& ' 256 KBytes buffer size
    6.  
    7. Private Const InFile As String = "C:\Test.txt" ' File name to compress
    8. Private Const OutFile As String = "C:\Test.cmp" ' File name compressed
    9.  
    10. Private Sub cmdCompress_Click() ' Command button to compress data
    11.     Dim InFL As Integer, OutFL As Integer
    12.     Dim InBuff As String, OutBuff As String
    13.     Dim InBuffSize As Long, OutBuffSize As Long
    14.    
    15.     InFL = FreeFile
    16.     Open InFile For Binary Access Read Lock Read Write As InFL
    17.    
    18.     OutFL = FreeFile
    19.     Open OutFile For Binary Access Write Lock Read Write As OutFL
    20.        
    21.         ' Do until end of file
    22.         Do Until Loc(InFL) >= LOF(InFL)
    23.             ' Compress PacketSize at one time (if file is very big, 1 Gig for example,
    24.             ' you would not want to load that much in memory)
    25.             ' or however much is left in the file
    26.             InBuffSize = lngMIN(LOF(InFL) - Loc(InFL), PacketSize)
    27.            
    28.             ' read data from file
    29.             InBuff = String(InBuffSize, 0)
    30.             Get InFL, , InBuff
    31.            
    32.             ' calculate maximum size for output
    33.             OutBuffSize = InBuffSize * 1.01 + 12
    34.             OutBuff = String(OutBuffSize, 0)
    35.            
    36.             ' do the actual compression
    37.             compress OutBuff, OutBuffSize, InBuff, Len(InBuff)
    38.            
    39.             ' resize the output buffer to the compressed size
    40.             OutBuff = Left(OutBuff, OutBuffSize)
    41.            
    42.             ' Write the size of compressed buffer
    43.             Put OutFL, , OutBuffSize
    44.             ' Write the size of original (uncompressed) buffer
    45.             Put OutFL, , InBuffSize
    46.             ' Write the compressed data
    47.             Put OutFL, , OutBuff
    48.         Loop
    49.    
    50.     Close InFL, OutFL
    51. End Sub
    52.  
    53. Private Function lngMIN(ByVal N1 As Long, ByVal N2 As Long) As Long
    54.     If N1 < N2 Then
    55.         lngMIN = N1
    56.     Else
    57.         lngMIN = N2
    58.     End If
    59. End Function
    How to decompress the file we just compressed:
    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function uncompress Lib "zlib.dll" (ByVal dest As String, destLen As Long, ByVal source As String, ByVal sourceLen As Long) As Long
    4.  
    5. Private Const InFile As String = "C:\Test.cmp" ' File name compressed
    6. Private Const OutFile As String = "C:\Test out.txt" ' File name decompressed
    7.  
    8. Private Sub cmdDecompress_Click() ' Command button to decompress data
    9.     Dim InFL As Integer, OutFL As Integer
    10.     Dim InBuff As String, OutBuff As String
    11.     Dim InBuffSize As Long, OutBuffSize As Long
    12.    
    13.     InFL = FreeFile
    14.     Open InFile For Binary Access Read Lock Read Write As InFL
    15.    
    16.     OutFL = FreeFile
    17.     Open OutFile For Binary Access Write Lock Read Write As OutFL
    18.        
    19.         ' Do until end of file
    20.         Do Until Loc(InFL) >= LOF(InFL)
    21.             Get InFL, , InBuffSize ' Compressed buffer size
    22.             Get InFL, , OutBuffSize ' Decompressed buffer size
    23.            
    24.             InBuff = String(InBuffSize, 0)
    25.             Get InFL, , InBuff ' Compressed data
    26.            
    27.             OutBuff = String(OutBuffSize, 0) ' allocate buffer
    28.            
    29.             ' Decompress data
    30.             uncompress OutBuff, OutBuffSize, InBuff, Len(InBuff)
    31.            
    32.             ' Write decompressed data to file
    33.             Put OutFL, , OutBuff
    34.         Loop
    35.    
    36.     Close InFL, OutFL
    37. End Sub
    Last edited by CVMichael; Oct 13th, 2006 at 07:32 AM.

  3. #3
    Member
    Join Date
    Mar 2010
    Posts
    33

    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?

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    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...

  5. #5
    Member
    Join Date
    Mar 2010
    Posts
    33

    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.

  6. #6
    Fanatic Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    760

    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
    Last edited by AAraya; Jun 10th, 2017 at 09:08 AM.

  7. #7
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine on fire (country of slaves)
    Posts
    750

    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;
    }
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  8. #8
    Fanatic Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    760

    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
    Last edited by AAraya; Jun 10th, 2017 at 12:36 PM.

  9. #9
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine on fire (country of slaves)
    Posts
    750

    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.
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  10. #10
    Fanatic Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    760

    Re: VB - How to compress a buffer with ZLIB.dll

    Thank you!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width