How to compress PNG files – Three different solutions

PNG (Portable Network Graphics) are great, you should always prefer them over GIFs or JPGs whenever the format suits the image. PNG works best when there are no blurs, faded colors or generally if there are mostly one-colored areas.

A screenshot is probably the best example of an image where PNGs work really good. You’ll get a pretty lossless and sharp screenshot when you use PNGs. Whenever there is a picture out of a camera like the right example above you should use JPG, it will be much smaller and you won’t notice the different compression.

The big problem of PNG is it’s size, out of the box PNGs are pretty big. Luckily there are a few options on how to compress PNG files, which I will show you here.

1. Browser-Beginner: The not every-day-solution

This one is so easy it almost doesn’t need an explanation. Fire up your browser and head over to TinyPNG. Drag and Drop the image onto the hungry panda, done. Well you need to download the file afterwards. It does not get easier than this.

tiny-png-gif-brewery

Disadvantage: The workflow is slow for a whole set of pictures, you can’t download the whole set after compression.

Performance: 329KB reduced to 145KB (–56%)

Will pointed out an alternative png compressor by giftofspeed.com in the comments. This service performs even a little bit better.

Performance: 329KB reduced to 139KB (-58%)

2. Automator-Hero: TinyPNG for every day!

Update: Thanks to a comment from Ingo the service now also works with JPG files. I’ve updated the script.

Especially when you start dealing with many files the browser-solution quickly becomes tedious. But we can automate that whole process so you’ll not have to open the browser by using Mac Automator.

I made a short video for you to follow along, the steps are explained below:

  1. Fire up Automator (CMD + SPACE, “automator”, ENTER)
  2. File -> New, Select “Service”.
  3. In the search field search for “run shell script”, drag the item to the right area.
  4. Setup like this:
    1. “Service receives selected” = “image files”
    2. “in” = “finder”
    3. “Shell” = “/bin/bash/”
    4. “Pass input” = “as arguments”
  5. Paste the following code into the text field below (delete the example code before)
  6. for f in "$@"
    do
    
       echo $f | while IFS= read file
       do
            filename=$(basename $file)
            ext=$(echo ${filename##*.} | tr "[:upper:]" "[:lower:]")
            if [ -f $file ]
            then
                if ( [ $ext == "png" ] || [ $ext == "jpg" ] || [ $ext == "jpeg" ] )
                then
                    JSON=`curl -i --user api:APIKEY --data-binary @$file https://api.tinypng.com/shrink 2>/dev/null  `
                    URL=${JSON/*url\":\"/}
                    URL=${URL/\"*/}
    
                    curl $URL>${file} 2>/dev/null
                fi
            fi
        done
    
    done
    
    afplay /System/Library/Sounds/Submarine.aiff
  7. Request a API Key from TinyPNG
  8. Click the Link in the Email TinyPNG sends you.
  9. Copy the API Key and replace it in the code fragment where it states APIKEY.
  10. File -> Save!
  11. Name the service how you want it to show up in the context menu. (Example: Compress PNGs).
  12. Done! Right click on an image file in the finder an hit “Compress PNGs” to let the magic happen!

Disadvantage: You’re limited to 500 files per month, although I’ve found this to be quite a lot.

Performance: 329KB reduced to 145KB (–56%) – it’s the same service as before.

3. The Designer-Pro: PNG Compression in Photoshop

This example comes last because not everyone uses Photoshop. Also the 2. solution is quite handy even if you have Photoshop. Getting this one to work is really quite easy. Download the Photoshop Plugin on GitHub and follow the instructions on how to install and use it!

Disadvantage: Not quite as small compression as TinyPNG, but there is no limit for the usage!

Performance: 328KB reduced to 170KB (–48%)

In

9 Antworten

  1. Will Mezker

    I usually use http://www.giftofspeed.com/png-compressor/ or https://kraken.io/web-interface which both seem to have the best results for me out of the (20+) online tools I’ve found searching on Google.

    1. With kraken.io’s pro account for the API the automator script would probably be possible as well! Only disadvantage is that you would need to pay for it. I’ll update the article to mention these alternatives! Thanks for the tipp!

      1. Will Mezker

        Thank you for your quick reply, that’s a great tip. Don’t mind paying if it’s a good service.

  2. Awesome. Now you can add support for JPG, too:

    Just override:
    if [ $ext == "png" ]
    With:
    if ( [ $ext == "png" ] || [ $ext == "jpg" ] || [ $ext == "jpeg" ] )

  3. Following the exact example, I can’t get this to work. Is there anything I need on the computer for this to work?
    It seems to run the shell script with no errors, but nothing happens. It doesn’t attempt to connect to the site or anything. Any ideas would be very much appreciated as this would be very helpful for me. Here’s my screenshot

    1. Gritty Dee

      you probably have some invalid characters in your filename, drive with a space on it or something. I also don’t have a solution yet for replacing these characters so it is properly encoded for a server request

      1. You’re right. If the path had any spaces in it the script wouldn’t work. Once they are removed it works perfectly.

  4. Richard Braxhoven

    I don’t get it to work… and i have copy pasted the code so there can’t be any typo and i have copy pasted my API code onto the text APIKEY in the code. But all i get when running it on a png is the Submarine sound…

    I hope somebody can help me with what i’m doing wrong. Thanks a lot.

    MY CODE:

    for f in „$@“

    do

    echo $f | while IFS= read file

    do

    filename=$(basename $file)

    ext=$(echo ${filename##*.} | tr „[:upper:]“ „[:lower:]“)

    if [ -f $file ]

    then

    if ( [ $ext == „png“ ] || [ $ext == „jpg“ ] || [ $ext == „jpeg“ ] )

    then

    JSON=`curl -i –user api:000000000000000000000000 –data-binary @$file https://api.tinypng.com/shrink 2>/dev/null `

    URL=${JSON/*url“:“/}

    URL=${URL/“*/}

    curl $URL>${file} 2>/dev/null

    fi

    fi

    done

    done

    afplay /System/Library/Sounds/Submarine.aiff

  5. 7 interactive™

    Small contribution.
    If 500 images/month is not enough for you, you can „overpass“ the limit creating multiple accounts:

    Just create multiple keys using your email like this
    [youruser]+tinypng1@gmail.com
    [youruser]+tinypng2@gmail.com
    [youruser]+tinypng3@gmail.com
    … you get the idea, u can use anything after the +, it’ll create a „unique“ mail record (on TinyPNG), but it’ll point all the emails to your account.

    Create a list of api keys adding them in an Array on the bash script, then u can randomise the current used api_key:

    – Replace „dummykeyN“ with your actual keys.

    *bummer, brush:* isn’t supported 🙁

    API_KEYS=(
        "dummykey1" #…+tinyurl@gmail.com
        "dummykey2" #…+tinyurl2@gmail.com
        "dummykey3" #…+tinyurl3@gmail.com
    
    )
    # -- get a random key from the array.
    api_user=api:${API_KEYS[(($RANDOM%${#API_KEYS[@]}))]};
    
    for f in "$@"
    do
       echo $f | while IFS= read file
       do
            filename=$(basename $file)
            ext=$(echo ${filename##*.} | tr "[:upper:]" "[:lower:]")
            if [ -f $file ]
            then
                if ( [ $ext == "png" ] || [ $ext == "jpg" ] || [ $ext == "jpeg" ] )
                then
    # here we replace the hardcoded user with the random key …
                    JSON=`curl -i --user @$api_user --data-binary @$file https://api.tinypng.com/shrink 2>/dev/null  `
                    URL=${JSON/*url":"/}
                    URL=${URL/"*/}
                    curl $URL>"${file}" 2>/dev/null
                fi
            fi
        done
    done
    afplay /System/Library/Sounds/Submarine.aiff