libvips ships with a handy command-line image thumbnailer,vipsthumbnail
.This page introduces it, with some examples.
The thumbnailing functionality is implemented byvips_thumbnail()
andvips_thumbnail_buffer()
(which thumbnails an image held as a string),see the docs for details. You can use these functions from any languagewith a libvips binding. For example, fromPHP you could write:
$filename = "image.jpg";$image = Vips\Image::thumbnail($filename, 200, ["height" => 200]);$image->writeToFile("my-thumbnail.jpg");
You can also callthumbnail_source
from theCLI, for example:
$catk2.jpg|\vipsthumbnail_source[descriptor=0].jpg[Q=90]128|\cat>x.jpg
vipsthumbnail
supports the usual range ofvips
command-line options. Afew of them are useful:
--vips-cache-trace
shows each operation as libvips starts it. It can behandy to see exactly what operationsvipsthumbnail
is running for you.
--vips-leak
turns on the libvips memory leak checker. As well as reportingleaks (hopefully there are none) it also tracks and reports peak memory use.
--vips-progress
runs a progress indicator during computation. It can beuseful to see where libvips is looping and how often.
--vips-info
shows a higher level view of the operations thatvipsthumbnail
is running.
vipsthumbnail
can process many images in one command. For example:
$vipsthumbnail*.jpg
will make a thumbnail for everyJPEG in the current directory. See theOutput directory section below to see how to changewhere thumbnails are written.
vipsthumbnail
will process images one after the other. You can get a goodspeedup by running severalvipsthumbnail
s in parallel, depending on howmuch load you want to put on your system. For example:
$parallelvipsthumbnail:::*.jpg
You can set the bounding box of the generated thumbnail with the--size
option. For example:
$vipsthumbnailshark.jpg--size200x100
Use a single number to set a square bounding box. You can omit either numberbut keep the x to mean resize just based on that axis, for example:
$vipsthumbnailshark.jpg--size200x
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 largerthan the target.
You can append!
to force a resize to the exact target size, breakingthe aspect ratio.
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. Excesspixels are trimmed away using the strategy you set. For example:
$vipsthumbnailowl.jpg--smartcropattention-s128
Whereowl.jpg
is an off-centre composition:
Gives this result:
First it shrinks the image to get the vertical axis to 128 pixels, then cropsdown to 128 pixels across using theattention
strategy. This one searchesthe image for features which might catch a human eye, seevips_smartcrop()
for details.
Shrinking images involves combining many pixels into one. Arithmeticaveraging really ought to be in terms of the number of photons, but (forhistorical reasons) the values stored in image files are usually relatedto the voltage that should be applied to the electron gun in aCRT display.
vipsthumbnail
has an option to perform image shrinking in linear space, thatis, a colourspace where values are proportional to photon numbers. For example:
$vipsthumbnailfred.jpg--linear
The downside is that in linear mode, none of the very fast shrink-on-loadtricks thatvipsthumbnail
normally uses are possible, since the shrinking isdone at encode time, not decode time, and is done in terms ofCRT voltage, notphotons. This can make linear light thumbnailing of large images extremely slow.
For example, for a 10,000 x 10,000 pixelJPEG I see:
$timevipsthumbnailwtc.jpgreal0m0.317suser0m0.292ssys0m0.016s$timevipsthumbnailwtc.jpg--linearreal0m4.660suser0m4.640ssys0m0.016s
You set the thumbnail write parameters with the-o
option. This is a pattern which the input filename is pasted into toproduce the output filename. For example:
$vipsthumbnailfred.jpgjim.tif-otn_%s.jpg
For each of the files to be thumbnailed,vipsthumbnail
will drop theextension (.jpg
and.tif
in this case) and then substitute the name intothe-o
option, replacing the%s
So this example will write thumbnails totn_fred.jpg
andtn_jim.jpg
.
If the pattern given to-o
is an absolute path, any path components aredropped from the input filenames. This lets you write all of your thumbnailsto a specific directory, if you want. For example:
$vipsthumbnailfred.jpg../jim.tif-o/mythumbs/tn_%s.jpg
Now both thumbnails will be written to/mythumbs
, even though the sourceimages are in different directories.
Conversely, if-o
is set to a relative path, any path component from theinput file is prepended. For example:
$vipsthumbnailfred.jpg../jim.tif-omythumbs/tn_%s.jpg
Now both input files will have thumbnails written to a subdirectory oftheir current directory.
You can use-o
to specify the thumbnail image format too. For example:
$vipsthumbnailfred.jpg../jim.tif-otn_%s.png
Will write thumbnails inPNG format.
You can give options to the image write operation as a list of comma-separatedarguments in square brackets. For example:
$vipsthumbnailfred.jpg../jim.tif-otn_%s.jpg[Q=90,optimize_coding]
will writeJPEG 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:
$vipsjpegsavesaveimagetojpegfileusage:jpegsaveinfilename[--option-nameoption-value...]where:in-Imagetosave,inputVipsImagefilename-Filenametosaveto,inputgchararrayoptionalarguments:Q-Qfactor,inputgintdefault:75min:1,max:100optimize-coding-ComputeoptimalHuffmancodingtables,inputgbooleandefault:falseinterlace-Generateaninterlaced(progressive)jpeg,inputgbooleandefault:falsetrellis-quant-Applytrellisquantisationtoeach8x8block,inputgbooleandefault:falseovershoot-deringing-Applyovershootingtosampleswithextremevalues,inputgbooleandefault:falseoptimize-scans-SplitspectrumofDCTcoefficientsintoseparatescans,inputgbooleandefault:falsequant-table-Usepredefinedquantizationtablewithgivenindex,inputgintdefault:0min:0,max:8subsample-mode-Selectchromasubsampleoperationmode,inputVipsForeignSubsampledefaultenum:autoallowedenums:auto,on,offrestart-interval-Addrestartmarkerseveryspecifiednumberofmcu,inputgintdefault:0min:0,max:2147483647keep-Whichmetadatatoretain,inputVipsForeignKeepdefaultflags:exif:xmp:iptc:icc:other:allallowedflags:none,exif,xmp,iptc,icc,other,allbackground-Backgroundvalue,inputVipsArrayDoubleprofile-FilenameofICCprofiletoembed,inputgchararray
Thekeep
option is especially useful. Many image have very largeIPTC,ICC orXMP metadata items embedded in them, and removing these can give alarge saving.
For example:
$vipsthumbnail42-32157534.jpg$ls-ltn_42-32157534.jpg-rw-r–r–1johnjohn6682Nov1221:27tn_42-32157534.jpg
keep=none
almost halves the size of the thumbnail:
$vipsthumbnail42-32157534.jpg-ox.jpg[optimize_coding,keep=none]$ls-lx.jpg-rw-r–r–1johnjohn3600Nov1221:27x.jpg
vipsthumbnail
will optionally put images through LittleCMS for you. You canuse this to move all thumbnails to the same colour space. All web browsersassume that images without anICC profile are in sRGB colourspace, so ifyou move your thumbnails to sRGB, you can strip all the embedded profiles.This can save several kb per thumbnail.
For example:
$vipsthumbnailshark.jpg$ls-ltn_shark.jpg-rw-r–r–1johnjohn7295Nov 914:33tn_shark.jpg
Now transform to sRGB and don’t attach a profile (you can also usekeep=none
, though that will removeall metadata from the image):
$vipsthumbnailshark.jpg--output-profilesrgb-otn_shark.jpg[profile=none]$ls-ltn_shark.jpg-rw-r–r–1johnjohn4229Nov 914:33tn_shark.jpg
(You can use the filename of anyRGB profile. The magic stringsrgb
selects ahigh-quality sRGB profile that’s built into libvips.)
tn_shark.jpg
will look identical to a user, but it’s almost half the size.
You can also specify a fallback input profile to use if the image has noembedded one. For example, perhaps you somehow know that aJPEG is in Adobe98space, even though it has no embedded profile.
$vipsthumbnailkgdev.jpg--input-profile/my/profiles/a98.icm
Putting all this together, I suggest this as a sensible set of options:
$vipsthumbnailfred.jpg\--size128\--output-profilesrgb\-otn_%s.jpg[optimize_coding,keep=none]