Wednesday, May 13, 2009

Small Linux utiltity for downloading camera images

On Linux, there's a couple programs for downloading pictures off a digital camera (like fspot). Although these apps feel too heavyweight -- and they have too many features I don't want, and not the features I do want.

What I want, is something that automatically downloads pictures off my camera when I plug it in. I don't want a GUI. Also, I'd like to be able to insert post-processing commands... like making a resized (smaller) copy of the image that I can email or post on a web page. The originals are too big to use for anything except archiving.

Fortunately, my camera just connects as a standard USB drive, so a simple bash script would work. Here's one I've written for Ubuntu 8.10 ... should work for later versions as well.


#!/bin/bash

#2008 GPL

#### ABOUT ####
# the sony cybershot camera connects as a standard removable drive
# this script copies pics off the camera and processes images
# for example, create resized copies for web/email around 50k each

#### REQUIRED ####
# sudo apt-get install imagemagick
# then set this script to run under
# nautilus (gnome file browser) -> Edit -> Preferences -> Media -> Photos
# otherwise, you may set up a udev rule
# don't forget to give the script executable privileges

#### CONFIG SECTION ####
# set the directory where the images are at
# browse to this if you are not sure (after pluging in camera)
# this should be under /media/ somewhere
camdir=/media/disk/DCIM/101MSDCF

# where pics will copy to the local hardrive:
picdir=~/Pictures/original

# where the resized pics will be copied:
resizedir=~/Pictures/resized

# file preview app:
imgbrowser=nautilus

# where operations will be logged:
log=/tmp/cameracopy-$(date +%F).log

#### IMAGE TRANSFER ####

echo "loading..." >> $log

# a folder containing links to all new files
new_files=$picdir/new

# a folder containing links representing
# the last known file structure on camera
# MAKE SURE THIS VARIABLE IS SET (used in rm)
camera_snapshot=$picdir/camera_snapshot

# all other files will be hashed by date in dirs
# global file hash for directories: year/month
HASH="+%Y/%m"

#### alt global file hash for directories: year/month/day
###HASH="+%Y/%m/%d"

# check output dirs
# create if needed
mkdir -p $picdir
mkdir -p $new_files
mkdir -p $camera_snapshot

# wait a little for camera to load in system
# check for existence of folder
while [[ ! -e $camdir ]]
do
echo "sleep" >> $log
sleep 1
done

#### SYNC UP CAMERA TO LOCAL FILE SYSTEM ####
while read f
do
if [[ ! -e "$camdir/$f" ]]
then

#double check camera still mounted
if [[ ! -e "$camdir" ]]
then
echo "error: camera directory $camdir not mounted!" >> $log
exit
fi

# remove out-dated links
echo "old $camdir/$f" >> $log
rm "$camera_snapshot/$f"

fi
done < <(find $camera_snapshot -type f -printf '%f\n')

#### TEST FOR NEW PICS ####
while read f
do

# copy new pics from camera to local storage
# and save reference to filename (link)
if [[ ! -e "$camera_snapshot/$f" ]]
then

#double check camera still mounted
if [[ ! -e "$camdir" ]]
then
echo "error: camera directory $camdir not mounted!" >> $log
exit
fi

echo "new $camdir/$f" >> $log
file_hash=$(date -r "$camdir/$f" $HASH)
mkdir -p $picdir/$file_hash
# copy or move, depending on whether you want pics left on camera
cp "$camdir/$f" "$picdir/$file_hash/$f"
# mv "$camdir/$f" "$picdir/$file_hash/$f"
# save link to new images
ln "$picdir/$file_hash/$f" "$new_files/$f"

fi
done < <(find $camdir -type f -printf '%f\n')

echo "finished camera download" >> $log

zenity --info --title="Download Complete" --text="All the pictures have been downloaded from the camera. You may turn the camera off and unplug it. Please wait while images are processed." &

#### POST IMAGE POCESSING ####

opened_viewer="0"

# test for new pics
while read f
do

# hash files by create year/month
# so number of files/dir is low
file_hash=$(date -r "$new_files/$f" $HASH)
mkdir -p $resizedir/$file_hash

# open an image previewer to first resized pic
if [[ $opened_viewer == "0" ]]
then
#proc_running=$( ps aux | grep "$resizedir/$file_hash" | grep -v grep )
#if [[ $proc_running == "" ]]
#then
$imgbrowser $resizedir/$file_hash &
#else
# echo "$imgbrowser already open" >> $log
#fi
opened_viewer="1"
fi

# resize picture
echo "resize to $resizedir/$file_hash/$f" >> $log
convert -resize 460 -quality 60 \
"$picdir/$file_hash/$f" "$resizedir/$file_hash/$f"


#### PROCESS IMAGES ####
# add more image processing here ...
# link on hard drive is at $new_files/$f
# actual file is at $picdir/$file_hash/$f
#### PROCESS IMAGES ####


# if processor slow
#sleep 1

# done with new files... move link to last known cam dir snapshot
mv "$new_files/$f" "$camera_snapshot/"

done < <(find $new_files -type f -printf '%f\n')


echo "exit" >> $log
exit

No comments: