Share your advanced PureBasic knowledge/code with the community.
wilbert
PureBasic Expert
Posts: 3942 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Sat Sep 02, 2006 8:57 am
After some experimenting I was able to use the PNG plugin to (un)compress a memory buffer using zlib compression.
Code: Select all
; purebasic 4.0 windows source
UsePNGImageEncoder()
Structure zstream
next_in.l
avail_in.l
total_in.l
next_out.l
avail_out.l
total_out.l
msg.l
state.l
zalloc.l
zfree.l
opaque.l
data_type.l
adler.l
reserved.l
EndStructure
Procedure.l Z_Compress(dest,destLen,source,sourceLen)
Static strm.zstream
strm\next_in = source
strm\avail_in = sourceLen
strm\next_out = dest
strm\avail_out = destLen
strm\zalloc = #Null
strm\zfree = #Null
strm\opaque = #Null
Static zf.l
Static err.l
!extrn _deflateInit_
!pushd _deflateInit_
!popd [s_Z_Compress.v_zf]
err = CallCFunctionFast(zf,@strm,-1,"1.2.3",SizeOf(zstream))
If err <> 0
ProcedureReturn zerr
EndIf
!extrn _deflate
!pushd _deflate
!popd [s_Z_Compress.v_zf]
err = CallCFunctionFast(zf,@strm,4)
!extrn _deflateEnd
!pushd _deflateEnd
!popd [s_Z_Compress.v_zf]
If err <> 1
CallCFunctionFast(zf,@strm)
If err = 0
ProcedureReturn -5
Else
ProcedureReturn err
EndIf
EndIf
PokeL(destLen,strm\total_out)
ProcedureReturn CallCFunctionFast(zf,@strm)
EndProcedure
Procedure.l Z_Uncompress(dest,destLen,source,sourceLen)
Static strm.zstream
strm\next_in = source
strm\avail_in = sourceLen
strm\next_out = dest
strm\avail_out = destLen
strm\zalloc = #Null
strm\zfree = #Null
strm\opaque = #Null
Static zf.l
Static err.l
!extrn _inflateInit_
!pushd _inflateInit_
!popd [s_Z_Uncompress.v_zf]
err = CallCFunctionFast(zf,@strm,"1.2.3",SizeOf(zstream))
If err <> 0
ProcedureReturn zerr
EndIf
!extrn _inflate
!pushd _inflate
!popd [s_Z_Uncompress.v_zf]
err = CallCFunctionFast(zf,@strm,4)
!extrn _inflateEnd
!pushd _inflateEnd
!popd [s_Z_Uncompress.v_zf]
If err <> 1
CallCFunctionFast(zf,@strm)
If err = 0
ProcedureReturn -5
Else
ProcedureReturn err
EndIf
EndIf
PokeL(destLen,strm\total_out)
ProcedureReturn CallCFunctionFast(zf,@strm)
EndProcedure
; see if it works
in = AllocateMemory(100)
out = AllocateMemory(100)
s.s = "Hello hello hello hello hello hello hello hello hello hello hello"
PokeS(in,s)
Debug Len(s)
insize.l = Len(s)
outsize.l = MemorySize(out)
Debug Z_Compress(out,@outsize,in,insize)
Debug outsize
Swap in, out
insize.l = outsize
outsize = MemorySize(out)
Debug Z_Uncompress(out,@outsize,in,insize)
Debug outsize
Last edited by
wilbert on Sat Sep 02, 2006 9:57 am, edited 1 time in total.
wilbert
PureBasic Expert
Posts: 3942 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Sat Sep 02, 2006 9:31 am
Linux version
Code: Select all
; purebasic 3.94 linux source
UsePNGImageEncoder()
Global zf.l
Structure zstream
next_in.l
avail_in.l
total_in.l
next_out.l
avail_out.l
total_out.l
msg.l
state.l
zalloc.l
zfree.l
opaque.l
data_type.l
adler.l
reserved.l
EndStructure
Procedure.l Z_Compress(dest,destLen,source,sourceLen)
Static strm.zstream
strm\next_in = source
strm\avail_in = sourceLen
strm\next_out = dest
strm\avail_out = destLen
strm\zalloc = #Null
strm\zfree = #Null
strm\opaque = #Null
Static err.l
!extrn deflateInit_
!pushd deflateInit_
!popd [v_zf]
err = CallCFunctionFast(zf,@strm,-1,"1.2.3",SizeOf(zstream))
If err <> 0
ProcedureReturn zerr
EndIf
!extrn deflate
!pushd deflate
!popd [v_zf]
err = CallCFunctionFast(zf,@strm,4)
!extrn deflateEnd
!pushd deflateEnd
!popd [v_zf]
If err <> 1
CallCFunctionFast(zf,@strm)
If err = 0
ProcedureReturn -5
Else
ProcedureReturn err
EndIf
EndIf
PokeL(destLen,strm\total_out)
ProcedureReturn CallCFunctionFast(zf,@strm)
EndProcedure
Procedure.l Z_Uncompress(dest,destLen,source,sourceLen)
Static strm.zstream
strm\next_in = source
strm\avail_in = sourceLen
strm\next_out = dest
strm\avail_out = destLen
strm\zalloc = #Null
strm\zfree = #Null
strm\opaque = #Null
Static err.l
!extrn inflateInit_
!pushd inflateInit_
!popd [v_zf]
err = CallCFunctionFast(zf,@strm,"1.2.3",SizeOf(zstream))
If err <> 0
ProcedureReturn zerr
EndIf
!extrn inflate
!pushd inflate
!popd [v_zf]
err = CallCFunctionFast(zf,@strm,4)
!extrn inflateEnd
!pushd inflateEnd
!popd [v_zf]
If err <> 1
CallCFunctionFast(zf,@strm)
If err = 0
ProcedureReturn -5
Else
ProcedureReturn err
EndIf
EndIf
PokeL(destLen,strm\total_out)
ProcedureReturn CallCFunctionFast(zf,@strm)
EndProcedure
; see if it works
in = AllocateMemory(100)
out = AllocateMemory(100)
s.s = "Hello hello hello hello hello hello hello hello hello hello hello"
PokeS(in,s)
Debug Len(s)
insize.l = Len(s)
outsize.l = 100
Debug Z_Compress(out,@outsize,in,insize)
Debug outsize
tmp = in
in = out
out = tmp
insize.l = outsize
outsize = 100
Debug Z_Uncompress(out,@outsize,in,insize)
Debug outsize
Trond
Always Here
Posts: 7446 Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway
Post
by Trond » Wed Feb 07, 2007 5:18 pm
This looks cool, I will see if I can get it to work.
Edit: How do I know how large output buffer I will need?
wilbert
PureBasic Expert
Posts: 3942 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Wed Feb 07, 2007 5:48 pm
It's the more or less the same as the PureZIP_UnpackMemory function from the PureZIP library. In other words ... you don't know and just have to make sure the destination buffer is large enough.
When I wrote this code I needed to decompress a compressed swf file in memory and still be able to use png files. For that purpose it worked fine.
Trond
Always Here
Posts: 7446 Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway
Post
by Trond » Wed Feb 07, 2007 5:54 pm
Is that a bug? It's poking into the memory at location destLen.
wilbert
PureBasic Expert
Posts: 3942 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Wed Feb 07, 2007 7:06 pm
It's supposed to be that way. As a parameter you pass a memory address as you can see in the debug function used to test it. The function itself returns a status code. You pass the address of a variable that after the function is executed should contain the uncompressed size.
Maybe I should have used another variable name to indicate it's the address of a variable that is expected.
Trond
Always Here
Posts: 7446 Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway
Post
by Trond » Wed Feb 07, 2007 7:15 pm
But here it wants the value? Or is it still supposed to be the pointer?
wilbert
PureBasic Expert
Posts: 3942 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Wed Feb 07, 2007 7:36 pm
As far as I know the pointer.
I used uncompr.c from the zlib library as an example but c is not my specialty
You might want to look at that file but for me it has worked so far.
Num3
PureBasic Expert
Posts: 2812 Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:
Post
by Num3 » Wed Feb 07, 2007 9:38 pm
Genial!
One of the Best Tips'&'Tricks...
Trond
Always Here
Posts: 7446 Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway
Post
by Trond » Thu Feb 08, 2007 8:05 pm
It's a great trick that works very well, but this time I think I found a real bug. Shouldn't zerr be err?
Code: Select all
If err <> 0
ProcedureReturn zerr
EndIf
Num3
PureBasic Expert
Posts: 2812 Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:
Post
by Num3 » Thu Feb 08, 2007 9:13 pm
Trond wrote: It's a great trick that works very well, but this time I think I found a real bug. Shouldn't zerr be err?
Code: Select all
If err <> 0
ProcedureReturn zerr
EndIf
Did you read VISTA SDK ???
That's the new fail error checking routine
wilbert
PureBasic Expert
Posts: 3942 Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands
Post
by wilbert » Thu Feb 08, 2007 10:11 pm
Trond wrote: Shouldn't zerr be err?
You are right of course
I just never got an error so I didn't notice the problem.
Trond
Always Here
Posts: 7446 Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway
Post
by Trond » Thu Feb 08, 2007 10:14 pm
I didn't get an error either, but I turned on EnableExplicit.
javabean
User
Posts: 60 Joined: Sat Nov 08, 2003 10:29 am
Location: Austria
Post
by javabean » Tue Feb 16, 2010 7:59 pm
Just a little modification of wilberts code: manual import of the deflate and inflate functions from a lib without making use of ImagePluginPNG.
Code: Select all
ImportC "zlib.lib"
inflateInit(*strm.l,*version.l,stream_size.l) As "_inflateInit_@12"
inflate(*strm.l,flush.l) As "_inflate@8"
inflateEnd(*strm.l) As "_inflateEnd@4"
deflateInit(*strm.l,level.l,*version.l,stream_size.l) As "_deflateInit_@16"
deflate(*strm.l,flush.l) As "_deflate@8"
deflateEnd(*strm.l) As "_deflateEnd@4"
EndImport
Structure zstream
next_in.l
avail_in.l
total_in.l
next_out.l
avail_out.l
total_out.l
msg.l
state.l
zalloc.l
zfree.l
opaque.l
data_type.l
adler.l
reserved.l
EndStructure
#Z_OK = 0
#Z_STREAM_END = 1
#Z_NEED_DICT = 2
#Z_ERRNO = -1
#Z_STREAM_ERROR = -2
#Z_DATA_ERROR = -3
#Z_MEM_ERROR = -4
#Z_BUF_ERROR = -5
#Z_VERSION_ERROR = -6
#Z_NO_FLUSH = 0
#Z_PARTIAL_FLUSH = 1
#Z_SYNC_FLUSH = 2
#Z_FULL_FLUSH = 3
#Z_FINISH = 4
#Z_BLOCK = 5
Global version$ ="1.2.3"
Procedure.l Z_Compress(*dest.l,*destLen.l,*source.l,sourceLen.l)
Static strm.zstream
strm\next_in = *source
strm\avail_in = sourceLen
strm\next_out = *dest
strm\avail_out = *destLen
strm\zalloc = #Null
strm\zfree = #Null
strm\opaque = #Null
Static err.l
err.l = deflateInit(@strm,-1,@version$,SizeOf(zstream))
If err <> 0
ProcedureReturn err
EndIf
err = deflate(@strm,#Z_FINISH)
If err <> 1
deflateEnd(@strm)
If err = 0
ProcedureReturn #Z_BUF_ERROR
Else
ProcedureReturn err
EndIf
EndIf
PokeL(*destLen,strm\total_out)
ProcedureReturn deflateEnd(@strm)
EndProcedure
Procedure.l Z_Uncompress(*dest.l,*destLen.l,*source.l,sourceLen.l)
Static strm.zstream
strm\next_in = *source
strm\avail_in = sourceLen
strm\next_out = *dest
strm\avail_out = *destLen
strm\zalloc = #Null
strm\zfree = #Null
strm\opaque = #Null
Static err.l
err.l = inflateInit(@strm,@version$,SizeOf(zstream))
If err <> 0
ProcedureReturn err
EndIf
err = inflate(@strm,#Z_FINISH)
If err <> 1
inflateEnd(@strm)
If err = 0
ProcedureReturn #Z_BUF_ERROR
Else
ProcedureReturn err
EndIf
EndIf
PokeL(*destLen,strm\total_out)
ProcedureReturn inflateEnd(@strm)
EndProcedure
; see if it works
in = AllocateMemory(100)
out = AllocateMemory(100)
s.s = "Hello hello hello hello hello hello hello hello hello hello hello"
PokeS(in,s)
Debug "Uncompressed: " + PeekS(@s)
insize.l = Len(s)
outsize.l = MemorySize(out)
Debug Z_Compress(out,@outsize,in,insize)
Debug "Compressed: "+ PeekS(out,outsize)
Swap in, out
insize.l = outsize
outsize = MemorySize(out)
Debug Z_Uncompress(out,@outsize,in,insize)
Debug "Uncompressed: "+ PeekS(out,outsize)
ts-soft
Always Here
Posts: 5756 Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany
Post
by ts-soft » Tue Feb 16, 2010 8:16 pm
a bit shorter and crossplattform:
Code: Select all
; Autor: Thomas (ts-soft) Schulz
; PB-Version: 4.xx
; OS: windows/linux/MacOS
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
ImportC #PB_Compiler_Home + "purelibraries/linux/libraries/zlib.a"
CompilerCase #PB_OS_MacOS
ImportC "/usr/lib/libz.dylib"
CompilerCase #PB_OS_Windows
ImportC "zlib.lib"
CompilerEndSelect
compress2(*dest, *destLen, *source, sourceLen, level)
uncompress(*dest, *destLen, *source, sourceLen)
EndImport
Procedure zipPackMemory(*source, sourceLen = #PB_Default, level = #PB_Default)
Protected *dest, destLen
If level < #PB_Default Or level > 9 : level = #PB_Default : EndIf
If *source
If sourceLen = #PB_Default : sourceLen = MemorySize(*source) : EndIf
destLen = sourceLen + 13 + (Int(sourceLen / 100))
*dest = AllocateMemory(destLen)
If *dest
If Not compress2(*dest, @destLen, *source, sourceLen, level)
*dest = ReAllocateMemory(*dest, destLen)
ProcedureReturn *dest
EndIf
EndIf
EndIf
EndProcedure
Procedure zipUnpackMemory(*source, *dest)
Protected sourceLen = MemorySize(*source)
Protected destLen = MemorySize(*dest)
If Not uncompress(*dest, @destLen, *source, sourceLen)
ProcedureReturn destLen
EndIf
EndProcedure
Greetings
Thomas