#!/bin/sh
#
# Description - read photos from CF/SD memory card, copy them to destination folder,
# auto-rotate images (Exif info used), add date-time to filename (Exif info used)
#
# Usage:
# foto-copy -- just copy all photos from memory card to your disk
# foto-copy remove -- copy all photos to your disk and remove them from your memory card
#
# Requirements:
# jhead - renaming
# exiv2 - Exif tag manipulations
# dcraw (for RAW photos)
# ppmtojpeg (for RAW photos)
# jpegtran - lossless JPEG rotation
# acpi - only for laptops
#
# Developed by Lubomir Host 'rajo' <rajo AT platon.sk>
# Copyright (c) 2005-2014 Platon Group, http://platon.sk/
# Licensed under terms of GNU General Public License.
# All rights reserved.
#
# Changelog:
# 2005-??-?? - created
# 2006-08-14 - enhanced - images are auto-rotated - Exif tag Exif.Image.Orientation is used
#
# $Platon: scripts/shell/photo-managment/foto-copy,v 1.6 2011-03-21 20:56:18 rajo Exp $
# where to mount you memory card - configure in /etc/fstab something like this:
# /dev/sdb1 /foto vfat iocharset=iso8859-2,umask=002,codepage=852,showexec,users,gid=users,noauto,nodev,nosuid,quiet 0 0
#MOUNTPOINT="/foto"
MOUNTPOINT="/media/usb0"
# where to copy your photos for sorting - /home/rajo/media/foto/2006/
DEST="$HOME/media/foto/`date +%Y`"
#@DEST="$HOME/tmp/foto-copy-test"
# wildcard names of your original photos
RENAME_FILES="PICT*.JPG pict*.jpg img_*.jpg IMG_*.JPG dsf*.jpg DSC*.JPG dsc*.jpg"
# howto rename your files: img_1234.jpg --> 2006-08-13_230001_img_1234.jpg (image taken on 2006-08-13 23:00:01)
JHEAD_OPTS="-autorot -n%Y-%m-%d_%H%M%S_%f"
# paths setup:
JHEAD="jhead"
DCRAW="dcraw"
EXIV2="exiv2"
PPMTOJPEG="ppmtojpeg"
ACPI="acpi"
if [ ! -d $DEST ]; then
mkdir -p $DEST;
fi
cd $DEST
# clean up extensions {{{
for i in *.JPG *.jpeg *.JPEG *.CRW *.CR2; do
[ "x$i" = "x*.JPG" ] && continue
[ "x$i" = "x*.JPEG" ] && continue
[ "x$i" = "x*.jpeg" ] && continue
[ "x$i" = "x*.CRW" ] && continue
[ "x$i" = "x*.CR2" ] && continue
if [ "x${i%.JPG}" != "x$i" ]; then # change *.JPG --> *.jpg
mv "$i" "${i%.JPG}.jpg"
fi
if [ "x${i%.JPEG}" != "x$i" ]; then # change *.JPEG --> *.jpg
mv "$i" "${i%.JPEG}.jpg"
fi
if [ "x${i%.jpeg}" != "x$i" ]; then # change *.jpeg --> *.jpg
mv "$i" "${i%.jpeg}.jpg"
fi
if [ "x${i%.CRW}" != "x$i" ]; then # change *.CRW --> *.crw
mv "$i" "${i%.CRW}.crw"
fi
if [ "x${i%.CR2}" != "x$i" ]; then # change *.CR2 --> *.cr2
mv "$i" "${i%.CR2}.cr2"
fi
done # }}}
# lossless rotation of JPEG files
do_rotation()
{ # {{{
rrfile="$1"
degres="$2"
echo -e "\t--> rotating $degres $rrfile"
if jpegtran -rotate $degres -copy all -outfile ${rrfile}_tmp ${rrfile};
then
echo -e "\t\tRotated"
mv ${rrfile}_tmp ${rrfile}
$EXIV2 -M'del Exif.Image.Orientation' $rrfile
else
echo -e "\t\tFailed"
rm ${rrfile}_tmp
fi
} # }}}
# distinguish angle of rotation
rotate_jpeg()
{ # {{{
rfile="$1"
orient=`$EXIV2 -P kyv $rfile | awk '/Exif.Image.Orientation/ { print $3; }'`
case "$orient" in
1) echo "$rfile: Orientation: $orient top left";
;;
6) echo "$rfile: Orientation: $orient right top";
do_rotation $rfile 90
;;
8) echo "$rfile: Orientation: $orient left bottom";
do_rotation $rfile 270
;;
*) echo "$rfile: Orientation: $orient UNKNOWN";
;;
esac
} # }}}
#
# mount, copy, umount # {{{
#
# is memory card mounted?
grep -q $MOUNTPOINT /etc/mtab
if [ $? = 1 ]; then
echo "Mounting $MOUNTPOINT"
available_devs=`awk "\\$2 == \"$MOUNTPOINT\" { print \\\$1; }" /etc/fstab`
if [ -z "$available_devs" ]; then
echo "ERROR: mountpoint '$MOUNTPOINT' not found in /etc/fstab"
exit 1;
fi
for dev in $available_devs; do
if [ -e $dev ]; then
echo "Mounting '$dev'"
mount $dev
break;
fi
done
#mount $MOUNTPOINT
make_umount="yes"
fi
count=1
# copy all files from memory card to destination folder
for file in `find $MOUNTPOINT -type f -print`; do
echo "$count: Copying file $file";
cp $file $DEST || exit 1
count=$(( count + 1))
done
# if first parameter is 'remove', remove files from memory card
if [ "x$1" = "xremove" ]; then
echo "REMOVED REMOVED REMOVED start:";
find $MOUNTPOINT -type f -print -exec rm -f {} \;
echo "REMOVED REMOVED REMOVED end:";
fi
# umount CF, if was mounted by this script
if [ "x$make_umount" = "xyes" ]; then
echo "Umounting $MOUNTPOINT"
umount $MOUNTPOINT
fi
# }}}
# now rotate and rename your JPEG files from your CF card
for ren in $RENAME_FILES; do
[ "x$ren" = "xpict*.jpg" ] && continue
[ "x$ren" = "xPICT*.JPG" ] && continue
[ "x$ren" = "ximg_*.jpg" ] && continue
[ "x$ren" = "xIMG_*.jpg" ] && continue
[ "x$ren" = "xIMG_*.JPG" ] && continue
[ "x$ren" = "xdsf*.jpg" ] && continue
[ "x$ren" = "xDSC*.JPG" ] && continue
[ "x$ren" = "xdsc*.jpg" ] && continue
#@rotate_jpeg $DEST/$ren
chmod a-x $DEST/$ren
$JHEAD $JHEAD_OPTS $DEST/$ren
done
# if we are not on battery, do CPU expensive job - decode RAW files to JPEG,
# add Exif info from thumbnail image *.thm to *.jpeg, rotate images, ...
on_bat=`$ACPI 2>/dev/null | awk '/discharging/ { print $3; }'`
if [ "x$on_bat" = "xdischarging," ]; then
if [ "x$1" = "xremove" ]; then
echo "On battery, do not decode RAW files"
exit 0;
fi
fi
find $DEST -maxdepth 1 -type f \( -name '*.CTG' -o -name '*.ctg' \) -ls -delete
# decode raw files - CPU expensive job...
echo "Decoding RAW files..."
for i in img_*.crw img_*.cr2 IMG_*.CRW CRW_*.CRW IMG_*.CR2; do # {{{
[ "x$i" = "ximg_*.crw" ] && continue
[ "x$i" = "ximg_*.cr2" ] && continue
[ "x$i" = "xIMG_*.CRW" ] && continue
[ "x$i" = "xCRW_*.CRW" ] && continue
[ "x$i" = "xIMG_*.CR2" ] && continue
small_i="`echo $i | tr '[A-Z]' '[a-z]'`"
if [ "x$i" != "x$small_i" ]; then
mv "$i" "$small_i";
# convert *.THM file to lowercase
t="${i%.CRW}.THM"
if [ -f "$t" ]; then
small_t="`echo $t | tr '[A-Z]' '[a-z]'`"
mv "$t" "$small_t"
fi
fi
# file has been renamed to lowercase, change variable
i="$small_i"
ext="${i#*\.}"
file="${i%.crw}"
file="${file%.cr2}"
if [ ! -f "$file.jpg" ]; then
echo --- $i;
chmod a-x $i
$DCRAW -w $i # use white ballance set by camera
$PPMTOJPEG $file.ppm > $file.jpg && rm -f $file.ppm ;
else
echo "===== Skipping RAW version of '$file.jpg'"
continue
fi
# set EXIF information:
rm -f $file.exv $file-thumb.jpg
$EXIV2 ex $i
[ -f $file.thm ] && ln -s $file.thm $file-thumb.jpg
# doesn't work correctly
#$EXIV2 -it $file.thm $file.jpg
# use Exif info from *.thm file otherwise from *.crw file
if [ -f "$file.thm" ]; then
$EXIV2 -P kyv $file.thm | awk 'NF > 2 { print; }' | sed 's/^/set /g;' > $file.cmd
else
$EXIV2 -P kyv $i | awk 'NF > 2 { print; }' | sed 's/^/set /g;' > $file.cmd
fi
$EXIV2 -m $file.cmd $file.jpg
# fix: Canon EOS 300D Digital Rebel stores wrong Exif.Image.Orientation info *.thm files
# Exif.Image.Orientation needs to be read from RAW image
#$EXIV2 -P kyv $file.crw | awk '/Exif.Image.Orientation/ { print; }' | sed 's/^/set /g;' > $file.cmd
#$EXIV2 -m $file.cmd $file.jpg
# rotate image if needed - we don't need rotate this JPEG file, because
# orientation will be fixed if Exif.Image.Orientation Exif tag is removed.
#rotate_jpeg $file.jpg
# remove incorrect Exif headers (taken from thumbnail or after rotation)
$EXIV2 \
-M'del Exif.Image.XResolution' \
-M'del Exif.Image.YResolution' \
-M'del Exif.Image.Orientation' \
$file.jpg
# cleanup
rm -f $file-thumb.jpg
rm -f $file.exv
rm -f $file.cmd
# rename decoded *.jpg and RAW file too
$JHEAD $JHEAD_OPTS $file.jpg | while read jpg arrow newjpg; do
mv "${jpg%.jpg}.$ext" "${newjpg%.jpg}.$ext"
t="${jpg%.jpg}.thm"
[ -f "$t" ] && mv "$t" "${newjpg%.jpg}.thm"
done
done # }}}
#echo "Removing unused *.thm files"
#for i in *.thm; do
# if [ ! -f "${i%.thm}.crw" ]; then
# echo "$i removed"
# rm -f $i;
# fi
#done
# vim: fdm=marker fdl=0 fdc=3
Platon Group <platon@platon.sk> http://platon.sk/
|