Vector graphics: batch manipulation on command line

Once in a while I need to manipulate multiple vector graphics at once (mostly svg, but could be embedded in pdf as well). For this purpose I list those commands I regularly resort to below, either directly as command or embedded into small command line scripts. Most of the examples require the vector graphics editor Inkscape to be installed.

Crop all graphics to area actually containing information

To crop the canvas size of a graphics to the area actually containing information (“drawing area” with Inkscape). Inkscape’s --without-gui option does not work yet because Inkscape headless graphics manipulation does not always change graphics, and therefore saving does not trigger anything.

Script fitImg2Canvas

inkscape --verb=FitCanvasToDrawing --verb=FileSave --verb=FileClose "$@"

Script call

fitImg2Canvas *svg

Update: in the meantime, pdfcrop was added to the Ubuntu repos in the texlive-extra-utils package, which is perfect for the job. pdfcrop automatically recognizes to which area a file can be cropped and further has a margins parameter, which – if given – specifies the margins that should remain in the file:

sudo apt-get install texlive-extra-utils
pdfcrop --margins '10 10 10 10' infile.pdf outfile.pdf

Convert all graphics (svg) to pdf (still containing vector graphics)

Batch converting all svg to pdf files can be useful e.g. with LaTeX (does not support svg graphics per default).

Script svg2pdf

for filename in "$@"
        b=$(basename "$filename" .svg)
        inkscape --without-gui --export-pdf="$b.pdf" "$filename"

Script call

svg2pdf *svg

Animated gif creation with automatic image alignment

Animated gif created with align_image_stack and convert.
Animated gif created with align_image_stack and convert.

In case you took some photos showing a scene in motion, you probably want to create an animated gif out of them. If you did not use a tripod for fixing your camera, the images will not be aligned perfectly, so that the scene is slightly shifted within the images – which is clearly visible in the animated gif, and doesn’t look too good. I’ve stumbled across this problem recently: there exist several GUI based tools for Linux to do the image alignment and gif creation (such as with using this Gimp plugin), but at least the tools I’ve tried require the user to start much of the processing by hand – which simply eats up too much of my time.  Inspired from here I used a combination of align_image_stack and PTblender (part of the Hugin panorama tool suite set I’ve used in automatic panorama creation) and ImageMagick’s convert to automatically align images, equalize brightness and color and create an animated gif from them to save me some time.

Aligning images and equalizing brightness and color

At first we need to align all images with the scene, so that they overlap “perfectly”. In this context, perfectly means adequate for my personal usage in animated gifs, as there are still minor shifts left after aligning. align_image_stack from the Hugin panorama tool suite is designed to do exactly that for aligning HDR images. Therefore, you can use

convert *JPG -resize 1000 +repage resized_%02d.jpg
align_image_stack -i -m -s 1 -C -a aligned_ -C resized*
PTblender -k 0 -t 0 -p blended_ aligned*
convert blended_* -format jpg blendedjpg_%02d.jpg

to automatically

  1. copy and resize all *JPG images in the current directory (accelerates consecutive aligning and gif creation, using only the “-s” parameter in the subsequent command would output bigger aligned images),
  2. align all these downscaled files using align_image_stack. There “-i” corrects image center shifts, “-m” optimized field of view, “-s 1” scales images internally before aligning by a factor of 2¹ (does not scale down aligned output files), “-C” automatically crops images to the area covered by all images, “-a aligned” stands for the command producing .tif files which have this additional prefix, and “-C” stands for the command automatically cropping all images to those areas contained in all images,
  3. equalize color and brightness across images using PTblender. “-k 0” takes the first of the images as reference image, “-t 0” corrects both brightness and color, “-p blended_” again specifies the output file prefix.

Creating the animated gif

Now we can create an animated gif from the aligned images. ImageMagick’s convert provides all features you need in order to create the gif exactly as you’d like to have it. I personally use the following command to additionally rotate and resize the images, reduce the amount of used colors and create a file name representing the originally used images. You might want to adapt these to fit your needs.

convert -format jpg -rotate "-90" -resize 600 +repage -delay 20 -loop 0 -colors 100 blendedjpg* "`ls *JPG | head -1 | sed s/\.JPG//`-`ls *JPG | tail -1 | sed s/\.JPG//`.gif"

If the gif contains erroneous areas (wrong color or completely black etc.) try a slightly changed color palette and image size or leave out the color palette completely.  That’s it, you’ve just created your aligned and animated gif.


If everything worked fine and you are happy with your animated gif: to quickly remove files created as side effect as well as log/debug files of the used tool suites:

rm aligned* blended* resized* Debug.txt zcom_log.txt

Installation on Ubuntu 12.04, 14.04 etc.

As align_image_stack and PTblender come with Hugin, and convert with ImageMagick, you just need to install those two tool suits from the Ubuntu repositories:

sudo apt-get install hugin imagemagick

convertconditional: convert an image if it fulfills certain conditions

Recently I needed a script to batch convert only those images amongst a large amount of images which fulfil certain criteria, namely of being exactly of a stated size. The script is based on ImageMagick’s convert and basically takes an arbitrary amount of convert parameters. I personally use this script to automatically reduce size and quality of photos taken with a specific camera in order to reduce their hard disk space coverage.

The script

#! /usr/bin/python
# convertconditional: Convert an image if it fulfills certain conditions, e.g. is of a certain size. Requires ImageMagick's convert.
# Rainhard Findling 2013/08
# example to convert all *JPG within the current directory with are of certain size to a reduced size and quality:
# find . -iname "*JPG" -exec ./convertconditional {} -filtersize 3888x2592 -convertparams "-resize 3500x3000 +repage -quality 80" \;
import argparse # check for help
import subprocess
import sys
# specify arguments
parser = argparse.ArgumentParser()
parser.add_argument('inputfile', help='path to the file that will be converted.')
parser.add_argument('-convertparams', required=True, help='parameters handed to the convert command used internally, e.g. resize, repage, reduce quality etc. Example: "-resize 300x200 +replage -quality 92"')
parser.add_argument('-filtersize', help='only convert if original image is of this size, stated as WIDTHxHEIGHT, e.g. 3500x3200.')
parser.add_argument('-o', '--outputfile', help='path to where the converted image will be stored. if not specified, the original file will be overwritten.')
parser.add_argument('-v','--verbose',help='print verbose output.',action='store_true')
args = parser.parse_args()
# make sure we can process names with spaces
args.inputfile = '"' + args.inputfile + '"'
# check for correct arguments
if not args.outputfile:
args.outputfile = args.inputfile
if args.filtersize:
filter_x = int(args.filtersize.split('x')[0])
filter_y = int(args.filtersize.split('x')[1])
if args.verbose:
print 'inputfile=' + args.inputfile
print 'outputfile=' + args.outputfile
if args.filtersize:
print 'resizing only', str(filter_x) + 'x' + str(filter_y), 'images.'
print 'convertparams=' + args.convertparams
# get size of image
imagesize = subprocess.check_output(["identify -format '%wx%h' '" + args.inputfile + "'"],
imagesize_x = int(imagesize.split('x')[0])
imagesize_y = int(imagesize.split('x')[1])
# condition: filter for images of certain size
if args.filtersize:
if args.verbose:
print 'size of', args.inputfile, 'is', str(imagesize_x) + "x" + str(imagesize_y)
# check filter criteria
if not imagesize_x == filter_x or not imagesize_y == filter_y:
print 'leaving out ' + args.inputfile + ' as it is of size ' +  str(imagesize_x) + "x" + str(imagesize_y) + " (required: " + args.filtersize + ")"
# passed all conditions: convert image
print 'converting ' + args.inputfile + ' (size: ' +  str(imagesize_x) + "x" + str(imagesize_y) + ')'
# convert image
command="convert '" + args.inputfile + "' " + args.convertparams + " '" + args.outputfile + "'"
if args.verbose:
print 'command:', command
imagesize = subprocess.check_output([command],

The script is written in Python, so all you need to do is save it (e.g. in a file called “convertconditional”) and make it executable:

chmod +x convertconditional

Then you can either call it with stating it’s path (e.g. “./convertconditional [parameters]”), or add it to your systems PATH to call it from everyhwere.

Script execution

In order to convert input.jpg to output.jpg, you can try

convertconditional input.jpg -filtersize 3888x2592 -convertparams "-resize 3500x3000 +repage -quality 85" -o output.jpg
  • -filtersize optional filtering: only convert the image  in case it is exactly of the stated size
  • -convertparams states parameters which should be handed to ImageMagick’s convert
  • -o states where to store the converted image (original image gets overwritten if omitted)

In case you want to conditionally convert multiple files (as with my usecase) you can combine convertconditional with find and overwrite the original files:

find . -iname "*JPG" -exec convertconditional {} -filtersize 3888x2592 -convertparams "-resize 3800x +repage -quality 85" \;