[Image-SIG] Patch: Better compression of png-images

Alexey Borzenkov snaury at gmail.com
Mon Jul 27 15:52:31 CEST 2009


Hi again,

I found what was the real problem with Z_NO_FLUSH. The code was only
checking that it ran out of output buffer, but when it does it can
usually mean that not all input was deflated. However, when it enters
ZipEncode next time, the data that was not deflated in the previous
round is forgotten and discarded (by overwriting next_in), thus it was
making holes in dicompressed data, which turned into corrupt png
images. The following patch (I hope) fixes it properly:

http://git.kitsu.ru/patched/pil.git?a=commitdiff;h=3f199f00ec63237ad3bf2d8895a2e16605c8c08a

diff --git a/libImaging/ZipEncode.c b/libImaging/ZipEncode.c
index 11e000c..e2480d3 100644
--- a/libImaging/ZipEncode.c
+++ b/libImaging/ZipEncode.c
@@ -69,6 +69,8 @@ ImagingZipEncode(Imaging im, ImagingCodecState
state, UINT8* buf, int bytes)
 	context->z_stream.zalloc = (alloc_func)0;
 	context->z_stream.zfree = (free_func)0;
 	context->z_stream.opaque = (voidpf)0;
+	context->z_stream.next_in = 0;
+	context->z_stream.avail_in = 0;

 	err = deflateInit2(&context->z_stream,
 			   /* compression level */
@@ -103,6 +105,27 @@ ImagingZipEncode(Imaging im, ImagingCodecState
state, UINT8* buf, int bytes)
     /* Setup the destination buffer */
     context->z_stream.next_out = buf;
     context->z_stream.avail_out = bytes;
+    if (context->z_stream.next_in && context->z_stream.avail_in > 0) {
+	/* We have some data from previous round, deflate it first */
+	err = deflate(&context->z_stream, Z_NO_FLUSH);
+
+	if (err < 0) {
+	    /* Something went wrong inside the compression library */
+	    if (err == Z_DATA_ERROR)
+		state->errcode = IMAGING_CODEC_BROKEN;
+	    else if (err == Z_MEM_ERROR)
+		state->errcode = IMAGING_CODEC_MEMORY;
+	    else
+		state->errcode = IMAGING_CODEC_CONFIG;
+	    free(context->paeth);
+	    free(context->average);
+	    free(context->up);
+	    free(context->prior);
+	    free(context->previous);
+	    deflateEnd(&context->z_stream);
+	    return -1;
+	}
+    }

     for (;;) {

@@ -237,12 +260,7 @@ ImagingZipEncode(Imaging im, ImagingCodecState
state, UINT8* buf, int bytes)
 		context->z_stream.next_in = context->output;
 		context->z_stream.avail_in = state->bytes+1;

-		/* err = deflate(&context->z_stream, Z_NO_FLUSH); */
-
-                /* FIXME: temporary workaround for problem with recent
-                   versions of zlib -- 990709/fl */
-
-		err = deflate(&context->z_stream, Z_SYNC_FLUSH);
+		err = deflate(&context->z_stream, Z_NO_FLUSH);

 		if (err < 0) {
 		    /* Something went wrong inside the compression library */


More information about the Image-SIG mailing list