[cairo] Reducing PNG Image Size
Mohit Sindhwani
ml3p at onghu.com
Wed Sep 24 13:02:25 PDT 2008
Hi Carl & Vlad,
Thanks for your replies! I've spent the whole day looking around for
solutions to this and to see what can be done (learnt a lot about PNG
today!) and here is where I'm at right now.
Carl Worth wrote:
> On Wed, 2008-09-24 at 12:36 -0700, Vladimir Vukicevic wrote:
>
>> pngcrush essentially runs the compression algorithm with different
>> settings for the various knobs (window size, etc., iirc), and then
>> picks whatever the best results are. It does a really good job, but
>> it's an expensive process... you essentially end up recompressing the
>> image around a dozen times.
>>
>
> Ah, cool.
>
> So games like that wouldn't make sense in cairo_surface_write_to_png at
> all. But an application making its own calls into libpng could easily do
> things like that.
>
> And as Vlad would say, all applications *should* be doing their own
> calls rather than using cairo_surface_write_to_png.
>
Yes, PNGCrush can be used, but it would be a bit slow for the task that
I have in mind.
Actually, the whole thing started with the fact that I didn't want to go
to pnglib directly and was wondering if PNG support in Cairo went beyond
just writing out the image surface to the file. I've seen the source
and it seemed that it wouldn't do what I wanted, so just wanted to check.
As it turns out, here is what I've learned and got to:
[1] There are ways to compress PNG - the best way, as you mentioned, is
to quantize the colors. What I had read was that at the same color
depth (8 bits), PNG does a better job than GIF.
[2] Naturally, the image surface is a 24-bit or 32-bit surface. As a
result, cairo_surface_write_to_png doesn't consider writing it as an
8-bit color depth file even if there are less than 256 colors in the
image. The files that it writes are grayscale or 32-bit.
[3] It seems that the files produced by cairo_surface_write_to_png are,
however, larger (30%) than a PNG file with the same data and same number
of colors. I saved the file to a PNG, opened it up in Microsoft Paint
and saved it as PNG. The file size is smaller (1.7MB against 2.2MB). I
found that using PNG crush in all its entirety cuts the file size by up
to 30% (in my case), using pngcrush with just "-m 1" is very fast and
cuts the size by about 25%. I think there is still some extra data in
the default file.
[4] To produce smaller size PNG files, quantization is necessary - if
your image data type supports it. Currently, there is nothing in Cairo
that supports this. After a lot of looking around, it seems that
CxImage [1] is quite a nice library - it looks like a fantastic add-on
to what Cairo does. So far, we've been able to use the image_surface to
create a CxImage object and then quantize that down to 256 colors and
save the reduced image to BMP (PNG tomorrow, I hope).
So, that's what I've learnt today.
Just one question: in Cairo, is it easy to know how many unique colors
are used in an image? If it's easy, it might be sensible to try
extending cairo_surface_write_to_png to check if the number of unique
colors in the image is below 256 and write it as a palette based image
that would be much smaller (about 25% of the size of the original).
Thanks for all the help. The time difference between my day (Singapore)
and yours (US) has given me enough time to look around at other things
and I think it's been useful.
I'm enjoying Cairo, thanks :)
Cheers,
Mohit.
9/25/2008 | 4:00 AM.
[1] http://www.xdp.it/cximage.htm
More information about the cairo
mailing list