⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comp_arithmetic.bas

📁 20多种VB软件的加密与压缩模块
💻 BAS
字号:
Attribute VB_Name = "Comp_Arithmetic"


Option Explicit

'This is a 2 run method

'This is an arithmetic coder
'It works but it's its not the best one
'If you want to use it or test it don't use a testfile which
'has all the characters in it because the requered presicion
'can't be hold in a variable in VB
'if the precision was calculated on the fly, it wouldn't be a problem

Private OutStream() As Byte
Private OutPos As Long
Private OutByteBuf As Integer
Private OutBitCount As Integer
Private Bits_To_Follow As Integer
Private Const BitsToStore As Integer = 30   'at 16 bits precision is not high enough
Private Const MaxValue As Long = 2 ^ BitsToStore

Private Type CharStats
    Count As Long
    LowValue As Variant
    HighValue As Variant
    Range As Variant
End Type
    

'Dit is een arithmetic coder
Public Sub Compress_Arithmetic(ByteArray() As Byte)
    Dim TotFileLen As Long
    Dim Char(256) As CharStats
    Dim TotChars As Integer
    Dim Teller As Long
    Dim LowValue As Long
    Dim First_Qtr As Long
    Dim Half As Long
    Dim Third_Qtr As Long
    Dim HighValue As Long
    Dim RangeValue As Long
    Dim X As Long
    Dim Y As Integer
    Call Init_Arithmetic
'first whe gather statistical data
    TotFileLen = UBound(ByteArray) + 1
    For X = 0 To UBound(ByteArray)
        Char(ByteArray(X)).Count = Char(ByteArray(X)).Count + 1
    Next
    For X = 0 To 255
        If Char(X).Count > 0 Then
            TotChars = TotChars + 1
        End If
    Next
    Teller = 0
    OutStream(0) = TotChars - 1
    OutPos = 1
    For X = 0 To 255
        If Char(X).Count > 0 Then
            OutStream(OutPos) = X
            OutPos = OutPos + 1
            OutStream(OutPos) = Int(Char(X).Count / &H10000) And &HFF
            OutPos = OutPos + 1
            OutStream(OutPos) = Int(Char(X).Count / &H100) And &HFF
            OutPos = OutPos + 1
            OutStream(OutPos) = Char(X).Count And &HFF
            OutPos = OutPos + 1
            Char(X).Range = Char(X).Count / TotFileLen
            Char(X).LowValue = Teller * (1 / TotFileLen)
            Char(X).HighValue = (Char(X).LowValue + Char(X).Range)
            Teller = Teller + Char(X).Count
        End If
    Next
    LowValue = 0
    HighValue = MaxValue - 1
    Half = HighValue / 2
    First_Qtr = Half / 2
    Third_Qtr = Half + First_Qtr
    For X = 0 To UBound(ByteArray)
        RangeValue = HighValue - LowValue + 1
        HighValue = (LowValue + RangeValue * Char(ByteArray(X)).HighValue)
        LowValue = LowValue + RangeValue * Char(ByteArray(X)).LowValue
        Do
            If HighValue < Half Then
                Call Bit_Plus_Follow(0)                 '* Output 0 if in low half. *'
                LowValue = 2 * LowValue
                HighValue = 2 * HighValue + 1        '* Scale up code range.     *'
            ElseIf LowValue >= Half Then                 '* Output 1 if in high half.*'
                Call Bit_Plus_Follow(1)
                LowValue = LowValue - Half
                HighValue = HighValue - Half                     '* Subtract offset to top.  *'
                LowValue = 2 * LowValue
                HighValue = 2 * HighValue + 1                    '* Scale up code range.     *'
            ElseIf LowValue >= First_Qtr And HighValue < Third_Qtr Then            '* Output an opposite bit   *'
                Bits_To_Follow = Bits_To_Follow + 1              '* later if in middle half. *'
                LowValue = LowValue - First_Qtr                 '* Subtract offset to middle*'
                HighValue = HighValue - First_Qtr
                LowValue = 2 * LowValue
                HighValue = 2 * HighValue + 1                    '* Scale up code range.     *'
            Else                                     '* Otherwise exit loop.     *'
                Exit Do
            End If
        Loop
    Next
    Bits_To_Follow = Bits_To_Follow + 1         '* Output two bits that     *'
    If LowValue < First_Qtr Then                '* select the quarter that  *'
        Call Bit_Plus_Follow(0)
    Else                                        '* the current code range   *'
        Call Bit_Plus_Follow(1)
    End If
    Call AddBitsToOutStream(LowValue, BitsToStore)
    Do While OutBitCount > 0
        Call AddBitsToOutStream(0, 1)
    Loop
    ReDim ByteArray(OutPos - 1)
    Call CopyMem(ByteArray(0), OutStream(0), OutPos)
End Sub

Public Sub DeCompress_Arithmetic(ByteArray() As Byte)
    Dim TotFileLen As Long
    Dim InpPos As Long
    Dim InBitPos As Integer
    Dim Tjar As Integer
    Dim Char(256) As CharStats
    Dim CharPos(256) As Long
    Dim TotChars As Integer
    Dim Teller As Long
    Dim LowValue As Long
    Dim First_Qtr As Long
    Dim Half As Long
    Dim Third_Qtr As Long
    Dim HighValue As Long
    Dim RangeValue As Long
    Dim MinRange As Integer
    Dim Value As Long
    Dim SearchValue As Double
    Dim X As Long
    Dim Symbol As Byte
    TotFileLen = 0
    InpPos = 0
    OutPos = 0
    LowValue = 0
    HighValue = MaxValue - 1
    Half = HighValue / 2
    First_Qtr = Half / 2
    Third_Qtr = Half + First_Qtr
'Read used characters
    TotChars = ByteArray(InpPos) + 1
    InpPos = InpPos + 1
    For X = 1 To TotChars
        Tjar = ByteArray(InpPos)
        InpPos = InpPos + 1
        Char(Tjar).Count = ByteArray(InpPos)
        InpPos = InpPos + 1
        Char(Tjar).Count = CLng(Char(Tjar).Count) * 256 + ByteArray(InpPos)
        InpPos = InpPos + 1
        Char(Tjar).Count = CLng(Char(Tjar).Count) * 256 + ByteArray(InpPos)
        InpPos = InpPos + 1
        CharPos(X) = Tjar
        TotFileLen = TotFileLen + Char(Tjar).Count
    Next
    ReDim OutStream(TotFileLen)
    MinRange = 1
    For X = 0 To 255
        If Char(X).Count > 0 Then
            Char(X).Range = Char(X).Count / TotFileLen
            Char(X).LowValue = Teller * (1 / TotFileLen)
            Char(X).HighValue = (Char(X).LowValue + Char(X).Range)
            Teller = Teller + Char(X).Count
            If Char(X).Range < MinRange Then MinRange = Char(X).Range
        End If
    Next
    Value = ReadBitsFromArray(ByteArray, InpPos, InBitPos, BitsToStore)
    Do While OutPos < TotFileLen
        RangeValue = HighValue - LowValue + 1
        SearchValue = (Value - LowValue) / RangeValue
        For X = 1 To TotChars
            If Char(CharPos(X)).LowValue <= SearchValue And Char(CharPos(X)).HighValue > SearchValue Then
                Exit For
            End If
        Next
        Symbol = CharPos(X)
        Call AddCharToArray(OutStream, OutPos, Symbol)
        HighValue = (LowValue + RangeValue * Char(Symbol).HighValue)
        LowValue = LowValue + RangeValue * Char(Symbol).LowValue
        Do                                  '* Loop to get rid of bits. *'
            If HighValue < Half Then
                '* nothing *'                       '* Expand low half.         *'
                LowValue = 2 * LowValue
                HighValue = 2 * HighValue + 1                    '* Scale up code range.     *'
                Value = 2 * Value + ReadBitsFromArray(ByteArray, InpPos, InBitPos, 1)        '* Move in next input bit.  *'
            ElseIf LowValue >= Half Then                 '* Expand high half.        *'
                Value = Value - Half
                LowValue = LowValue - Half                      '* Subtract offset to top.  *'
                HighValue = HighValue - Half
                LowValue = 2 * LowValue
                HighValue = 2 * HighValue + 1                    '* Scale up code range.     *'
                Value = 2 * Value + ReadBitsFromArray(ByteArray, InpPos, InBitPos, 1)        '* Move in next input bit.  *'
            ElseIf (LowValue >= First_Qtr And HighValue < Third_Qtr) Then '* Expand middle half.      *'
                Value = Value - First_Qtr
                LowValue = LowValue - First_Qtr                 '* Subtract offset to middle*'
                HighValue = HighValue - First_Qtr
                LowValue = 2 * LowValue
                HighValue = 2 * HighValue + 1                    '* Scale up code range.     *'
                Value = 2 * Value + ReadBitsFromArray(ByteArray, InpPos, InBitPos, 1)        '* Move in next input bit.  *'
            Else                             '* Otherwise exit loop.     *'
                Exit Do
            End If
        Loop
    Loop
    ReDim ByteArray(OutPos - 1)
    Call CopyMem(ByteArray(0), OutStream(0), OutPos)
End Sub


Private Sub Init_Arithmetic()
    ReDim OutStream(1000)
    OutPos = 0
    OutBitCount = 0
    OutByteBuf = 0
    Bits_To_Follow = 0
End Sub


Private Sub Bit_Plus_Follow(Bit As Integer)
    Call AddBitsToOutStream(CLng(Bit), 1)                    '* Output the bit.          *'
    Do While Bits_To_Follow > 0
        Call AddBitsToOutStream(1 - Bit, 1)            '* Output bits_to_follow    *'
        Bits_To_Follow = Bits_To_Follow - 1            '* opposite bits. Set       *'
    Loop                                           '* bits_to_follow to zero.  *'
End Sub

Private Sub AddBitsToOutStream(Number As Long, Numbits As Integer)
    Dim X As Long
    For X = Numbits - 1 To 0 Step -1
        OutByteBuf = OutByteBuf * 2 + (-1 * ((Number And CDbl(2 ^ X)) > 0))
        OutBitCount = OutBitCount + 1
        If OutBitCount = 8 Then
            OutStream(OutPos) = OutByteBuf
            OutBitCount = 0
            OutByteBuf = 0
            OutPos = OutPos + 1
            If OutPos > UBound(OutStream) Then
                ReDim Preserve OutStream(OutPos + 500)
            End If
        End If
    Next
End Sub

'this function will return a value out of the amaunt of bits you asked for
Private Function ReadBitsFromArray(FromArray() As Byte, FromPos As Long, FromBit As Integer, Numbits As Integer) As Long
    Dim X As Integer
    Dim Temp As Long
    For X = 1 To Numbits
        Temp = Temp * 2 + (-1 * ((FromArray(FromPos) And 2 ^ (7 - FromBit)) > 0))
        FromBit = FromBit + 1
        If FromBit = 8 Then
            If FromPos + 1 > UBound(FromArray) Then
                Do While X < Numbits
                    Temp = Temp * 2
                    X = X + 1
                Loop
                FromPos = FromPos + 1
                Exit For
            End If
            FromPos = FromPos + 1
            FromBit = 0
        End If
    Next
    ReadBitsFromArray = Temp
End Function

'this sub will add a char into the outputstream
Private Sub AddCharToArray(Toarray() As Byte, ToPos As Long, Char As Byte)
    If ToPos > UBound(Toarray) Then ReDim Preserve Toarray(ToPos + 500)
    Toarray(ToPos) = Char
    ToPos = ToPos + 1
End Sub

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -