Skip to main content
gamedev.net
🔒 Locked

zlib help

Started by Foot Soldier 5 replies 1.6k views
Original Post
Foot Soldier
Foot Soldier
I am working on a graphical filetype, and in a seperate program I can create it and compress it with zlib. I am working on the C++ functions to acess it, but am hung up on zlib. Basically what I am doing is loading the header and decompressing it, then memcpy'ing it onto a struct. But I get absolutly no results. Here is the relevant code:
int ret;

	FILE *fp=fopen(filename, "rb");

	if(fp == NULL)
		return FIM_NULL_FILEHANDLE;

	int fileSize;

	fseek(fp, 0, SEEK_END);
	fileSize = ftell(fp);
	fileSize /= sizeof(ANIMATION);
	fseek(fp, 0, SEEK_SET);

	FIM_BYTE headerBuffer[sizeof(FIMHEADER)];
	FIM_BYTE headerIn[sizeof(FIMHEADER)];

	file->z.zalloc = Z_NULL;
    file->z.zfree = Z_NULL;
    file->z.opaque = Z_NULL;
    file->z.avail_in = 0;
    file->z.next_in = Z_NULL;
    ret = inflateInit(&file->z);

	do
	{
		file->z.avail_in = fread(headerIn, 1, sizeof(FIMHEADER), fp);

		if(file->z.avail_in == 0)
			break;

		file->z.next_in = headerIn;

		do
		{
			file->z.avail_out = sizeof(FIMHEADER);
			file->z.next_out = &file->header;

			ret = inflate(&file->z, Z_NO_FLUSH);
           
            switch (ret) 
			{
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;     //fall through
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&file->z);
                return ret;
            }
		} while (file->z.avail_out == 0);

	} while(ret != Z_STREAM_END);

	(void)inflateEnd(&file->z);

	memcpy(&file->header, headerBuffer, sizeof(FIMHEADER));

Any help from someone who has wrassled with zlib before would be very appreciated.
Sure is a big 'ol world.
Evil Steve
Evil Steve
What do you mean by you "get no results"? I can't see anything immediately wrong with the code, although you might want to use memset() instead of zeroing the values manually.
Here's the function I use (Calls pfnAppend() to copy data into the buffer):
typedef int (*LPAppend)(unsigned char* pBuffer, unsigned long dwLen, void* pContext);#define RET_CONTINUE 0#define RET_STOP     1#define RET_ERROR    2bool ZLibDecompress(unsigned char* pBuffer, unsigned int dwLen, LPAppend pfnAppend, void* pContext){z_stream theStream;unsigned char byBuffer[1024];int nRet, nFuncRet;	// Begin compression //	memset(&theStream,0,sizeof(theStream));	if(inflateInit(&theStream) != Z_OK)		return false;	// Flush stream //	theStream.next_in = pBuffer;	theStream.avail_in = dwLen;	do {		theStream.next_out = byBuffer;		theStream.avail_out = 1024;		nRet = inflate(&theStream,Z_NO_FLUSH);		if((nRet != Z_OK) && (nRet != Z_STREAM_END))		{			inflateEnd(&theStream);			return false;		}		nFuncRet = pfnAppend(byBuffer,1024-theStream.avail_out,pContext);		if(nFuncRet == RET_ERROR)		{			inflateEnd(&theStream);			return false;		}	} while((nRet != Z_STREAM_END) && (nFuncRet != RET_STOP));	// Finish up //	inflateEnd(&theStream);	return true;}
Foot Soldier
Foot Soldier
What I mean is, the structure I memcpy it into is all blank. I feel the problem is getting to data from an array into a struct. What is the best way to do this?
Sure is a big 'ol world.
Evil Steve
Evil Steve
Oh, I see the problem. You tell zlib that you want it to output to file->header, and then your memcpy call copies data into file->header again, from headerBuffer, which hasn't been filled yet.
If you change file->z.next_out = &file->header; to file->z.next_out = headerBuffer; it should work.
Foot Soldier
Foot Soldier
I origonally had it that way, and have since changed it back. I posted source in the middle of experimenting, and didn't realize I had left that.

Here is what I think, but lack the knowledge of zlib to know for sure:

When I set avail_in, I am setting it to the size of a decompressed FIMHEADER struct. WHat I need to do is set it to the amount of compressed data though, right? Would it be a good idea to read in the entire file, then memcpy parts of it from the array?

Also, thank you very much for your help Steve. I appreaciate it.
Sure is a big 'ol world.
Evil Steve
Evil Steve
Quote:
Original post by Foot Soldier
When I set avail_in, I am setting it to the size of a decompressed FIMHEADER struct. WHat I need to do is set it to the amount of compressed data though, right?
Yes, avail_in is how much data there is for zlib to process - i.e. how much compressed data. avail_out is the amount of buffer space availiable for zlib to extract to.

Quote:
Original post by Foot Soldier
Would it be a good idea to read in the entire file, then memcpy parts of it from the array?
That depends on how large the file is. It might be a good idea to do this if the file is fairly small (under 4 or 5 Mb), since it'll get it all done in one block, which zlib will probably prefer. However, over 4 or 5 Mb, and you'll be eating up a bit of memory. Although 4 or 5 Mb is nothing too much, it could still be put to better use, and large allocations can be slow I've found. Also, if you want to use a buffer on the stack, you only have 1Mb of stack in total to play with. So you'll probably have around 1000k free to make into a buffer, and it'll be freed when your function returns.

Quote:
Original post by Foot Soldier
Also, thank you very much for your help Steve. I appreaciate it.
No problem, glad I can be of assistance [smile]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.