The best compressor IMHO is simply to regard the input file (graphics e.t.c.) as a large base 256 number.
It satisfies the criteria, every digit in range 0 to 255.
change the whole number to base ten then change from base 10 to base 128, ascii start at 32.
This gives a good compression.
Here is Basiccoder's spritesheet results:
Code: Select all
Length original 48963
Length readable 55958
Length returned 48963
-1
First few characters of the forum readable file
15"Y.-%&a@ -Dr(e0 !ö >@0# "MûPA +èa8tBƒƒƒ
Unfortunately the GMP library is really required to achieve results in a few seconds.
Here is the GMP code for the above result.
Code: Select all
#Include once "gmp.bi"
#include "file.bi"
'convert a decimal string to base b
Function convertDecimaltobase(Byval Base10 As String ,b As String="256",begin As Long=32) As String
Dim As zstring Ptr s
Dim As __mpz_struct answer,id,divd,modd,bb,zero
mpz_init2( @answer,0)
mpz_init2( @id,0)
mpz_init2( @divd,0)
mpz_init2( @modd,0)
mpz_init2( @bb,0)
mpz_init2( @zero,0)
mpz_init_set_str( @id,Base10,10)
mpz_init_set_str( @bb,b,10)
Dim As String acc
Do
mpz_div(@divd,@id,@bb)
mpz_mod(@modd,@id,@bb)
s= mpz_get_str(0, 10, @modd)
acc= Chr(Vallng(*s)+begin)+acc
Mpz_set(@id,@divd)
Loop Until Mpz_cmp(@divd,@zero)=0
Function= acc
mpz_clear(@answer) : mpz_clear(@id) : mpz_clear(@divd)
mpz_clear(@modd) : mpz_clear(@bb) : mpz_clear(@zero)
Deallocate s
End Function
'convert from base b to a decimal string
Function convertbasetoDecimal(Byval Basenum As String ,b As String="256",begin As Long=32) As String
Dim As zstring Ptr s
Dim As String sum
Dim As Ulong u=Valulng(b)
sum=Str(Asc(Left(BaseNum,1))-begin)
Dim As __mpz_struct mul,znum,zsum
mpz_init2( @mul,0)
mpz_init2 (@znum,0)
mpz_init2 (@zsum,0)
mpz_set_str(@zsum,sum,10)
For n As Long=2 To Len(basenum)
Var z=basenum[n-1]
mpz_mul_ui(@mul,@zsum,u)
mpz_set_str(@znum,Str(z-begin),10)
mpz_add(@zsum,@mul,@znum)
Next n
s= mpz_get_str(0, 10, @zsum)
Function= *s
mpz_clear(@mul) : mpz_clear(@znum) : mpz_clear(@zsum)
Deallocate s
End Function
Function compress(f As String,basenum As String="128",begin As Long=32) As String export
Var b=convertbasetoDecimal(f,"256",0)
Return convertDecimaltobase(b,basenum,begin)
End Function
Function uncompress(f As String,basenum As String="128",begin As Long=32) As String export
Var g=convertbasetoDecimal(f,basenum,begin)
Return convertDecimaltobase(g,"256",0)
End Function
Function loadfile(file As String) As String
Var f=Freefile
if FileExists(file)=0 then print file;" not found,press a key":sleep:end
Open file For Binary Access Read As #f
Dim As String text
If Lof(1) > 0 Then
text = String(Lof(f), 0)
Get #f, , text
End If
Close #f
Return text
end function
Sub savefile(filename As String,p As String)
Dim As Integer n
n=Freefile
If Open (filename For Binary Access Write As #n)=0 Then
Put #n,,p
Close
Else
Print "Unable to load " + filename
End If
end sub
dim as string nbase="128"
dim as long ascistart=32
var f=loadfile("spritesheet.png")
var c=compress(f,nbase,ascistart) 'forum readable
''savefile("something.txt",c)
print "Length original ";len(f)
print "Length readable ";len(c)
var r=uncompress(c,nbase,ascistart) 'original returned
print "Length returned ";len(r)
print f=r
print
print "First few characters of the forum readable file"
print
print left(c,50)
sleep
I have both 32 bit and 64 bit GMP static libraries.
I can send them via mediafire if there is interest.
Coupled with a little Win api thing to directly deal with the clipboard, this method would suffice I think.
The
WEB basese 64 encoders (there was use of one quite recently used on the forum) possibly uses a Bigint routine to get that compression edge, rather than a digit to digit method.
Not to take anything away from Mr Swiss's method here, which is pretty good.