I am trying to write my own PNG decoder for learning purposes. The code I'm using to decompress the data is below:
//Stores the return code from the inflation stream
int returnCode;
//Tracks amount of data inflated
unsigned int dataReturned;
//Inflation stream
z_stream stream;
//Initalising the inflation state
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = chunkSize;
stream.next_in = compressedPixelData;
//Beginning the inflation stream
cout << "Beginning inflation" << endl;
returnCode = inflateInit(&stream);
//Checks for any errors with the inflation stream
if (returnCode != Z_OK)
throw invalid_argument("Provided file is corrupted or does not use deflate as its compression algorithm");
//Pointing the stream to the output array
stream.avail_out = chunkSize;
stream.next_out = pixelData;
//Inflating the data
returnCode = inflate(&stream, Z_NO_FLUSH);
//Checking for errors
switch (returnCode) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
throw runtime_error("Error while decompressing pixel data. Either out of memory or the file is corrupted.");
}
dataReturned = chunkSize - stream.avail_out;
cout << dataReturned << endl;
//Ending the deflation stream and cleaning up
cout << "Return Code: " << returnCode << endl;
(void)inflateEnd(&stream);
delete[] compressedPixelData;
I get Z_OK as the return code at the end of inflating the chunk. I've double checked and there is only one IDAT chunk in the file, chunkSize
is the size of the chunk taken from the header of the chunk, and both compressedPixelData
and pixelData
are both char arrays allocated with chunkSize
bytes of memory. pixelData
contains the entire contents of the IDAT chunk (excluding the CRC checksum).
Why is the return code still Z_OK
instead of Z_STREAM_END
, once the entire IDAT chunk has been inflated?
As pointed out by Shawn, the decompressed data is larger than the original input data. Increasing the size of stream.avali_out
and the output buffer, pixelData
fixed the issue.