Search code examples
pythonimagezlibpython-imaging-libraryimage-compression

Surprising behaviour of image/string compression with zlib


I am interested in finding out by how much images with different features can be compressed without loss. So I have generated 3 different types of bilevel images (all black, a b/w checkerboard, and a random b/w) and compressed the images using zlib. I have done the same using PIL (pillow) compressing to PNG and got the same results, but for simplicity let's stick to just using zlib (I believe PIL uses zlib as well).

I do the following. I generate a numpy two dimensional array (of type uint8) of 0s and 1s and convert it to bytes (yes I lose information about the shape of the array by doing this). Then I pass the string to zlib that compresses it, and I compare the size of the raw image to that of the compressed image. I do this as a function of number of raw pixels (bytes). A minimal working example can be found here. Up to 1024x1024 bytes the number of compressed bytes vs the number of raw bytes is the following ("raw" is simply the total number of pixels we start with, "comp." stands for compressed and "constant" refers to all 0s, "checkerboard" to repeating 101010 and in "random" each pixel is randomly sampled)

comparison of compressed images

and the ratio of compressed bytes to raw bytes (coloured lines divided by the black line)

enter image description here

I find the outcome strange, probably because I don't understand very well what zlib is doing. Why does the rate of compression change? It is amazingly efficient at first and then it reaches a constant rate (ratio is constant).

For the "constant" (all 0s) example why does the size of the compressed string keeps growing at such a rate when I'm essentially adding little information by adding more 0s? (similar considerations can be made for the checkerboard, since it is periodic)

I expected the size of the compressed image to be somewhat related to its Kolmogorov complexity, but it does not seem to be so.


Solution

  • As noted in the zlib technical notes, the deflate format inherently has a maximum compression ratio of 1032:1. You are saturating the capability of the format when you get to the ratio on your plot of 10-3.