PNG Image Optimisation

filled under:
February 14, 2011 

I did some research at work for PNG image optimization, to find out what are the best tools to compress PNG RGBA to paletted png with alpha channel, that would also fit into a good workflow.
In previous projects it was common to compress each picture individually and that, of course, was a long and repeating process. Screen’s often change during development and if you need to do a task over and over again, you might end up finding a solution that shortens the process.

My goal was find a solution and tools that would cover the following things:

  • Tools that are available on linux and OSX from commandline, to execute them via script
  • a good compression ratio in a short amount of time
  • Tools that transcode from rgba to paletted images with alpha cannel
  • Tools that can read, modify (optional) and delete Header-Chunks
  • Tools have to be opensourced or must be at least for free

For comparsion I’ve choose the following tools:

Tested Tools

Here is a brief overview of what matters: Short description + usage example. When I mention quantize, i mean the reductions of colors from rgba to a paletted color map with alpha channel.

Pngcrush

Can not quantize as described above but processes fast when optimizing the IDAT Stream.
Usage: pngcrush -reduce alpha24.png alpha24-crushed.png

Pngrewrite

Can handle only paletted images but the result then is very good.
Usage: pngrewrite alpha24.png alpha24-pngrewrite.png

ImageMagick

Comes with a hugh amount of features but is no good choice for compression, it produces partial bigger file sizes than the original. I was not able to archive any good results – thus I’m just mention it here for the completeness, but do not enlist it in the charts.

Pngnq

Can not quantize as described above but works very well for all other purposes.
Usage: pngnq -s1 -e"-nq256.png" -v alpha24.png

PNGOUT

The main feature is quantisation as we want it and it does the job very well. It “Quantizes a 32-bit RGBA PNG image to an 8 bit RGBA palette PNG using the neuquant algorithm”.
Usage: pngout alpha24.png alpha24-pngout-default.png

OptiPNG

Is seems to be very similar to Pngcrush (the Author states that OptiPNG is inspired by Pngcrush) but the results are a little bit better and the arguments differs.
Usage: optipng -full alpha24.png -out alpha24-optipng-full.png

Feature Overview

Benchmark and Comparsion

I’ve taken one RGBA TrueColor image with a dimension of 300×300, with lossless compression. The arguments used, are those in the usage examples described earlier.

Original file size in Bytes “4739″

tool size after optimization Saved Bytes
pngcrush 3954 785
optipng 3953 786
pngrewrite can’t handle format 0
pngnq 3344 1395
pngout 4096 634

As you can see, pngnq had the best results and therefor I’ll use it for the next step.

tool size after optimization Saved Bytes
pngcrush 3344 0
optipng 3329 15
pngrewrite 2604 740
pngout 2866 478

That means I’ve saved 2135 bytes and the optimised image is only 45,05% of the original file size. In comparsion to ImageOptim, that is a GUI App for OSX and only can save up to 25,5% (74,5% of original file size), the result ist pretty impressing. It is worth to mention, that none of the Adobe Products, besides Fireworks, can produce 8bit-paletted-with-alpha images.

Note:
The optimisation is meant for UI-images. Sprites, buttons, etc – not for user generated content or similar.

Buildprocess

If you need to do a task over and over again: automate it ;)

My idea is to have a source image in full quality, that gets processed via a script and then gets stored into a destination folder. However, some images needs a special treatment and therefore it makes sense to have a configuration file.

In order to not process images twice, you could modify the iTxt for instance, to mark it as processed and if the image has such header chunk – do not process it. If you drop a new image into the source folder, the image doesn’t have the chunk, thus it gets processed. But that’s just micro-tuning, because pngnq and pngrewrite are fast enough … IMHO … because you shouldn’t have more than 10 – 20 images to process.

tags:

Workaround for Zend_Dojo_Form when you render elements individually and dijit.byId() returns ‘undefined’

filled under:
June 11, 2010 

Problem: When you render the form as a whole (i.e: <?php echo $this->form ?>), everything works fine, but when you render each element separate, the zendDijit {"id":"yourFormId","params":{"dojoType":"dijit.form.Form"}} is missing. This causes to break the validation/xhr process, because dijit.byId() returns only an ‘undefined’ value.

Solution: Go to your View, where you render your form and add the following:

$form = $this->form;
$this->dojo()->setDijit($form->getId(), array('dojoType' => 'dijit.form.Form')); 

// add form tag ...
// add elements ...

It took me nearly 3 hours to figure this out ;)
Hope this helps someone.

e-mu 0404 usb control panel won’t display on windows 7 and the default 48KHz issue.

filled under:
November 5, 2009 

Since a few months I had the very strange issue that the default samplerate is 48KHz which caused me to set it manualy each time I wanted to play “normal” encoded audio. When I upgraded to windows 7 the control panel stopped displaying. It launches correctly when windows starts but it won’t open the control panel when i click it – and it’s strangely enough to mention that the pane preview works fine. Since I am listnen to music primary via winamp, I could work around the samplerate issue via the out_aiso plugin, so that I can listnen to music again.

However, the disappearing of the control panel “on screen” can be eventually solved if you do the following very few steps:

  • close the control panel
  • open up rededit
  • navigate to HKEY_CURRENT_USER\Software\Creative Professional\E-MU USB Audio Control Panel
  • delete the following entries: “WindowX”, “WindowY”
  • launch the CP again and you will see it again ;)

The one and only correct way to use sprites.

filled under:
August 11, 2009 

In this post I’ll show you the one and only correct way to use sprites and the very little benefit if you use sprites the wrong way.

It’s in everyones mouth but a lot of people do not understand fully what sprites are supposed to optimize. Well we want so badly to reduce the HTTP requests but as I’ll show you, a lot of people do not understand how to write efficient selectors for sprites.

Here’s a meaningfull chart I’m going to explain a few pixel down.
css sprites the wrong and correct way

The first “wrong way” uses multiple images and no sprites and show you what you might except. For each image a request gets done. 22ms were used.

The second wrong way shows you something, a lot of people wouldn’t have guessed. For each CSS selector a request is made! The reason is, that the Browser does not know that the image has been already requested and requests it again. The browser then, when it does it’s pre-processing understands, that tghe ressource has been already requested and grabs it ideally from the browser-cache. However that’s just 4ms faster than without sprites.

.icon-mail 			{ background: transparent url(images/sprite.png) 0 0 no-repeat }
.icon-mail-add 		{ background: transparent url(images/sprite.png) 0 -40px no-repeat }
.icon-mail-attach 		{ background: transparent url(images/sprite.png) 0 -80px no-repeat }
.icon-mail-delete 		{ background: transparent url(images/sprite.png) 0 -120px no-repeat }
.icon-mail-edit 		{ background: transparent url(images/sprite.png) 0 -160px no-repeat }
.icon-mail-error 		{ background: transparent url(images/sprite.png) 0 -200px no-repeat }
.icon-mail-go 			{ background: transparent url(images/sprite.png) 0 -240px no-repeat }
.icon-mail-link 		{ background: transparent url(images/sprite.png) 0 -280px no-repeat }
.icon-nail-open 		{ background: transparent url(images/sprite.png) 0 -320px no-repeat }
.icon-mail-open-image 	{ background: transparent url(images/sprite.png) 0 -360px no-repeat }

The third and correct way uses one selector containing the sprite and a few others to change only the position of the sprite. As you can see in my fancy chart, the benefit is: 4ms for the whole test document. Thats 5.5 times faster than the first example and unbelievable 4 times faster than the second example, which uses the very same sprite!

.icons { background-image: url(images/sprite.png); background-repeat: none }
.icon-mail 			{ background-position: 0 0 }
.icon-mail-add 		{ background-position: 0 -40px }
.icon-mail-attach 		{ background-position: 0 -80px }
.icon-mail-delete 		{ background-position: 0 -120px }
.icon-mail-edit 		{ background-position: 0 -160px }
.icon-mail-error 		{ background-position: 0 -200px }
.icon-mail-go 			{ background-position: 0 -240px }
.icon-mail-link 		{ background-position: 0 -280px }
.icon-nail-open 		{ background-position: 0 -320px }
.icon-mail-open-image 	{ background-position: 0 -360px }

ps: You need something like firebug or httpwatch to check it for yourself.

tags:

life moves pretty fast

filled under:
July 9, 2009 

Every once in a while I write something really personal – and today is such day. As I’ve posted earlier on my flicker account, my step dead died a lonesome death. A few weeks have passed and all I can say is that time moves pretty fast. Your Mom gives birth and it’s you – your parents raise you and especially when you’re young – time moves so slow – you can’t become old enougth to early. However – the older one become, the faster lifes moves. Not forgetting: the faster it goes on – the less we do remember certain things. Less we wonder and slowly we loose the ability to be surprised.

This post is personal – as I’ve already mentioned – and I guess I am in the position to say that I’ve matured without becoming old. And for my step dad – I’d arrogate to oneself that i knew him that much, that he was a good person suffered a great burden he was unable to fight. Over a few years he has supported me financially and personal – because as he stated – he was able to at that time. I know he had a good reputation and people liked him for his honesty and the ability to say whats important. The sadly part about it – he wasn’t able to do all the good things to himself – which he adviced to others. It’s always easy to give good advice …

And the good thing is – he’ll be in my heart – forever. No matter how fucked up the situations sometimes was with him … he tought me a few essential things I continue to teach aswell to others:

  • have a real opinion
  • believe in yourself
  • it doesn’t matter what other people say – as long as you don’t betray yourself

In two weeks will be the ceremony and I guess it’s my first funeral after all … and the family will come together – after long period of being not together.

May he rest in peace and whatever he has wished for shall come true in eternity.
Word!

PS: A few links I’ve just discovered about him (in german):

tags:

if your svn is obstructed

filled under:
May 28, 2009 

try to run a cleanup and remove all obstructed files from your local copy. Or better said: copy them to a save place! Now remove all .svn dirs from your copy and run an update on your local project and copy back the »obstructed« dirs/files. Hit refresh and commit it. That should fix the “obstructed” files.

The reason might be, you’ve copied from another repos some files – including – some .svn dirs.

tags:

Permission denied in Unknown on line 0

filled under:
May 13, 2009 

if you install apache/php and get the following error:
Warning: Unknown: failed to open stream: Permission denied in Unknown on line 0
Then consider to check the permissions.

What user/group has the apache?
ps -ef | grep apache

Who owns the files in your htdocs?

Because it is most likely that you need to chown your htdocs, and or add a user to the correct group.

tags:

no fun with server

filled under:
May 1, 2009 

At work we’ve ordered a new server and I’ve installed and configured apache, mysql, php5 and lighty + some tools, when spontaneously ‘less’ died and also ‘vim’ broke. Then mysql didn’t start, because ‘There’s not enough space in /var/lib/mysql/’ and the eth0 changes I made broke aswell. reinstalling mysql didn’t solve it – actually the installation broke. Dependencies errors and the same ol ‘not enough space’ stuff. ‘Dmesg’ is reporting ‘Invalid field in CDB’ a few times and that eth0: link is not ready…

This is a fresh server with 500gig and only 1% is in use – so there is space and I guess there is something else wrong. fsck ‘mention’ that the superblock is corrupted. Well ok – I know it is not so wise to run fsck on a running mashine – it would be more wise from lilo or a live cd – but it is a ‘managed OS’ so the hoster do not provide such thing. If the worse get worse, I can call them and let em reinstall everything but all my configurations would be lost – or at least I had to copy my configs to the new one.

Right now I am in fsck’s interactive mode and pushing the confirm button repeatedly and /lost+found is getting affiled.

And then some message:
/dev/sda1: 37458/30277632 Dateien (1.3% nicht zusammenhängend), 2216874/121093945 Blöcke
and the console stands still. no Ctrl+C, no ‘enter’, no nothing works…

*duck*

and then

[LOCAL] : SSH2Core version 4.3.0.371
[LOCAL] : Connecting to netfreaks.de:22 ...
[LOCAL] : Changing state from STATE_NOT_CONNECTED to STATE_EXPECT_KEX_INIT
[LOCAL] : RECV: TCP/IP close
[LOCAL] : Changing state from STATE_EXPECT_KEX_INIT to STATE_CLOSED
[LOCAL] : Connected for 0 seconds, 47 bytes sent, 0 bytes received

it wasn’t me!

tags: