Creating Quality Web Sized PNGs with ImageMagick

Note: This is a post with me messing around with ImageMagick and it’s good food for thought, however as a reader pointed out I accidentally started with a lossy image and turned it to a lossless image which was a mistake on my part.

I recently posted The Battle for Wesnoth – 1.4 picture review, a look at the new version of turn based strategy game. I had uploaded the post and the screenshots from a super fast pc at work. I gave it no thought when it was as easy as clicking a button. No thought until I loaded the blog at home yesterday and I patiently waited as the browser icon kept looping. Scrolling to the Wesnoth post and seeing images were only half loaded, I looked into my images folder and discovered my Wesnoth screenshots took up a whooping 4MB. Yikes! To make matters worse, I had lazily used html image resizing for thumbnails. This was a time warp I’d forgotten with fast networking but a basic html blunder: when writing for a general audience, write for the lowest common denominator. Scrolling my other posts and their images were still loading I thought, if I had visited this page for the first time and it was taking this long to load, I probably would have closed the tab by now.

And such it is on todays modern web. Not everyone has that T3 spliced into their home. On this slow connection, I have learned to be patient but I really like those pages that load quickly. Portable Network Graphics (PNG)’s the graphic format I use are designed for modern networks. A lossless format for good quality images with a reasonable file size for optic networks, cable modems and dsl. A good number of people though still use standard phone modems or experience congested networks and some images can take awhile to download. Well compressed PNG’s can be made though that load reasonably well while maintaining good image quality.

So I decided to find out what I could do to reduce the load of my web graphics. I did numerous tests over differing quality and quantity. I tested all conversions from a standard jpeg photo. The image is scaled down to 500 width (aspect preserved), a good size for viewing on this blog. First of all I have to say that GIMP does this very well – accurate color reproduction, smoothing, no color bleeds, all in a 270K file.

But often I don’t wanna fire up gimp just to convert one image in such instance I like to use ImageMagick’s command line programs: convert/mogrify.

Resizing is simple:

convert -resize 500 a-friend-in-need.jpg a-friend-in-need-500.png

The image produced is as good as quality as the one produced by GIMP but doesn’t particularly do well at compression this image is a whopping 871K which explains alot about my web page load yesterday. So next I reduced the colorspace to 256 to see if this could produce an acceptable image:

Not too bad. At 109K its a good size for the internet but after looking awhile the dithering becomes obvious. The number of colors is a big factor in determining the size of the image. I played with the colors a bit and came to that around 2000 colors as images began to look non-dithered.

convert -resize 500 -colors 2048 -depth 16 -quality 95 a-friend-in-need.jpg a-friend-in-need-500-c256.png

Quality is the compression amount and type. The first digit is the compression level (nine is the highest) and the next digit is compression type (five is adaptive). I also used optipng that can add up to 30% further compression.

optipng -o5 a-friend-in-need-500-c256.png

The images still look a bit too sharp so I used the enhance variable to smooth. Enhance is it’s own filter and will over-rule other variables so setting color and depth needs to be done in another step.

Doing these steps gives me nice quality, lightweight (comparably – 280k) images that I can use for my blog. The final product:

Creating Quality Web Sized PNGs with Imagemagick

To simplify the process, I wrote a script to make it easier:

# resize-image-new - makes new image and resizes.

#ENHANCE - options to enhance image -enhance smoothes rough images

if [[ -z $NAME ]]; then
    echo "resize-image <WIDTHxHEIGHT> <original-image>"

# Convert (SIZE is proportional least value is used and only x needs specifid.)
convert -resize "$SIZE" -enhance "$NAME" "$RESIZEDNAME"

mogrify -colors $COLORS -depth $DEPTH "$RESIZEDNAME"

# Compress PNG
optipng -o5 "$RESIZEDNAME" 

I’d like to be able to learn if I could adapt this script to batch conversions.


About Gen2ly

<3's linux

Posted on 2008-03-17, in Command Line, Design, Linux. Bookmark the permalink. 7 Comments.

  1. Is this a joke? ;-) JPEG will give you the best quality/size ratio if the original image is a real world photo. PNG is not superior, it is meant for different purposes, for example the screenshots you mentioned. But reducing size of a .jpg photograph by reducing its number of colors and smoothing it is way too much.

  2. PNG is made for exactly this purpose! PNG was designed for the next generation web not original 56 baud modems. Remember PNG stands for portable network graphic. To a discerning photographer or artist the differences between png and jpeg are remarkable – bleeding/smearing are all common in compressing jpeg images. you are right about one thing: in filesize jpegs are superior.

  3. I have to say that Vlasta is right. JPEG is meant for photos; use PNG for small images that need to be lossless, like the borders in web layouts! (The name “Network” graphic does not mean it’s meant for all web images!) You say that the JPEG compression artifacts are remarkable, yet you are happy with dithering your photo and smoothing it to blur away the loss of information?

    Tip: increase the compression quality on a JPEG until the filesize is equal to the size of your dithered PNG. *Then* see which one is better. Try it!

  4. You are both right – for general Web design, yes, you should use JPG for photos and PNG for critical areas.

    But if you are a photographer who wants to display photos at full resolution, this PNG method will preserve grain and fine detail while offering a decent reduction in size for web display. This example just seems a bit odd because you are starting from a JPEG (lossy) high-resolution image and moving to a lossless format. But some cameras do not have RAW support, which means all your high-res photos are in a large JPEG file.



  5. I found this blog using google to try to trim my png files. I found that just using -depth 8 with convert/mogrify works better than having to use optipng. It made the files smaller and didn’t lose any image quality.

  6. Just found this, and was incredibly useful for the site that I run (which is naturally image-heavy =P). Thanks for sharing the great info!

  7. Try this for batch conversion of a folder.

    if [[ -z $FOLDER ]]; then
        echo "resize-image  "
    for NAME in $FOLDER/*.jpg
        echo "convert "$NAME" to "$RESIZEDNAME
        # Convert (SIZE is proportional least value is used and only x needs specifid.)
        convert -resize "$SIZE" -enhance "$NAME" "$RESIZEDNAME"
        mogrify -colors $COLORS -depth $DEPTH "$RESIZEDNAME"
        # Compress PNG
        optipng -o5 "$RESIZEDNAME" 

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.

Join 58 other followers

%d bloggers like this: