#!/bin/sh # # $Id$ # # Edit the (text) comments in one or more JPEG files. # # Usage: # USAGE='Usage: camcomment [-d] [-l] [-m] [-v] jpeg-files' # # First, the current commentary is extracted from all files. The # editor is then invoked on a file with all comments. Each file's # comments are preceded by a header formatted as follows: # # ===== file-name ===== # # When the editor is exited, the revised comments are expected to be # separated by headers in the same format. Any revised comments are # reinserted in the named files; files no longer mentioned in the # edited file are not modified. The script is very sensitive to # format, so be sure to preserve the header lines as they were # originally given. # # Options: # # -d Debug: report what would be done, but don't do it. # -l List: print the headers and comments to stdout, but # don't invoke an editor or modify comments. # -m Metacam: insert any comment that can be extracted with metacam # -v Verbose: report each comment modification as it is done. # debug=false list=false metacam=false verbose=false # # Argument processing # while [ $# -gt 0 ] do case "$1" in -d) debug=true verbose=true ;; -l) list=true ;; -m) metacam=true ;; -v) verbose=true ;; --) shift break ;; -*) echo "$USAGE" 1>&2 exit 2 ;; *) break ;; esac shift done case "$#" in 0) echo "$USAGE" 1>&2 exit 2 ;; esac # # Process all file arguments # #TMP=/tmp/_ccm$$ TMP=_ccm$$ trap "rm -f $TMP.*; exit 1" 1 2 15 trap "rm -f $TMP.*; exit 0" 13 for file do dir=`dirname $file` case "$file" in *.jpg|*.jpeg|*.JPG|*.JPEG) ;; *) echo "Can't handle file '$file', skipping" 1>&2 continue ;; esac echo "===== $file =====" >> $TMP.a if $metacam then metacam -v "$file" 2>/dev/null \ | fgrep '[User Comment]:' \ | awk 'BEGIN \ { hex["0"] = 0 hex["1"] = 1 hex["2"] = 2 hex["3"] = 3 hex["4"] = 4 hex["5"] = 5 hex["6"] = 6 hex["7"] = 7 hex["8"] = 8 hex["9"] = 9 hex["A"] = 10 hex["B"] = 11 hex["C"] = 12 hex["D"] = 13 hex["E"] = 14 hex["F"] = 15 hex["a"] = 10 hex["b"] = 11 hex["c"] = 12 hex["d"] = 13 hex["e"] = 14 hex["f"] = 15 } { comment = "" for (i = 3; i <= NF; i++) { if ($i != "00") { char = \ hex[substr($i, 1, 1)] * 16 + hex[substr($i, 2, 1)] comment = comment sprintf("%c", char) } } while (comment != "" \ && substr(comment, length(comment), 1) == " ") comment = substr(comment, 1, length(comment) - 1) if (comment != "") print comment }' \ >> $TMP.a fi rdjpgcom "$file" | sed '$d' >> $TMP.a done # # If we had any files, bring up the editor and process the results. # if $list then cat $TMP.a elif [ -s $TMP.a ] then # # For reasons I don't understand, some versions of # emacs seem to let a SIGINT (signal 2) through to the # parent shell while they are exiting. This is # inconvenient to say the least, since it aborts the # entire list of pending checkins. So we will ignore # SIGINT while the editor is running. # trap "" 2 ${EDITOR:-vi} $TMP.a trap "rm -f $TMP.*; exit 1" 2 # # Extract a list of files to be recommented, and do so. # firstFile=true for file in `sed -n 's/ *===== *//gp' $TMP.a` do case "$file" in */*) safeName=`echo "$file" | sed 's;/;\\\\/;g'` ;; *) safeName="$file" ;; esac if $verbose then echo "Modifying comment in $file" fi if $debug then continue fi if $firstfile then sed -e 1d -e '/^===== /,$d' $TMP.a \ | wrjpgcom -replace "$file" > $TMP.b firstfile=false else sed -e "1,/^===== $safeName =====/d" -e '/^===== /,$d' $TMP.a \ | wrjpgcom -replace "$file" > $TMP.b fi cp $TMP.b "$file" done fi rm -f $TMP.*