76

I have a directory with a lots of images but they are in the wrong orientation. I want to rotate the images to correct the orientation (mostly ±90o). Using image (shotwell photo) viewer I can rotate them individually by clicking the rotate button but that's too tedious.

I looked at man shotwell and shotwell --help-all but there's nothing that explains how to invoke the rotate command from the command line.

Is there any way I can invoke the rotate command of shotwell (or any other viewer) from the terminal? Or any other methods to rotate images are welcome too.

Zanna
  • 70,465
pranphy
  • 1,608

9 Answers9

76

If you're looking for a pure bash implementation, ImageMagick's convert command is what you're looking for:

for szFile in /path/*.png
do 
    convert "$szFile" -rotate 90 /tmp/"$(basename "$szFile")" ; 
done

Above will leave existing files intact and copy the newly rotated ones to /tmp so you can move or copy them somewhere else or even replace the existing ones after the conversion and after verification.

(and it'll work on all recent releases of Ubuntu as it's standard software)

Fabby
  • 34,259
  • 1
    This isn't lossless. – Geremia Jun 27 '20 at 21:24
  • @Geremia That depends on the file format used. If it's a TIFF or BMP that you rotate and (keep the same destination file format) it will be perfectly lossless. If you use JPEG or PNG (both lossy file formats) the result will be lossy as well, but that was not what the original question was about... 0:-) – Fabby Jul 05 '20 at 17:03
50
for file in *.JPG; do convert $file -rotate 90 rotated-$file; done

This will copy-rotate-and-rename your files.

If you want to leave the original files untouched just yet, this method may work well for you...

Note that this is case-sensitive: if your files are named *.jpg replace with lower-case (or *.png ...) accordingly.

26

If you want to overwrite in-place, mogrify from the ImageMagick suite seems to be the easiest way to achieve this:

# counterclockwise:
mogrify -rotate -90 *.jpg

# clockwise:
mogrify -rotate 90 *.jpg

CAVEAT: This isn't a lossless rotation method for JPEG files, https://www.imagemagick.org/discourse-server/viewtopic.php?t=5899. jpegtran achieves this (untested):

# counterclockwise
ls *.jpg | xargs -n 1 jpegtran -perfect -rotate 270

# clockwise
ls *.jpg | xargs -n 1 jpegtran -perfect -rotate 90
krlmlr
  • 3,337
7

Here's how I do it:

  1. Install gThumb

     sudo apt-get install gthumb
    
  2. Open up nautilus and go to your images directory. Right click on one and choose Open with -> gthumb.

  3. Under the view menu choose Browser or press the Esc key. This will open the directory browser showing all your images.

    enter image description here

  4. Press Ctrl and select the images you want to rotate or select all of them via Ctrl + A.

  5. On the toolbar, select Tools and then Rotate Right or Rotate Left depending on your preference.

    enter image description here

Parto
  • 15,325
  • 24
  • 86
  • 117
2

How about exiftran - transform digital camera jpeg images

I know it's a bit limiting (jpeg) but it has automatic (using exif orientation tag).

for photo in *.jpg
  do exiftrans -ia $photo
done

About Exiftran, it is a command line utility to transform digital camera jpeg images. It can do lossless rotations like jpegtran(1), but unlike jpegtran(1) it cares about the EXIF data: It can rotate images automatically by checking the exif orientation tag; it updates the exif informations if needed (image dimension, orientation); it also rotates the exif thumbnail. It can process multiple images at once

Bruno
  • 121
  • 1
    You can also leave out the for loop and simply use: exiftran -i1 *.JPG. (I'm using -1 here to enforce a 180 degree rotation because my files don't have an orientation tag in the EXIF data.) Check exiftran -h for more options. – Falko Menge Aug 25 '23 at 14:25
2

As krlmlr notes in their answer, jpegtran (installed on Ubuntu with sudo apt install libjpeg-turbo-progs) is available for lossless rotation, but because it outputs to standard output, the command to use it would be something like this:

$ for img in *.jpg; do jpegtran -rotate 90 -copy all $img > rotated-${img}; done

This command will take each file in the current directory, and produce a rotated version (90° clockwise) copy of each file with the new name rotated-image-name.jpg. The switch -copy all is to copy all metadata to the new file.

For more information see man jpegtran.

An additional piece of information given that the original question referenced Shotwell: according to Shotwell's documentation, Shotwell's rotations and other edits will not actually edit the files on disk:

Shotwell is a non-destructive photo editor. It does not modify your original photographs. That is to say, if you crop a photo or adjust its colors, the photo file on disc remains untouched. Shotwell stores your edits in a database and applies them on the fly as necessary. This means you can undo any alterations you make to a photograph.

1

A nice solution is to make a set of backups (e.g. prefixed backup-), rotate the original files producing a set of new files (prefixed e.g. rotated-), giving you a set of

  • img-1.png
  • backup-img-1.png
  • rotated-img-1.png
  • img-2.png
  • ...and so on

The mv/cp tools [bash globbing] can only add prefixes, it's messy to take them away (it'd use parameter expansion, ewww...)

The rename tool allows you to use s/before/after/ substitution syntax (from the sed tool) to swap that safeguard prefix and overwrite the original files, so your overall process for a given set of pictures img-{1..n}.png would be:

for imgf in img-*.png; do mv "$imgf" "backup-$imgf"; done
for imgf in backup-img-*.png; do convert "$imgf" -rotate 90 "rotated-$imgf"; done

Note:

  • you could use cp rather than mv, but then there's 2 copies of the original lying around (downside is you get concatenation of prefixes, "rotated-backup-...")
  • rotation is clockwise (-rotate 270 gets you 90° anti-clockwise)
  • to track progress, add echo "Rotating ${imgf#backup-} ... "; after convert calls (before done)
  • for a more compact form (e.g. a set of numbered files), use some parameter expansion like echo "$(echo ${imgf#backup-img-} | cut -d\. -f 1)..."; instead

    ( You can't remove prefix and suffix in the same bash param expansion hence use cut )

Then after verification you've not messed up, delete the pictures by moving them back to the original

rename 's/^rotated-//;' rotated-*
rm backup-img-*
Louis Maddox
  • 223
  • 3
  • 9
1

You can copy/paste this code, and save it as rotate.sh

#!/bin/bash -e

CUR_DIR=$(pwd)
cd $1
for file in *.jpg
do
    convert $file -rotate 90 $file
done
cd $CUR_DIR

After saving this file, run it from terminal using ./rotate.sh folder_containing_images.

Zanna
  • 70,465
vin
  • 11
  • 1
  • Please check your code and the link given! – George Udosen Mar 31 '17 at 23:28
  • This runs serious risk of data loss! You must use quotation marks, thus: CUR_DIR="$PWD" (note the simplification of using the built-in variable), cd "$1", convert "$file" -rotate 90 "$file" and cd "$CUR_DIR" – Paddy Landau Nov 11 '20 at 13:04
  • You can simplify further by using pushd and popd. They're great for changing directory and back again. – Paddy Landau Nov 11 '20 at 13:05
0

If you have ffmpeg and if your images are numbered consecutively starting from zero with 6 digits, you can rotate them with

ffmpeg -pattern_type glob -i '*.jpg' -start_number 0 -vf "transpose=1" -qscale:v 5 %06d.jpg 

The digit after qscale:v controls output quality, lower is better.

Antonio
  • 840