Intro to jpegoptim and optipng

In a recent article I went through some of the basics using image optimization with Grunt. Since I went through the steps with Grunt it only seems fitting to share what it looks like when optimizing images with brew packages. For those that are not familiar with brew (i.e Homebrew), it’s a package manager for Mac. Homebrew installs the stuff you need that Apple didn’t.

brew install jpegoptim

jpegoptim is a utility for optimizing JPEG files. It provides lossless optimization (based on optimizing the Huffman tables) and “lossy” optimization based on setting a maximum quality factor.

GrayGhost ✱ grayghostvisualsmacmini.local  ~/httpd/my-project on master*
$ brew install jpegoptim
⇒ Downloading http://www.kokkonen.net/tjko/src/jpegoptim-1.3.0.tar.gz
######################################################################## 100.0%
⇒ ./configure --prefix=/usr/local/Cellar/jpegoptim/1.3.0
⇒ make install
/usr/local/Cellar/jpegoptim/1.3.0: 6 files, 68K, built in 11 seconds
Fig1.0 | Installing jpegoptim via brew. You can also view all the options here
jpegoptim [ options ] [ filenames ]
Fig1.1 | Synatx for jpegoptim
GrayGhost ✱ grayghostvisualsmacmini.local  ~/httpd/my-project on master*
$ jpegoptim img/*.jpg
./my-awesome-project/img/beer-pour.jpg 1200x800 24bit N JFIF  [OK] 100189 --> 100189 bytes (0.00%), skipped.
img/girl-smiling.jpg 1200x800 24bit N JFIF  [OK] 53615 --> 53615 bytes (0.00%), skipped.
img/hero-community.jpg 1200x800 24bit N JFIF  [OK] 94900 --> 94900 bytes (0.00%), skipped.
img/hero-food-for-all.jpg 1200x800 24bit N JFIF  [OK] 108999 --> 108999 bytes (0.00%), skipped.
img/hero-our-story.jpg 1200x800 24bit N JFIF  [OK] 120630 --> 120630 bytes (0.00%), skipped.
img/hero-real-food.jpg 1200x800 24bit N JFIF  [OK] 108079 --> 108079 bytes (0.00%), skipped.
img/hero-slide1.jpg 1161x672 24bit N JFIF  [OK] 253631 --> 253631 bytes (0.00%), skipped.
img/home-grown.jpg 1200x800 24bit P Exif Adobe  [OK] 57106 --> 56729 bytes (0.66%), optimized.
img/location-vha.jpg 1200x800 24bit N JFIF  [OK] 64746 --> 64746 bytes (0.00%), skipped.
img/nav-bg.jpg 203x801 24bit N JFIF  [OK] 49540 --> 49540 bytes (0.00%), skipped.
img/noise-crease.jpg 1200x347 24bit N JFIF  [OK] 165211 --> 165211 bytes (0.00%), skipped.
img/radio-checked.jpg 16x16 24bit N JFIF  [OK] 645 --> 645 bytes (0.00%), skipped.
img/radio-off.jpg 16x16 24bit N JFIF  [OK] 380 --> 380 bytes (0.00%), skipped.
Fig1.2 | Results from execution of jpegoptim

brew install optipng

OptiPNG is a PNG optimizer that re-compresses image files to a smaller size, without losing any information. This program also converts external formats (BMP, GIF, PNM and TIFF) to optimized PNG, and performs PNG integrity checks and corrections. If you wish to learn how PNG optimization works, or to know about other similar tools, see the PNG-Tech article A guide to PNG optimization.

grayghostvisuals ✭ GrayGhostVisualsMacBookAir.local  ~
$ brew install optipng
==> Downloading http://downloads.sourceforge.net/project/optipng/OptiPNG/optipng-0.7.4/optipng-0.7.4.tar.gz
Already downloaded: /Library/Caches/Homebrew/optipng-0.7.4.tar.gz
==> ./configure --with-system-zlib --prefix=/usr/local/Cellar/optipng/0.7.4 --mandir=/usr/local/Cellar/optipng/0.7.4/share/man
==> make install
  /usr/local/Cellar/optipng/0.7.4: 6 files, 184K, built in 2 seconds
Fig1.3 | installing optipng via brew
Synopsis:
    optipng [options] files ...
Files:
    Image files of type: PNG, BMP, GIF, PNM or TIFF
Basic options:
    -?, -h, -help	show this help
    -o 		optimization level (0-7)		[default: 2]
    -v			run in verbose mode / show copyright and version info
General options:
    -backup, -keep	keep a backup of the modified files
    -clobber		overwrite existing files
    -fix		enable error recovery
    -force		enforce writing of a new output file
    -preserve		preserve file attributes if possible
    -quiet, -silent	run in quiet mode
    -simulate		run in simulation mode
    -out 		write output file to 
    -dir 	write output file(s) to 
    -log 		log messages to 
    --			stop option switch parsing
Optimization options:
    -f 	PNG delta filters (0-5)			[default: 0,5]
    -i 		PNG interlace type (0-1)
    -zc 	zlib compression levels (1-9)		[default: 9]
    -zm 	zlib memory levels (1-9)		[default: 8]
    -zs 	zlib compression strategies (0-3)	[default: 0-3]
    -zw 		zlib window size (256,512,1k,2k,4k,8k,16k,32k)
    -full		produce a full report on IDAT (might reduce speed)
    -nb			no bit depth reduction
    -nc			no color type reduction
    -np			no palette reduction
    -nx			no reductions
    -nz			no IDAT recoding
Editing options:
    -snip		cut one image out of multi-image or animation files
    -strip 	strip metadata objects (e.g. "all")
Optimization levels:
    -o0		<=>	-o1 -nx -nz				(0 or 1 trials)
    -o1		<=>	-zc9 -zm8 -zs0 -f0			(1 trial)
    		(or...)	-zc9 -zm8 -zs1 -f5			(1 trial)
    -o2		<=>	-zc9 -zm8 -zs0-3 -f0,5			(8 trials)
    -o3		<=>	-zc9 -zm8-9 -zs0-3 -f0,5		(16 trials)
    -o4		<=>	-zc9 -zm8 -zs0-3 -f0-5			(24 trials)
    -o5		<=>	-zc9 -zm8-9 -zs0-3 -f0-5		(48 trials)
    -o6		<=>	-zc1-9 -zm8 -zs0-3 -f0-5		(120 trials)
    -o7		<=>	-zc1-9 -zm8-9 -zs0-3 -f0-5		(240 trials)
    -o7 -zm1-9	<=>	-zc1-9 -zm1-9 -zs0-3 -f0-5		(1080 trials)
Notes:
    The combination for -o1 is chosen heuristically.
    Exhaustive combinations such as "-o7 -zm1-9" are not generally recommended.
Examples:
    optipng file.png						(default speed)
    optipng -o5 file.png					(slow)
    optipng -o7 file.png					(very slow)
Figure 1.4 | optipng options
GrayGhost ✱ grayghostvisualsmacmini.local  ~/httpd/my-project on master*
$ optipng img/*.png
** Processing: img/arrow-large.png
160x35 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 17 colors (17 transparent) in palette
Input IDAT size = 411 bytes
Input file size = 505 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 194
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 190
  zc = 9  zm = 8  zs = 3  f = 0   IDAT size = 178

Selecting parameters:
  zc = 9  zm = 8  zs = 3  f = 0   IDAT size = 178

Output IDAT size = 178 bytes (233 bytes decrease)
Output file size = 364 bytes (141 bytes = 27.92% decrease)

** Processing: img/arrow.png
160x25 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 17 colors (17 transparent) in palette
Input IDAT size = 425 bytes
Input file size = 519 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 191
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 189
  zc = 9  zm = 8  zs = 3  f = 0   IDAT size = 173

Selecting parameters:
  zc = 9  zm = 8  zs = 3  f = 0   IDAT size = 173

Output IDAT size = 173 bytes (252 bytes decrease)
Output file size = 359 bytes (160 bytes = 30.83% decrease)

** Processing: img/badge-bon-appetite.png
507x418 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Reducing image to 8 bits/pixel, 251 colors (251 transparent) in palette
Input IDAT size = 105488 bytes
Input file size = 106466 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 70588
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 70112
  zc = 9  zm = 8  zs = 3  f = 0   IDAT size = 70097
  zc = 9  zm = 8  zs = 3  f = 5   IDAT size = 69991

Selecting parameters:
  zc = 9  zm = 8  zs = 3  f = 5   IDAT size = 69991

Output IDAT size = 69991 bytes (35497 bytes decrease)
Output file size = 71997 bytes (34469 bytes = 32.38% decrease)

** Processing: img/badge-food-to-love.png
507x418 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Input IDAT size = 122525 bytes
Input file size = 123503 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 122495

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 122495

Output IDAT size = 122495 bytes (30 bytes decrease)
Output file size = 123473 bytes (30 bytes = 0.02% decrease)

** Processing: img/badge-keep-it-local.png
507x418 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Reducing image to 8 bits/pixel, 254 colors (254 transparent) in palette
Input IDAT size = 120138 bytes
Input file size = 121116 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 86142
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 85400
  zc = 9  zm = 8  zs = 0  f = 5   IDAT size = 83242
  zc = 9  zm = 8  zs = 1  f = 5   IDAT size = 81239

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 5   IDAT size = 81239

Output IDAT size = 81239 bytes (38899 bytes decrease)
Output file size = 83257 bytes (37859 bytes = 31.26% decrease)

** Processing: img/badge-sprite.png
96x188 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Input IDAT size = 19453 bytes
Input file size = 20363 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 19453

img/badge-sprite.png is already optimized.

** Processing: img/button-sprite.png
215x298 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Input IDAT size = 14761 bytes
Input file size = 15671 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 14761

img/button-sprite.png is already optimized.

** Processing: img/community-plane.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 255 colors (148 transparent) in palette
Input IDAT size = 7150 bytes
Input file size = 7244 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4701

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4701

Output IDAT size = 4701 bytes (2449 bytes decrease)
Output file size = 5732 bytes (1512 bytes = 20.87% decrease)

** Processing: img/cow.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 224 colors (158 transparent) in palette
Input IDAT size = 6610 bytes
Input file size = 6704 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4209

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4209

Output IDAT size = 4209 bytes (2401 bytes decrease)
Output file size = 5157 bytes (1547 bytes = 23.08% decrease)

** Processing: img/environment.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 140 colors (92 transparent) in palette
Input IDAT size = 5945 bytes
Input file size = 6039 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 3933

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 3933

Output IDAT size = 3933 bytes (2012 bytes decrease)
Output file size = 4563 bytes (1476 bytes = 24.44% decrease)

** Processing: img/farmer-john.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 238 colors (160 transparent) in palette
Input IDAT size = 7229 bytes
Input file size = 7323 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4711

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4711

Output IDAT size = 4711 bytes (2518 bytes decrease)
Output file size = 5703 bytes (1620 bytes = 22.12% decrease)

** Processing: img/little-piglet.png
248x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 73 colors (16 transparent) in palette
Input IDAT size = 10707 bytes
Input file size = 10801 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4702

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4702

Output IDAT size = 4702 bytes (6005 bytes decrease)
Output file size = 5055 bytes (5746 bytes = 53.20% decrease)

** Processing: img/logo.png
153x162 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 33 colors (16 transparent) in palette
Input IDAT size = 4998 bytes
Input file size = 5092 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 3414
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 3402

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 3402

Output IDAT size = 3402 bytes (1596 bytes decrease)
Output file size = 3635 bytes (1457 bytes = 28.61% decrease)

** Processing: img/menu-download.png
90x88 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Reducing image to 8 bits/pixel, 33 colors (16 transparent) in palette
Input IDAT size = 2933 bytes
Input file size = 3027 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 1984
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 1904

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 1904

Output IDAT size = 1904 bytes (1029 bytes decrease)
Output file size = 2137 bytes (890 bytes = 29.40% decrease)

** Processing: img/menu-icon.png
121x96 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 39 colors (26 transparent) in palette
Input IDAT size = 563 bytes
Input file size = 657 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 237
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 234

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 234

Output IDAT size = 234 bytes (329 bytes decrease)
Output file size = 495 bytes (162 bytes = 24.66% decrease)

** Processing: img/mobile-logo.png
351x72 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 17 colors (16 transparent) in palette
Input IDAT size = 3614 bytes
Input file size = 3708 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 2108
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 2093

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 2093

Output IDAT size = 2093 bytes (1521 bytes decrease)
Output file size = 2278 bytes (1430 bytes = 38.57% decrease)

** Processing: img/noise.png
210x123 pixels, 3x8 bits/pixel, RGB, interlaced
Input IDAT size = 44325 bytes
Input file size = 45235 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 44240

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 44240

Output IDAT size = 44240 bytes (85 bytes decrease)
Output file size = 45150 bytes (85 bytes = 0.19% decrease)

** Processing: img/right-on-dude.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Input IDAT size = 16587 bytes
Input file size = 16681 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 16587

img/right-on-dude.png is already optimized.

** Processing: img/skateboarder.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 248 colors (199 transparent) in palette
Input IDAT size = 7757 bytes
Input file size = 7851 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4924

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 4924

Output IDAT size = 4924 bytes (2833 bytes decrease)
Output file size = 5985 bytes (1866 bytes = 23.77% decrease)

** Processing: img/social-icons.png
150x46 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Reducing image to 8 bits/pixel, 33 colors (32 transparent) in palette
Input IDAT size = 2240 bytes
Input file size = 2334 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 1631
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 1613

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0   IDAT size = 1613

Output IDAT size = 1613 bytes (627 bytes decrease)
Output file size = 1862 bytes (472 bytes = 20.22% decrease)

** Processing: img/sprites.png
800x1600 pixels, 4x8 bits/pixel, RGB+alpha, interlaced
Input IDAT size = 599667 bytes
Input file size = 600657 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 542345

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 542345

Output IDAT size = 542345 bytes (57322 bytes decrease)
Output file size = 543335 bytes (57322 bytes = 9.54% decrease)

** Processing: img/subnav-bgblocks.png
156x78 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 4 bits/pixel, 16 colors (15 transparent) in palette
Input IDAT size = 374 bytes
Input file size = 468 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 240

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 240

Output IDAT size = 240 bytes (134 bytes decrease)
Output file size = 421 bytes (47 bytes = 10.04% decrease)

** Processing: img/yeah-dude.png
147x210 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 125 colors (31 transparent) in palette
Input IDAT size = 8149 bytes
Input file size = 8243 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 3765

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0   IDAT size = 3765

Output IDAT size = 3765 bytes (4384 bytes decrease)
Output file size = 4289 bytes (3954 bytes = 47.97% decrease)
Fig1.4 | Results from execution of optipng

Losslessness in the strictest sense, where no information whatsoever is lost, can only be achieved by leaving the original file (any file) intact, or by transforming it (e.g. compressing it, encrypting it) in such a way that there is an inverse transformation which recovers it completely, bit by bit.

In the first stage, the image pixels are passed through a lossless arithmetic transformation named delta filtering, or simply filtering, and sent further as a (filtered) byte sequence. Filtering does not compress or otherwise reduce the size of the data, but it makes the data more compressible.

As you can see there are a ton of other options available to you that I will not be diving into further for this article. My intentions are only to expose this tool to authors unaware of it and as you experiment please feel free to leave a comment or feedback regarding your findings or experience. Happy optimizing everyone!

Resources

Dennis Gaebel

Design Technologist passionate for Open Source, SVG, Typography, Web Animation, Interaction Development & Pattern Based Design. http://droidpinkman.io.
  1. […] INTRO TO JPEGOPTIM AND OPTIPNG (Jeff) […]

Leave a Reply

Your email address will not be published. Required fields are marked *

show formatting examples
<pre class="language-[markup | sass | css | php | javascript | ruby | clike | bash]"><code>
…code example goes here…
</code></pre>

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comment Preview

  1. John Doe shouted this comment preview:
    2013/08/13