Inflate (decompress) PNG file using ZLIB library C++ -
i'm trying use zlib inflate (decompress) .fla files, extracting contents. since fla files use zip format, able read local file headers(https://en.wikipedia.org/wiki/zip_(file_format)) it, , use info inside decompress files.
it seems work fine regular text-based files, when comes binary (i've tried png , dat files), fails decompress them, returning "z_data_error".
i'm unable use minilib library inside zlib, since central directory file header inside fla files differs normal zip files (which why im reading local files header manually).
here's code use decompress chunk of data:
void decompressbuffer(char* compressedbuffer, unsigned int compressedsize, std::string& out_decompressedbuffer) { // init decompression stream z_stream stream; stream.zalloc = z_null; stream.zfree = z_null; stream.opaque = z_null; stream.avail_in = 0; stream.next_in = z_null; if (int err = inflateinit2(&stream, -max_wbits) != z_ok) { printf("error: inflateinit %d\n", err); return; } // set starting point , total data size read stream.avail_in = compressedsize; stream.next_in = (bytef*)&compressedbuffer[0]; std::stringstream strstream; // start decompressing while (stream.avail_in != 0) { unsigned char* readbuffer = (unsigned char*)malloc(max_read_buffer_size + 1); readbuffer[max_read_buffer_size] = '\0'; stream.next_out = readbuffer; stream.avail_out = max_read_buffer_size; int ret = inflate(&stream, z_no_flush); if (ret == z_stream_end) { // store data have left in stream size_t length = max_read_buffer_size - stream.avail_out; std::string str((char*)readbuffer); str = str.substr(0, length); strstream << str; break; } else { if (ret != z_ok) { printf("error: inflate %d\n", ret); // reaches when trying inflate png or dat file break; } // store readbuffer in stream strstream << readbuffer; } free(readbuffer); } out_decompressedbuffer = strstream.str(); inflateend(&stream); }
i have tried zipping single png file , extracing that. doesn't return errors inflate(), doesn't correctly inflate png either, , corresponding values seem first few.
the original file (left) , uncompressed via code file (right):
you things rely on data being text , strings, not binary data.
for example
std::string str((char*)readbuffer);
if contents of readbuffer
raw binary data might contain 1 or more 0 bytes in middle of it. when use c-style string first 0 act string terminator character.
i suggest try generalize it, , remove dependency of strings. instead suggest use e.g. std::vector<int8_t>
.
meanwhile, during transition more generalized way, can e.g.
std::string str(readbuffer, length);
this create string of specified length, , contents not checked terminators.
Comments
Post a Comment