Decompressing zlib data from .tmx (Tiled) file

2k views Asked by At

I'm trying to write a .tmx loader that will load the Tiled map data directly into my game. I've already written the Base64 decoder and decoded the string.

However, I receive no output after decompressing the data. I'll walk you through an example so you can see the problem.

The .tmx file, or rather the line of code I'm trying to work with, looks like this:

<data encoding="base64" compression="zlib">
    eJzt1UEKwCAMBMBUsPXi/7+rH9CjSp2BPeWyEEgiAIA/yT3PIO/GXrdKPXUyY63ZPljPPs7iXp2lxPiffxt7AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAtGh4aAGc=
</data>

First, I have the Base64 encoded, zlib compressed data string from the .tmx file:

std::string TmxSample = "eJzt1UEKwCAMBMBUsPXi/7+rH9CjSp2BPeWyEEgiAIA/yT3PIO/GXrdKPXUyY63ZPljPPs7iXp2lxPiffxt7AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAtGh4aAGc=";

I run my Base64 decoder like so:

std::string DecodedTmxSample = Base64::decode(TmxSample);

and get

xœíÕA
À ÀT°õâÿ¿«Ð£J=å²H"

I can only assume that this is correct. I've tried my decoder on Wikipedia examples and it gave me the correct output. Therefore, I am not assuming that my Base64 decoder is wrong. After all, I have output which should at least return some kind of crap after I decompress it, or a stream error.

I am using the zlib library and a copy-paste version of the decompression sample in zpipe.c (the function called int inf(FILE *source, FIle *dest). For this example, I quickly copied the output (the decoded tmx string) to file. This is the code for the decompression (again, mostly copy-paste)

#define CHUNK 16384
int           ret;
unsigned      have;
z_stream      strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];

strm.zalloc   = Z_NULL;
strm.zfree    = Z_NULL;
strm.opaque   = Z_NULL;
strm.avail_in = 0;
strm.next_in  = Z_NULL;
ret           = inflateInit(&strm);

FILE *file;
// Contains decoded data.
file = fopen("testFile", "r");

FILE *dest;
// We write decompressed data to this file.
dest = fopen("testOutFile", "w");

do 
{
    strm.avail_in = fread(in, 1, CHUNK, file);
    strm.next_in  = in;

    do
    {
        strm.avail_out = CHUNK;
        strm.next_out  = out;
        ret            = inflate(&strm, Z_NO_FLUSH);
        have           = CHUNK - strm.avail_out;

    } while (strm.avail_out == 0);

} while (ret != Z_STREAM_END);

Some notes: I have removed the error checking (the example code and my code had plenty) for brevity. I did not receive any error messages during the run. However, the output file is empty, and I don't know why.

1

There are 1 answers

0
J T On

Try this:

do 
{
    if ( strm.avail_in == 0 ){
       strm.avail_in = fread(in, 1, CHUNK, file);
       strm.next_in  = in;
    }
    strm.avail_out = CHUNK;
    strm.next_out  = out;

    ret            = inflate(&strm, Z_SYNC_FLUSH);
    have           = CHUNK - strm.avail_out;

    fwrite ( out, 1, have, dest ); //you forgot this step

} while (ret != Z_STREAM_END);