After understood (with some help…) how work the compress and uncompress functions of zlib library, I’m now trying to understand how deflate and inflate work. As far as i understand, compress is used in a single call, whereas deflate can be called several time.
Having a simple program with a Particle struct (coordinate x, y, z), I can deflate my datas without errors (getting a Z_STREAM_END response) and then inflate them with another z_stream object (Z_STREAM_END response too). But when I tried to display back my datas from the inflate response, I can get the x and y coordinate of my struct by not the third one (z).
I think it’s due to a wrong parameters i gave to my z_stream object for inflate, but I can’t find which one. As far as i understand reading docs and example, that’s how I think z_stream works (this is just an example) :
// Here i give a total memory size for the output buffer used by deflate func
#define CHUNK 16384
struct Particle
{
float x;
float y;
float z;
};
...
// An element to get a single particule and give it to deflate func
Bytef *dataOriginal = (Bytef*)malloc( sizeof(Particle) );
// This var will be used to pass compressed data
Bytef *dataCompressed = (Bytef*)malloc( CHUNK );
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, Z_DEFAULT_COMPRESSION);
strm.avail_out = CHUNK;
strm.next_out = dataCompressed;
int nbrLoop = 2;
int spaceUsed = 0;
int flush;
Particle p;
for (var i = 0; i<nbrLoop; i++){
// set all values equals to 0
memset( &p, 0, sizeof(Particle) );
// insert some random values
p.x = (i+1) * 1;
p.y = (i+1) * 3;
p.z = (i+1) * 7;
//copy this values in a Bytef* elements
memcpy( dataOriginal, &p, sizeof(Particle) );
strm.avail_in = sizeof(dataOriginal);
strm.next_in = dataOriginal;
// If it's the last particle :
if(i == nbrLoop - 1){
flush = Z_FINISH;
}
else{
flush = Z_NO_FLUSH;
}
int response = deflate(&strm, flush);
// I don't get any errors here
// EDIT : Get Z_OK at first loop, the Z_STREAM_END at second (last)
if( res == Z_STREAM_END ){
spaceUsed = CHUNK - strm.avail_out;
}
}
deflateEnd(&strm);
// Trying to get back my datas
Bytef *decomp = (Bytef*)malloc( sizeof(Particle) );
z_stream strmInflate;
strmInflate.zalloc = Z_NULL;
strmInflate.zfree = Z_NULL;
strmInflate.opaque = Z_NULL;
inflateInit(&strmInflate);
// datas i want to get at the next inflate
strmInflate.avail_in = sizeof(Particle);
strmInflate.next_in = dataCompressed;
// Two particles were compressed, so i need to get back two
strmInflate.avail_out = sizeof(Particle) * 2;
strmInflate.next_out = decomp;
int response = inflate( &strmInflate, Z_NO_FLUSH );
// No error here,
// EDIT : Get Z_OK
inflateEnd( &strmInflate );
Particle testP;
memset( &testP, 0, sizeof(Particle) );
memcpy( &testP, decomp, sizeof(Particle) );
std::cout << testP.x << std::endl; // display 1 OK
std::cout << testP.y << std::endl; // display 3 OK
std::cout << testP.z << std::endl; // display 0 NOT OK
Moreover, i thought that calling inflate a second time will allow me to recover datas of my second particle that was created in my for loop but i can’t retrieve it.
Thanks in advance for any help !
strmInflate.avail_in = sizeof(Particle);needs to bestrmInflate.avail_in = spaceUsed;You have to provide inflate all of the data produced by deflate.At the end you want to get
Z_STREAM_ENDfrominflate(), notZ_OK. Otherwise you have not decompressed the entire generated stream.Note that per the documentation in zlib.h, you need to also set
next_inandavail_in(toZ_NULLand0if you like) before callinginflateInit()Depending on the size of the input and output buffers you will be using in the final application, you may need more loops to assure that
deflate()andinflate()can finish their jobs. Please see the example of how to use zlib.