lvandeve / lodepng

PNG encoder and decoder in C and C++.
zlib License
2.06k stars 421 forks source link

load png with custom zlib, why not provide uncompressed size? #69

Closed powof2 closed 6 years ago

powof2 commented 6 years ago

Hi, I'm using standard zlib to load pngs via lodepng, i find it would be much easier to provide uncompressed size for custom zlib_decompress to uncompress data, like this :

// decodeGeneric, line 4720 in lodepng.cpp
scanlines.size = predict; // <--- add this to init the size with predict (the uncompressed size) instead of 0
state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
                                   idat.size, &state->decoder.zlibsettings);

what do you think? what's the correct way to load pngs with custom zlib?

Thank you.

lvandeve commented 6 years ago

An example of using a custom codec is here: https://github.com/google/zopfli/blob/master/src/zopflipng/zopflipng_lib.cc#L171 It's an encoder there, but it's simimar to set a decoder.

An example of using zlib (deflate) with unknown size is here: https://github.com/madler/zlib/blob/master/test/example.c#L258

What you suggest could be interesting: Normally you do not know the decompressed size of a zlib stream beforehand, but in the case of PNG you can of course compute it given width, height, color model etc... It's of course not a trivial computation (with various subtleties about how to end sub-byte pixels at scanlines etc...) but possible. Of course a bad PNG file could contain a zlib stream in it that has a larger size anyway for some reason, so it would never be guaranteed. This may be a possible optimization in the future. For now, it's with unknown size though.

powof2 commented 6 years ago

I said so because there are already 'predict' bytes memory allocated to scanlines, its size is 'predict and expecting decoded size is 'predict' too.

  // here predict bytes memory are allocated (reserved) to scanlines
  if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/
  if(!state->error)
  {
    state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
                                   idat.size, &state->decoder.zlibsettings);
    if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/
  }

but it does not matter since it is possible to decode with unknown size, thank you for the link.

zpul commented 1 year ago

do you have some examples of using standard zlib with lodepng ?