2017-04-01 18:05:05 +02:00
|
|
|
|
<refmeta>
|
|
|
|
|
<refentrytitle>Using `vipsthumbnail`</refentrytitle>
|
|
|
|
|
<manvolnum>3</manvolnum>
|
|
|
|
|
<refmiscinfo>libvips</refmiscinfo>
|
|
|
|
|
</refmeta>
|
|
|
|
|
|
|
|
|
|
<refnamediv>
|
|
|
|
|
<refname>`vipsthumbnail`</refname>
|
|
|
|
|
<refpurpose>Introduction to `vipsthumbnail`, with examples</refpurpose>
|
|
|
|
|
</refnamediv>
|
|
|
|
|
|
2017-03-31 19:11:39 +02:00
|
|
|
|
libvips ships with a handy command-line image thumbnailer, `vipsthumbnail`.
|
2017-04-01 18:05:05 +02:00
|
|
|
|
This page introduces it, with some examples.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
The thumbnailing functionality is implemented by `vips_thumbnail()` and
|
|
|
|
|
`vips_thumbnail_buffer()` (which thumbnails an image held as a string),
|
|
|
|
|
see the docs for details. You can use these functions from any language
|
|
|
|
|
with a libvips binding. For example, from PHP you could write:
|
|
|
|
|
|
2017-04-23 23:09:17 +02:00
|
|
|
|
```php?start_inline=1
|
2017-04-23 20:29:02 +02:00
|
|
|
|
$filename = "image.jpg";
|
2017-04-01 18:05:05 +02:00
|
|
|
|
$image = Vips\Image::thumbnail($filename, 200, ["height" => 200]);
|
2017-04-23 19:52:05 +02:00
|
|
|
|
$image->writeToFile("my-thumbnail.jpg");
|
2017-04-01 18:05:05 +02:00
|
|
|
|
```
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# libvips options
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
`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.
|
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Looping
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
`vipsthumbnail` can process many images in one command. For example:
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ vipsthumbnail *.jpg
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
will make a thumbnail for every jpeg in the current directory. See the
|
2017-04-01 18:05:05 +02:00
|
|
|
|
[Output directory](#output-directory) section below to see how to change
|
|
|
|
|
where thumbnails are written.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
`vipsthumbnail` will process images one after the other. You can get a good
|
|
|
|
|
speedup by running several `vipsthumbnail`s in parallel, depending on how
|
2017-03-31 19:11:39 +02:00
|
|
|
|
much load you want to put on your system. For example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ parallel vipsthumbnail ::: *.jpg
|
|
|
|
|
```
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Thumbnail size
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
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
|
2017-03-31 19:11:39 +02:00
|
|
|
|
than the target.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Cropping
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
`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:
|
|
|
|
|
|
|
|
|
|
![](owl.jpg)
|
|
|
|
|
|
|
|
|
|
Gives this result:
|
|
|
|
|
|
|
|
|
|
![](tn_owl.jpg)
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Linear light
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
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
|
2017-04-01 18:05:05 +02:00
|
|
|
|
to the voltage that should be applied to the electron gun in a CRT display.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
`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
|
2017-04-01 18:05:05 +02:00
|
|
|
|
tricks that `vipsthumbnail` normally uses are possible, since the shrinking is
|
|
|
|
|
done at encode time, not decode time, and is done in terms of CRT voltage, not
|
|
|
|
|
photons. This can make linear light thumbnailing of large images extremely slow.
|
|
|
|
|
|
|
|
|
|
For example, for a 10,000 x 10,000 pixel JPEG I see:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ time vipsthumbnail wtc.jpg
|
|
|
|
|
real 0m0.317s
|
|
|
|
|
user 0m0.292s
|
|
|
|
|
sys 0m0.016s
|
|
|
|
|
$ time vipsthumbnail wtc.jpg --linear
|
|
|
|
|
real 0m4.660s
|
|
|
|
|
user 0m4.640s
|
|
|
|
|
sys 0m0.016s
|
|
|
|
|
```
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Output directory
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
```
|
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
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`.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
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:
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ vipsthumbnail fred.jpg ../jim.tif -o /mythumbs/tn_%s.jpg
|
|
|
|
|
```
|
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
Now both thumbnails will be written to `/mythumbs`, even though the source
|
|
|
|
|
images are in different directories.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
Conversely, if `-o` is set to a relative path, any path component from the
|
|
|
|
|
input file is prepended. For example:
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ 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.
|
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Output format and options
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
You can use `-o` to specify the thumbnail image format too. For example:
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ vipsthumbnail fred.jpg ../jim.tif -o tn_%s.png
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Will write thumbnails in PNG format.
|
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
You can give options to the image write operation as a list of comma-separated
|
|
|
|
|
arguments in square brackets. For example:
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ vipsthumbnail fred.jpg ../jim.tif -o > tn_%s.jpg[Q=90,optimize_coding]
|
|
|
|
|
```
|
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
will write jpeg images with quality 90, and will turn on the libjpeg coding
|
|
|
|
|
optimizer.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-04-01 18:05:05 +02:00
|
|
|
|
Check the image write operations to see all the possible options. For example:
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ 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
|
|
|
|
|
```
|
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Colour management
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
`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
|
2018-01-23 14:09:51 +01:00
|
|
|
|
embedded one. This can often happen with CMYK images, producing an error
|
|
|
|
|
message like:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ vipsthumbnail kgdev.jpg
|
|
|
|
|
vipsthumbnail: unable to thumbnail kgdev.jpg
|
|
|
|
|
vips_colourspace: no known route from 'cmyk' to 'srgb'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If you supply a CMYK profile, it will be able to convert the image,
|
|
|
|
|
for example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ vipsthumbnail kgdev.jpg --iprofile /usr/share/color/icc/colord/FOGRA28L_webcoated.icc
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
I've had good results with this profile:
|
|
|
|
|
|
|
|
|
|
https://github.com/jcupitt/nip2/blob/master/share/nip2/data/cmyk.icm
|
|
|
|
|
|
|
|
|
|
It makes nice-looking images from most CMYK files, and is completely free.
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Auto-rotate
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2017-03-31 21:15:33 +02:00
|
|
|
|
# Final suggestion
|
2017-03-31 14:26:25 +02:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
```
|