Digital photo handling on the command line ========================================== Mini HOWTO from Till Kamppeter http://www.linuxprinting.org/download/digitalimage/ Here is described how very common tasks of digital photo handling can be done on the command line, this is especially interesting when one has to apply manipulations to several hundreds of photos, where using graphical applications can get a pain. All operations described here are completely done with free software (My scripts below are GPL) and should work (assuming all needed software is installed) on all GNU/Linux systems. All JPEG manipulations are done without recompression, so there is no loss of image quality. Download photos --------------- Using USB or PCMCIA (PC-Card) flash card adapters saves battery power in the camera and allows to use cameras where direct USB connection does not work with free software. See http://www.teaser.fr/~hfiguiere/linux/digicam.html for camera protocols and compatibility. - USB storage camera or USB flash card adapter # modprobe usb-storage (only if not done automatically, check with "lsmod") # mkdir /mnt/camera # mount /dev/sda1 /mnt/camera (Can be /dev/sdb1, /dev/sdc1, ...) $ cp -a /dev/camera/* . For non-root mount add /dev/sda1 /mnt/camera auto user,noauto 0 0 to /etc/fstab and $ mount /mnt/camera $ cp -a /dev/camera/* . $ umount /mnt/camera Do not forget to unmount ("umount" command) before turning off or disconnecting the camera/the adapter/removing the card. In case of problems check the presence of the USB storage device with (it appears as a SCSI disk): cat /proc/scsi/scsi cdrecord -scanbus Check whether the "usb-storage" kernel module is loaded with lsmod Another problem is that sometimes /dev/sda1, /dev/sdb1, ... is not automatically created. Here is a trick which Derk te Bokkel (tebokkel at telus dot net) posted on the HPOJ (http://hpoj.sf.net/) mailing list: >> Hi Reguarding mass storage cards under linux.. A quirk I've noticed is >> that the normal mount point /dev/sda1 or /dev/sdb1 etc. quite >> often does >> not get generated. It is only after trying to mount the device on >> /dev/sda or /dev/sdb does the /dev/sda1 or /dev/sdb1 mount point get >> created. I'm not sure why. But for me the trick is to 'kick' >> the device >> first by trying to mount on /dev/sda, then when it says: >> >> mount: wrong fs type, bad option, bad superblock on /dev/sda, or too >> many mounted file systems >> >> usually I can then mount on /dev/sda1 normally. - GPhoto2 (if USB storage does not work) $ gphoto2 --list-files $ gphoto2 --get-all-files More info, more operations, and PC-assisted capturing with $ gphoto2 --help $ man gphoto2 - PCMCIA (PC-Card) adapter for flash cards Similar to USB storage, but # mkdir /mnt/card # mount /dev/hdc1 /mnt/card (Can be /dev/hdb1, /dev/hdd1, /dev/hde1, ...) User mounting with /dev/hdc1 /mnt/card auto user,noauto 0 0 in /etc/fstab PCMCIA support must be installed and running. Mandrake 9.0, 9.1, and 9.2 have a bug which prevents PCMCIA flash card access from working. To work around it, rename the /usr/sbin/drakupdate_fstab file or turn off devfsd ("devfs=nomount" in kernel command line). See https://qa.mandrakesoft.com/show_bug.cgi?id=3176 Camera-specific/proprietary data formats ---------------------------------------- - dcraw/rawphoto Higher end cameras allow saving the pictures in a raw data format to provide non-preprocessed and loss-less image files for processing on the computer. Unfortunately, there is no standard format for such high-color-depth (36 or 48 bit) images. Therfore every manufacturer uses its own proprietary format. These files can be read by the "dcraw" command line tool and the "rawphoto" GIMP plug-in. Note that both the plug-in on the dcraw site and the external plug-in are named "rawphoto". The external one has a preview to see the effect of the parameter settings. See links to both dcraw and the external rawphoto below. - metacam Another problem are manufacturer-specific fields in the EXIF data of JPEG files. Several of these can be read with "metacam", especially the ones of Canon's cameras. - mrwtoppm For the Minolta DiMAGE 5, 7, 7UG, 7i, 7hi, and A1 there is a special raw converter package named mrwtoppm. It also contains command line software and a GIMP plug-in. This software is much more comfortable and feature-rich than dcraw/rawphoto, but works only with the mentioned DiMAGE models. mrwtoppm is not based on dcraw. Put photos in correct orientation (loss-less) --------------------------------------------- Neads jhead, jpegtran, no JPEG recompression, so no quality loss - Automatically Works only with newer cameras with orientation sensor $ jhead -autorot *.jpg - Manually $ jhead -cmd "jpegtran -rot 270 &i > &o" file.jpg (90 degree left) $ jhead -cmd "jpegtran -rot 90 &i > &o" file.jpg (90 degree right) Or use scripts "rotateleft file.jpg" or "rotateright file.jpg" (below) Crop photos to 3:2 ratio (for filling 4x6in/10x15cm photo paper, loss-less) or any other ratio --------------------------------------------------------------------------- Manually done with (needs jpegtran with jpegcrop patch, jhead) jhead -cmd "jpegtran -crop NEWWIDTHxNEWHEIGHT+XOFFSET+YOFFSET &i > &o" *.jpg NEWWIDTH, NEWHEIGHT, XOFFSET, and YOFFSET must be replaced by the appropriate values in pixels (integer numbers). Automatization with script based on jpegtran with jpegcrop patch, jhead, ImageMagick (script below), no JPEG recompression, so no quality loss $ crop -r 3:2 *.jpg $ crop -r 1:1.414 *.jpg $ crop -r A4 *.jpg $ crop -r Letter *.jpg $ crop -r 8x10 *.jpg $ crop -h The orientation of the images (landscape, portrait) is taken into account, so the image is always cropped in a way that a minimum of area gets removed. As this command cuts away parts of the image on the two long edges it cannot be undone. So copy the photos you want to print at first into a newly created directory, and apply the command there. Remove bad pixels due to defects in the image sensor of the camera ------------------------------------------------------------------ Needs jpegpixi. No JPEG recompression, so no quality loss Preparation: Has to be done once for every of your digital cameras. Take a completely black photo by covering the lens and/or setting the most close aperture and the fastest shutter speed, flash off, focusing does not matter. Use the highest available JPEG quality, RAW or TIFF. jpegpixi contains a utility to automatically find the dead (stuck) pixels in the black frame. Its name is "jpeghotp" and works only on JPEG images. So convert your dark frame into a high quality JPEG image at first. Then run jpeghotp blackframe.jpg deadpixels.txt and there will be a list of the dead pixel coordinates, readable by jpegpixi in the deadpixels.txt file. Alternatively, you can load the photo into the GIMP and zoom it by right-clicking and choosing "View"/"Zoom"/"1:1" to find the bad spots and "4:1" to easily determine the coordinates (visible in the lower left corner of the image window). The bad pixels are easy-to-see light spots on the black area. Note all coordinates. You can also use the "display" utility of ImageMagick. Here zoom the image and click onto the dead pixels with the middle mouse button to see their coordinates. Now write a file deadpixels.txt with the coordinates of all bad spots as follows: 1348,838,6 713,1009,4 Every line is one bad spot or area. The first two numbers are the coordinates of the upper left corner of the bad area and the last number is the border length of a square covering the bad spot. Choose coordinates and size to make the bad area one or two pixels bigger all around. The bad spot gets somewhat blurred by the JPEG compression of the real photos. In the TIFF or RAW images the bad spot is absolutely sharp and therefore smaller. Removing bad spots from one photo $ jpegpixi orig.jpg fixed.jpg -f deadpixels.txt or from all photos in the current directory $ jhead -cmd "jpegpixi &i &o -f deadpixels.txt" *.jpg This removes the bad spots by interpolating the colors of the environment to replace the spot. Or make a little script ("removebadpoints") containing the lines #!/bin/sh jhead -cmd "jpegpixi &i &o 1348,838,6 713,1009,4" $* and do $ removebadpoints *.jpg to clean every new set of photos in one simple step. Name photos by their capturing date/time ---------------------------------------- E. g. for sequencializing photos from different cameras $ jhead -n *.jpg Correcting timezone ------------------- To correct photos when you have forgotten to adjust the time of your camera when you were on travel (example here: photos taken in Portland/Oregon in the US, camera was on Central European Time). Very important is to do this in the two separate command lines as shown. Otherwise neither the file date will be set nor the file will be renamed. $ jhead -ta-9 *.jpg $ jhead -ft -n *.jpg (leave out "-n" to not rename) Shrinking photos for web/screen display --------------------------------------- Needs ImageMagick, NOTE: JPEG is recompressed, resolution is lowered, quality loss! It is assumed that the long edge of the destination images should be 640 pixel. Replace all occurences of "640" by your desired length of the long edge (e. g. 1024) if you want to have another size. The photo is always resized to the biggest size which fits into the size given on the "convert" command line keeping the aspect ratio (for 4:3 images the size will be 640x480 for landscape or 480x640 for portrait images). The duplicate mention of the size on the command line is to increase performance, as the JPEG decoding of the input file is already done with the resizing in mind. $ convert -size 640x640 file.jpg -resize 640x640 -quality 75 newfile.jpg Automatic resizing of a series of images (with jhead): $ jhead -cmd "convert -size 640x640 &i -resize 640x640 -quality 75 &o" *.jpg Use this command only on copies of your images, it overwrites the original files. Noise reduction --------------- Needs ImageMagick, NOTE: JPEG is recompressed, resolution is lowered, quality loss! Modify the numerical value to optimize your results. The higher the value the more blurred gets the image, the lower the value the more of the noise still stays visible. $ convert -noise 2 before.jpg after.jpg or for a series of images $ jhead -cmd "convert -noise 2 &i &o" *.jpg Use this command only on copies of your images, it overwrites the original files. Using these manipulations in gqview ----------------------------------- To quickly apply a certain task on the image currently visible in gqview, one can right-click the image and then choose "Edit" in the pop-up-menu. Currently here are only editing tools as GIMP, Electric Eyes, XV, etc. available, but the list can be customized by the user choosing "Edit" in the menu bar, and then "Options". In the upcoming dialog one goes to the "Editors" tab and enters the desired menu entry texts and commands. If a command requires the file name of the image, one inserts the placeholder "%f" at the appropriate place. It is very handy to add entries for the scripts "rotateleft" and "rotateright" shown below and "removebadpoints" shown above. GIMP ---- Some links for photo touch-up and enhancement tutorials (not all can be done automatically by applying command line tools or scripts): Photo-specific: http://gimpguru.org/ General, but many photo-specific: http://mmmaybe.gimp.org/tutorials/ General: http://gimp-savvy.com/BOOK/index.html http://www.gimp.org/tutorials.html Grain/noise remover: http://members.ozemail.com.au/~hodsond/degrain.html GIMP - Red-Eye reduction ------------------------ You can easily remove red eyes in flash photos with the "redeye" GIMP plug-in. The nice thing in this plug-in is that you do not need to mark the red eyes exactly, the plug-in finds the borders of the red puplis by itself. Remote Control for Canon Cameras -------------------------------- Most Canon cameras can be fully remote-controlled with free software using the "capture" utility based in libptp2. Supported are all manual exposure settings and there is even a life viewfinder window. Tools ----- (Most of these are all already part of Mandrake 9.2) GPhoto2: http://www.gphoto.org/ Access for many non-USB-Storage digital cameras, PC-controlled capture. Your camera not supported by last stable release? Download CVS snapshots and/or release candidates from http://n-dimensional.de/projects/digicam/software/snapshots/ (see SUPPORTED-CAMERAS file there). See also http://www.teaser.fr/~hfiguiere/linux/digicam.html dcraw: http://www.cybercom.net/~dcoffin/dcraw/ Reading and converting raw image formats of more than 100 cameras rawphoto: http://ptj.rozeta.com.pl/Soft/RawPhoto GIMP plug-in for dcraw with preview of the parameters applied to the photo, replaces the simple rawphoto plug-in in the dcraw package metacam: http://www.cheeseplant.org/~daniel/pages/metacam.html Reading manufacturer-specific fields in EXIF data mrwtoppm: http://home.swbell.net/dobroom/mintoppm/ Raw converter for the Minolta DiMAGE 5, 7x, A1, with GIMP plug-in jhead: http://www.sentex.net/~mwandel/jhead/ Manipulation of whole photo collections with conservation of EXIF info jpegtran (in utils of libjpeg): http://www.ijg.org/ Loss-less rotation of JPEG images and other manipulations jpegcrop: http://sylvana.net/jpegcrop/ or http://jpegclub.org/ Patch for jpegtran for loss-less cropping of photos jpegpixi: http://jpegpixi.sourceforge.net/ Program for removing bad pixels caused by defects of the CCD of the digital camera. No JPEG recompression loss and no loss of the EXIF data. ImageMagick: http://www.imagemagick.org/ Image conversion on the command line (NO EXIF conservation!), display of image data, display of image with simple GUI tool flphoto: http://www.easysw.com/~mike/flphoto/ GUI for downloading photos from camera or file system, loss-less rotation, simple manipulations, printing index, 1 per sheet, NxM per sheet, with frame, slide show, simple web album gqview: http://gqview.sourceforge.net/ Image display utility redeye: http://www.cs.hmc.edu/~geoff/digicam/, http://www.cs.hmc.edu/~geoff/digicam/redeye GIMP plug-in for easy red-eye removal. capture: http://www.ucl.cas.cz/~petr/plant-growth/ Remote capturing on Canon's digital cameras. GPhoto is not needed. libptp2: http://sourceforge.net/projects/libptp Access to digital cameras via PTP. Includes manufacturer-specific commands for Canon. GPhoto is not needed. Scripts ------- Download on http://www.linuxprinting.org/download/digitalimage/ All scripts take one or more JPEG images as command line arguments (or wildcard patterns as "*.jpg". Non-JPEG files will be skipped. Conversion is done without recompression to avoid compression loss. Published under the terms of the GPL (www.gnu.org). - rotateleft shell script, rotates image by 90 degrees counter-clockwise, needs jhead, jpegtran ------------------------------------------------------------------------- #!/bin/sh jhead -cmd "jpegtran -rot 270 &i > &o" $* ------------------------------------------------------------------------- - rotateright shell script, rotates image by 90 degrees clockwise, needs jhead, jpegtran ------------------------------------------------------------------------- #!/bin/sh jhead -cmd "jpegtran -rot 90 &i > &o" $* ------------------------------------------------------------------------- - crop Perl script, crops images to have a 3:2 ratio, needs ImageMagick, jhead, jpegtran with jpegcrop patch ------------------------------------------------------------------------- #!/usr/bin/perl # crop # ==== # # (C) 2003 by Till Kamppeter # Released under the terms of the GPL (see www.gnu.org). # # "crop" crops JPEG images to a user-specified width/height ratio without # JPEG recompression, so without quality loss. Also EXIF data is conserved. # # It uses the "jpegtran" utility which is part of libjpeg # (http://www.ijg.org/). "jpegtran" needs the patches in either # croppatch.tar.gz or droppatch.tar.gz from http://jpegclub.org/ # (statically linked binary of patched "jpegtran" in both tarballs). # Also "jhead" from http://www.sentex.net/~mwandel/jhead/ and # ImageMagick from http://www.imagemagick.org/ is needed. # # The program simplifies the process by calculating the correct parameters # for "jpegtran" from a user-supplied ratio and by processing multiple # images with one command line. # Check for command line options use Getopt::Std; getopts("r:h"); # Usage info if ($opt_h) { my $prog = $0; $prog =~ s!^.*?([^/]+)$!$1!; print STDERR "\n\"$prog\" crops JPEG images to a user-specified\n"; print STDERR "width/height ratio without JPEG recompression, so without\n"; print STDERR "quality loss.\n\n"; print STDERR "Usage: $prog [ -r ratio ] file1.jpg [ file2.jpg ... ]\n\n"; print STDERR " -r ratio: Width/height ratio or page size.\n"; print STDERR " Ratio: 3:2, 4x6, 8x10, 1:1.414, ...\n"; print STDERR " Page sizes: A1, A2, A3, A4, ...,\n"; print STDERR " Letter, Legal\n"; print STDERR " Photo (3:2), Screen (4:3)\n"; print STDERR " file1.jpg ...: Images to be cropped, more than one\n"; print STDERR " can be specified, must be JPEG\n\n"; } # Default is the ratio for standard 4x6inch/10x15cm photos my $ratiox = 3.0; my $ratioy = 2.0; # Did the user give a ratio via the "-r" option? if (my $ratio = $opt_r) { if ($ratio =~ /^\s*([\d\.]+)\s*[:x\/]\s*([\d\.]+)\s*$/i) { # Explicitly given ratio ("16:9", "8x10", ...) $ratiox = $1; $ratioy = $2; # None of the two values should be zero or negative if (($ratiox <= 0.0) || ($ratioy <= 0)) { die "Invalid ratio: $ratiox:$ratioy!\n"; } # $ratiox must always be greater than $ratioy if ($ratioy > $ratiox) { ($ratiox, $ratioy) = ($ratioy, $ratiox); } } elsif ($ratio =~ /^\s*A\d+\s*$/i) { # European "A" paper format $ratiox = sqrt(2.0); $ratioy = 1.0; } elsif ($ratio =~ /^\s*letter\s*$/i) { # US Letter paper format $ratiox = 11.0; $ratioy = 8.5; } elsif ($ratio =~ /^\s*legal\s*$/i) { # US Legal paper format $ratiox = 14.0; $ratioy = 8.5; } elsif ($ratio =~ /^\s*photo\s*$/i) { # Standard 4x6inch/10x15cm photo format $ratiox = 3.0; $ratioy = 2.0; } elsif ($ratio =~ /^\s*screen\s*$/i) { # The camera does 3:2, but you want to use the photo as desktop # wallpaper $ratiox = 4.0; $ratioy = 3.0; } } # Process all supplied files for my $file (@ARGV) { # Does the file exist and is readable and writable if ((! -r $file) or (! -w $file)) { print STDERR "Cannot process $file, skipping!\n"; next; } my $portrait = 0; # Portrait orientation? # Get dimensions of image file my $width = `identify -format %w $file 2>/dev/null` * 1.0; my $height = `identify -format %h $file 2>/dev/null` * 1.0; # Skip non-image files if (($width <= 0) or ($height <= 0)) { print STDERR "$file is not an image, skipping!\n"; next; } if ($width < $height) { # Portrait orientation, change dimensions $portrait = 1; ($width, $height) = ($height, $width); } my $ratio = $width/$height; # X/Y ratio of current image my $newratio = $ratiox/$ratioy; # Desired X/Y ratio my $r = $ratio/$newratio; next if ($r < 1.01) and ($r > 0.99); # Skip image with desired X/Y ratio if ($r > 1.0) { # We need to crop the short edges, so proceed as with a portrait- # oriented image, but with the reciprocal of the ratio $portrait = 1 - $portrait; ($width, $height) = ($height, $width); $r = 1.0 / $r; } # Calculate new dimensions, store as integer my $newwidth = $width; my $newheight = sprintf("%d", $height*$r); my $xoffset = 0; my $yoffset = sprintf("%d", $height*(1-$r)/2.0); if ($portrait) { # Portrait orientation, change back the dimensions ($width, $height) = ($height, $width); $newwidth = $newheight; $newheight = $height; $xoffset = $yoffset; $yoffset = 0; } # Do a loss-less JPEG cropping to the new dimensions system("jhead -cmd \"jpegtran -crop ${newwidth}x${newheight}+$xoffset+$yoffset &i > &o\" $file"); } -------------------------------------------------------------------------