Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Working on Base-85 Encoder/Decoder Functions
#1
When I learned QB64-PE allows resources to be loaded from memory it re-kindled my interest in encoding methods to put small files in BAS code, like Base64 is used in several programs found here.  One step more space efficient than Base64 is Base85 (also called ASCII85) which outputs smaller encoded data and uses a larger character set, so I started trying to figure it out.  It's been a real challenge as I am not very math savvy and there were no BASIC sources of Base85 out there I could find to study.

Here's what I have so far.  This will take 4 bytes of binary data, convert it to an integer, divide that up and map them to a characterset, outputting 5 bytes of printable characters that can be included in BAS code.  The decoder reverses the process. I have tested these functions on a few files, and they seem to encode/decode ok here - but they is VERY SLOW.  If you would like to try them and/or add some improvements please do (Speed it up if you can).   I'm also working on Base91 too, but it's not ready to post yet.

- Dav

Edit: Updated version.  Now encode/decode much faster.
Code: (Select All)

'==========
'BASE85.BAS - v0.30
'==========
'Base85 Encoder/Decoder Functions.
'Coded by Dav for QB64-PE 3.8.0, SEP/2023

'CREDIT:  Thanks to RhoSigma for helping me make these lightning fast!!


a1$ = Space$(1000000) ' make a 1MB string to test encoder/decoder speed

Print
Print "Original size:"; Len(a1$); "bytes."
Print

t1# = Timer
Print "Encoding"; Len(a1$); "bytes....";
a2$ = Base85Encode$(a1$)
Print Timer - t1#; "secs, output size:"; Len(a2$)
Print
t1# = Timer
Print "Decoding"; Len(a2$); "bytes....";
a3$ = Base85Decode$(a2$)
Print Timer - t1#; "secs, output:"; Len(a3$)
Print

If a1$ = a3$ Then
    Print "Original Data and Decoded Data Match!"
    Print Len(a1$), Len(a3$)
Else
    Print "Original Data and Decoded DO NOT Match!"
    Print Len(a1$), Len(a3$)
End If



Function Base85Encode$ (in$)
    For i = 39 To 125 'Make 85 character set to use
        If i <> 64 And i <> 96 Then c$ = c$ + Chr$(i)
    Next
    Dim v As _Unsigned Long

    t$ = in$ 'make a working copy so in$ isn't changed

    If Len(t$) Mod 4 > 0 Then 'pad needed bytes on end
        a = 5 - Len(t$) Mod 4
        t$ = t$ + Space$(a - 1)
    End If

    out$ = Space$(Len(t$) * 1.25): outb& = 1

    For i& = 1 To Len(t$) Step 4
        v = CVL(Mid$(t$, i&, 4))
        For j& = 4 To 0 Step -1
            p& = 85 ^ j&
            r& = v \ p&
            v = v Mod p&
            Mid$(out$, outb&, 1) = Mid$(c$, r& + 1, 1)
            outb& = outb& + 1
        Next
    Next
    Base85Encode$ = LTrim$(RTrim$(Str$(a))) + out$
End Function

Function Base85Decode$ (in$)
    For i = 39 To 125 'Make an 85 character set
        If i <> 64 And i <> 96 Then c$ = c$ + Chr$(i)
    Next
    Dim v As _Unsigned Long
    t$ = in$ 'use a working copy so in$ isn't changed
    a = Val(Mid$(t$, 1, 1)) 'grab pad number

    out$ = Space$(Len(t$) / 1.25 - 1): outb& = 1

    For i& = 2 To Len(in$) Step 5: v = 0
        For j& = 0 To 4: p& = 85 ^ (4 - j&)
            cv& = InStr(c$, Mid$(t$, i& + j&, 1)) - 1
            v = v + cv& * p&
        Next

        Mid$(out$, outb&, 4) = MKL$(v)
        outb& = outb& + 4

    Next
    Base85Decode$ = Mid$(out$, 1, Len(out$) - a + 1)
End Function

Find my programs here in Dav's QB64 Corner
Reply


Messages In This Thread
Working on Base-85 Encoder/Decoder Functions - by Dav - 09-23-2023, 03:35 AM



Users browsing this thread: 1 Guest(s)