You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
4.5 KiB

---
title: Optimizing PNG images
aliases: /posts/2020-01-20-optimizing-png-images
summary: >
A quick notice about three very handy tools to optimize PNG images on
the command line. They work on linux and macOS. Use jpegtran for JPG
images.
categories: [computerstuff]
tags: [ zsh-shell, fish-shell ]
date: 2020-01-20T20:34:20+01:00
lastmod: 2023-12-26T13:25:16+0000
---
## Optimizing a bunch of images in a directory
I found these commands here coincidentally on a
[pull request](https://github.com/xianmin/hugo-theme-jane/pull/266) at Github.
I found them quite handy :+1:
~~~console
$ find . -type f -name "*.png" -print0 | xargs -0 -I {} optipng -nb -nc "{}"
$ find . -type f -name "*.png" -print0 | xargs -0 -I {} advpng -z4 "{}"
$ find . -type f -name "*.png" -print0 | xargs -0 -I {} pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow "{}"
~~~
## Quickly optimizing only one image
I've set up a function in my `.zaliases` file for this to be done on a single
image aswell:
~~~zsh
function opti() {
optipng -nb -nc "$*";
advpng -z4 "$*";
pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow "$*";
}
~~~
To run all three commands on a single image I just call it like that:
~~~console
$ opti image.png
~~~
That's all the magic it needs.
## Use jpegtran for JPG images
~~~console
$ jpegtran -copy none -optimize -progressive -outfile output.jpg input.jpg
~~~
## Install these tools on your system
On debian or ubuntu
~~~console
$ sudo apt-get install optipng pngcrush advancecomp
~~~
On Arch based distros using pamac
~~~console
$ sudo pamac install optipng pngcrush advancecomp
~~~
(advancecomp is in AUR)
On macOS
~~~console
$ sudo port install optipng pngcrush advancecomp
~~~
or if you use homebrew
~~~console
$ brew install optipng pngcrush advancecomp
~~~
You may know other package managers commands, but I only use these.
## An example
### By filesize
The files taken from the snapshot tool on my macbook.
~~~plain
33K 00_locales.png
61K 01_control-software.png
157K 02_mmdvmhost.png
184K 03_general.png
187K 04_dmrconfig.png
69K 05_exp_mmdvmhost-dmrnetwork.png
212K 06_exp_dmrgw-dmrnetwork1.png
236K 07_exp_dmrgw-dmrnetwork2.png
~~~
Three to four minutes later (all three commands):
~~~plain
17K 00_locales.png
33K 01_control-software.png
81K 02_mmdvmhost.png
98K 03_general.png
97K 04_dmrconfig.png
32K 05_exp_mmdvmhost-dmrnetwork.png
127K 06_exp_dmrgw-dmrnetwork1.png
144K 07_exp_dmrgw-dmrnetwork2.png
~~~
### By view
~~~plain
25K opti_01.png
13K opti_02.png
~~~
![Original image](opti_01.png "This is the unmodified image: `opti_01.png`") ![Optimized image](opti_02.png "And this is the optimized image: `opti_02.png`")
Do you see much difference?
## Using this with the **fish** shell
I added this to my fishs configuration (when I used fish for a while).
~~~fish
# file: "~/.config/fish/functions/opti.fish"
function opti --description "Optimizes .png files"
# Author: Dominic, OE7DRT <dominic@oe7drt.com>
# 2021-04-17
set -e missing
for program in optipng advpng pngcrush
if \! command -v $program > /dev/null
set -a missing $program
continue
end
end
if test -n "$missing"
echo "Could not find executables: $missing"
return 1
end
if test -z $argv[1]
echo "usage: opti <files...>"
return 1
end
set count (count $argv)
for i in (seq 1 $count)
if test ! -f $argv[$i]
echo "Could not read file $argv[$i]..."
continue
end
optipng -nb -nc "$argv[$i]";
advpng -z4 "$argv[$i]";
pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow "$argv[$i]";
end
end
~~~
And I made one for the jpeg version too:
~~~fish
# file: "~/.config/fish/functions/jopti.fish"
function jopti --description "Optimizes .jpg files"
# Author: Dominic, OE7DRT <dominic@oe7drt.com>
# 2021-08-07
set -e missing
for program in jpegtran
if \! command -v $program > /dev/null
set -a missing $program
continue
end
end
if test -n "$missing"
echo "Could not find executables: $missing"
return 1
end
if test -z $argv[1]
echo "usage: jopti <files...>"
return 1
end
set count (count $argv)
for i in (seq 1 $count)
if test ! -f $argv[$i]
echo "Could not read file $argv[$i]..."
continue
end
jpegtran -copy none -optimize -progressive -outfile "$argv[$i]" "$argv[$i]"
end
end
~~~