I didn't hear back, but after reading your post I followed up with another couple emails... the following is what was asked and answered:
Question
In the below code I’m passing a 2mb file for compression, and I thought by using deflateBound the optimized compression size would be returned. But the compressed file size is larger than the original file size; is this to be expected? And is there a correct way to determine the optimized compression size?
Code Included with Question
Code: Select all
Procedure DeflatePayload(*Input, windowBits.i)
LengthToRead = MemorySize(*Input)
strm.Z_STREAM
strm\next_in = *Input
strm\avail_in = LengthToRead
strm\zalloc = #Z_NULL
strm\zfree = #Z_NULL
strm\opaque = #Z_NULL
deflateInit2_(@strm, #Z_DEFAULT_COMPRESSION, #Z_DEFLATED, windowBits, #MAX_MEM_LEVEL, #Z_DEFAULT_STRATEGY, #ZLIB_VERSION, SizeOf(Z_STREAM))
LengthToWrite = deflateBound(@strm, LengthToRead)
*Payload = AllocateMemory(LengthToWrite)
strm\next_out = *Payload
strm\avail_out = LengthToWrite
deflate(@strm, #Z_FINISH)
deflateEnd(@strm)
ProcedureReturn *Payload
EndProcedure
Response
deflateBound() bounds by how much the uncompressed data can possibly be expanded by compression. For example, if you feed random data to a compressor, the result will be larger. deflateBound() must give a number larger than the source length, since by definition a compressor must make some inputs larger. It is the worst case size of the result, allowing the user to allocate a buffer large enough to hold the result.
Question
... trying to figure out how to determine what to set for [ strm\avail_out ] when using [ deflateInit2_ ] in a single pass.
- set it to small and there is data loss
Response
That is what deflateBound() is for.
Additional Information from Website
deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(). This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used.
I still don't know of a way to determine (on a single pass) the best size for output... My guess is not to do it in a single pass, but in a loop monitoring the responses.