9.6 KiB
libvips has shipped with a handy thumbnail maker for a while now. I thought a post of tips and tricks might be useful. Scroll all the way to the bottom for a summary and recommended usage.
Why use vipsthumbnail?
It’s fast and uses little memory. For example, here’s ImageMagick with
wtc.tif
, a 10,000 x 10,000 pixel RGB tiff image:
$ time convert wtc.tif -resize 128 tn_wtc.jpg
peak RSS: 705m
real 0m2.639s
user 0m4.036s
sys 0m0.516s
And here’s vipsthumbnail
:
$ time vipsthumbnail wtc.tif
peak RSS: 52mb
real 0m0.239s
user 0m0.168s
sys 0m0.072s
So vipsthumbnail
is about 11 times faster and needs 1 / 13th of the memory.
vipsthumbnail
and convert
are using the same downsizing algorithm: a fast box filter for
large-scale reduction, and a high-quality lanczos3 interpolator for the
final 200%.
You see similar improvements with png images, but much less with jpeg. This is because libjpeg includes support for shrink-during-load, so the image processing system has much less effect.
$ time convert -define jpeg:size=256x256 wtc.jpg -resize 128
tn_wtc.jpg
peak rss: 19mb
real 0m0.259s
user 0m0.284s
sys 0m0.004s
$ time vipsthumbnail wtc.jpg
peak rss: 30mb
real 0m0.268s
user 0m0.256s
sys 0m0.016s
The define
argument makes convert
load the image at twice the target size, then use a high-quality
downsampler to get to the exact output dimensions. If you don’t leave
this headroom you can get bad aliasing artifacts. vipsthumbnail
does exactly this automatically.
At larger output sizes you start to see a difference, since there are actually some pixels being processed:
$ time convert -define jpeg:size=4000x4000 wtc.jpg -resize 2000
tn_wtc.jpg
peak rss: 285mb
real 0m1.126s
user 0m2.508s
sys 0m0.240s
$ time vipsthumbnail wtc.jpg -s 2000
peak rss: 47mb
real 0m0.499s
user 0m0.928s
sys 0m0.028s
libvips options
vipsthumbnail
supports the usual range of vips command-line options. A
few of them are useful:
--vips-cache-trace
shows each operation as libvips starts it. It can be
handy to see exactly what operations vipsthumbnail
is running for you.
--vips-leak
turns on the libvips memory leak checker. As well as reporting
leaks (hopefully there are none) it also tracks and reports peak memory use.
--vips-progress
runs a progress indicator during computation. It can be
useful to see where libvips is looping and how often.
--vips-info
shows a higher level view of the operations that vipsthumbnail
is running.
Looping
vipsthumbnail can process many images in one operation. For example:
$ vipsthumbnail *.jpg
will make a thumbnail for every jpeg in the current directory. See the Output directory section below to see how to change where thumbnails are written.
vipsthumbnail
will process images one after the other. You can get a good
speedup by running several vipsthumbnail
s in parallel, depending on how
much load you want to put on your system.
Thumbnail size
You can set the bounding box of the generated thumbnail with the --size
option. For example:
$ vipsthumbnail shark.jpg --size 200x100
Use a single number to set a square bounding box. You can omit either number but keep the x to mean resize just based on that axis, for example:
$ vipsthumbnail shark.jpg --size 200x
Will resize to 200 pixels across, no matter what the height of the input image is.
You can append <
or >
to mean only resize if the image is smaller or larger
than the target.
Cropping
vipsthumbnail
normally shrinks images to fit within the box set by --size
.
You can use the --smartcrop
option to crop to fill the box instead. Excess
pixels are trimmed away using the strategy you set. For example:
$ vipsthumbnail owl.jpg --smartcrop attention -s 128
Where owl.jpg
is an off-centre composition:
Gives this result:
First it shrinks the image to get the vertical axis to 128 pixels, then crops
down to 128 pixels across using the attention
strategy. This one searches
the image for features which might catch a human eye, see vips_smartcrop()
for details.
Linear light
Shrinking images involves combining many pixels into one. Arithmetic averaging really ought to be in terms of the number of photons, but (for historical reasons) the values stored in image files are usually related to the voltage that should be applied to a CRT electron gun.
vipsthumbnail
has an option to perform image shrinking in linear space, that
is, a colourspace where values are proportional to photon numbers. For example:
$ vipsthumbnail fred.jpg --linear
The downside is that in linear mode, none of the very fast shrink-on-load
tricks that vipsthumbnail
normally uses are possible, since the shrinking
done by the image libraries is done at encode time, and done in
terms of CRT voltage, not light. This can make linear light thumbnailing of
large images extremely slow.
Output directory
You set the thumbnail write parameters with the -o
option. This is a pattern which the input filename is pasted into to
produce the output filename. For example:
$ vipsthumbnail fred.jpg jim.tif -o tn_%s.jpg
For each of the files to be thumbnailed, vipsthumbnail
will drop the extension (.jpg
and .tif
in this case) and then substitute the name into the -o
option, replacing the %s
So this example will write thumbnails to tn_fred.jpg
and tn_jim.jpg
.
If the pattern given to -o
is an absolute path, any path components are dropped from the input
filenames. This lets you write all of your thumbnails to a specific
directory, if you want. For example:
$ vipsthumbnail fred.jpg ../jim.tif -o /mythumbs/tn_%s.jpg
Now both thumbnails will be written to /mythumbs
,
even though the source images are in different directories.
Conversely, if -o
is set to a relative path, any path component from the input file is
prepended. For example:
$ vipsthumbnail fred.jpg ../jim.tif -o mythumbs/tn_%s.jpg
Now both input files will have thumbnails written to a subdirectory of their current directory.
Output format and options
You can use -o
to specify the thumbnail image format too. For example:
$ vipsthumbnail fred.jpg ../jim.tif -o tn_%s.png
Will write thumbnails in PNG format.
You can give options to the image write operation as a list of comma-separated arguments in square brackets. For example:
$ vipsthumbnail fred.jpg ../jim.tif -o > tn_%s.jpg[Q=90,optimize_coding]
will write jpeg images with quality 90, and will turn on the libjpeg coding optimizer.
Check the image write operations to see all the possible options. For example:
$ vips jpegsave
save image to jpeg file
usage:
jpegsave in filename
where:
in - Image to save, input VipsImage
filename - Filename to save to, input gchararray
optional arguments:
Q - Q factor, input gint
default: 75
min: 1, max: 100
profile - ICC profile to embed, input gchararray
optimize-coding - Compute optimal Huffman coding tables, input gboolean
default: false
interlace - Generate an interlaced (progressive) jpeg, input gboolean
default: false
no-subsample - Disable chroma subsample, input gboolean
default: false
trellis-quant - Apply trellis quantisation to each 8x8 block, input gboolean
default: false
overshoot-deringing - Apply overshooting to samples with extreme values, input gboolean
default: false
optimize-scans - Split the spectrum of DCT coefficients into separate scans, input gboolean
default: false
quant-table - Use predefined quantization table with given index, input gint
default: 0
min: 0, max: 8
strip - Strip all metadata from image, input gboolean
default: false
background - Background value, input VipsArrayDouble
The strip
option is especially useful. Many image have very large IPCT, ICC or
XMP metadata items embedded in them, and removing these can give a large
saving.
For example:
$ vipsthumbnail 42-32157534.jpg
$ ls -l tn_42-32157534.jpg
-rw-r–r– 1 john john 6682 Nov 12 21:27 tn_42-32157534.jpg
strip
almost halves the size of the thumbnail:
$ vipsthumbnail 42-32157534.jpg -o x.jpg[optimize_coding,strip]
$ ls -l x.jpg
-rw-r–r– 1 john john 3600 Nov 12 21:27 x.jpg
Colour management
vipsthumbnail
will optionally put images through LittleCMS for you. You can
use this to move all thumbnails to the same colour space. All web browsers
assume that images without an ICC profile are in sRGB colourspace, so if
you move your thumbnails to sRGB, you can strip all the embedded profiles.
This can save several kb per thumbnail.
For example:
$ vipsthumbnail shark.jpg
$ ls -l tn_shark.jpg
-rw-r–r– 1 john john 7295 Nov 9 14:33 tn_shark.jpg
Now encode with sRGB and delete any embedded profile:
$ vipsthumbnail shark.jpg --eprofile /usr/share/color/icc/sRGB.icc --delete
$ ls -l tn_shark.jpg
-rw-r–r– 1 john john 4229 Nov 9 14:33 tn_shark.jpg
It’ll look identical to a user, but be almost half the size.
You can also specify a fallback input profile to use if the image has no embedded one, but this is less useful.
Auto-rotate
Many JPEG files have a hint set in the header giving the image orientation. If you strip out the metadata, this hint will be lost, and the image will appear to be rotated.
If you use the --rotate
option, vipsthumbnail
examines the image header and
if there's an orientation tag, applies and removes it.
Final suggestion
Putting all this together, I suggest this as a sensible set of options:
$ vipsthumbnail fred.jpg \
--size 128 \
-o tn_%s.jpg[optimize_coding,strip] \
--eprofile /usr/share/color/icc/sRGB.icc \
--rotate