ZaBa Photomosaic
In 2013 with a friend of mine I started exploring Android. Our main product was ZaBa Photomosaic, an App able to make a photomosaic with images in gallery like this one.
It reached about 100.000 installation in one year, but after Andorid 6.0 we no more update it and since 2021 the App is no more in the Play Store, but it can be still found in external stores like here, and it is described in some blog like here or here. I’m not sure it can be run in most recent Android versions but I hope in the near future to adapt it to modern Android APIs and publish it again.
However the aim of the this page is not to talk about ZaBa Photomosaic itself, but about one of its main component: the PNG Encoder.
The problem
The algorithm to make a photomosaic is quite straight:
- reduce the target image to a very low resolution, like 32×32 (also if 48×48 or 72×72 gives better photomosaic)
- replace each pixel of the low resolution image with a thumbnail of an image whose average color is similar to the color of the pixel. The thumbnail should be at least something like 64×48 to be distinguishable, but 128×96 or bigger gives better results, especially if the image has to be printed.
It is quite probable that the final photomosaic has a very high resolution, like 10.000×7.500 or more. A pixel usually requires 4 bytes (trasparency and RGB), so the raw image uses something like 300MB in RAM (maybe more since it is a Java object).
At that time Android 4.x Jelly Bean was new, devices already had 1GB of RAM, but there were yet a lot of Android 2.x running devices with few hundred MBs of RAM. The Android version of those old devices limited to 16-32 MB the RAM available to one device and our App still had to work also there.
In our solution we couldn’t use directly the Android Bitmap since App was killed by Android as it exceeded 16 MB. So I developed an encoder for PNG that outputs the compressed image chunked, without the need to have the whole image in memory before saving it.
In the App we used it to output a line of thumbnails at once in place of the whole image at once as required by the standard Bitmap class, bypassing the 16MB limit with success (this is an example of memory optimization).
ZaBa PNG Encoder
This is the history of this small library. The encoder is quite simple, still very effective: with opportune code you can create images like 100mln x 75mln pixels, since its memory footprint potentially is as small as a single line of pixels of the image.
Here the Github repository of the encoder: https://github.com/zagonico86/zaba-png-encoder
Feel free to use it in your projects, just please make a reference to the original authors and this website.