rewritten for posix-shell (dash), added improvements
[anondcim.git] / anondcim
1 #!/bin/sh
2
3 # anondcim
4 # forked from http://code.sotun.de/git/anondcim/
5
6 die() { 
7     echo "$*" >&2
8     exit 1
9 }
10
11 err() { 
12     echo "$*" >&2
13 }
14
15 rand() {
16     # random number between 0 and $1 - 1
17     # read from urandom, sh interpretes numbers with leading 0 wrong, so prepend $1 which doesn't change the result
18     echo $(( $1$(tr -dc "0-9" < /dev/urandom | head -c $((${#1} + 1))) % $1 ))
19 }
20
21 [ $# -gt 0 ] || die "Usage: $0 [-p image_prefix] [-s destination_size (absolute or percentage)] [-d destination_directory] imagefile(s)"
22
23 [ ! -x "$(which convert)" ] && die "ImageMagick (convert, identify) is not installed"
24 [ ! -x "$(which jhead)" ] && [ ! -x "$(which exiftool)" ] && die "jhead or exiftool has to be installed"
25
26 # set default values
27 file_prefix=""
28 dst_size="1280"
29 dst_dir="--same--"
30
31 while getopts ':p:s:d:' OPTION
32 do
33     case $OPTION in
34         "p")
35             file_prefix="${OPTARG}_"
36         ;;
37         "s")
38             dst_size="$OPTARG"
39         ;;
40         "d")
41             # enforce a trailing "/"
42             [ -d "${OPTARG%/}/" ] && dst_dir="${OPTARG%/}/" || die "destination directory \"${OPTARG%/}/\" does not exist"
43         ;;
44         *)
45             err "not recognised: OPTION=$OPTION, OPTARG=$OPTARG"
46         ;;
47     esac
48 done
49 shift $(($OPTIND - 1))
50
51 cur=1
52 total=$#
53
54 for fn in "$@"
55 do
56     if [ "$dst_dir" = "--same--" ]
57     then
58         # if the filename contains a "/" then use this dir
59         [ "$fn" != "${fn%/*}" ] && dst="${fn%/*}/" || dst=""
60     else
61         dst="$dst_dir"
62     fi
63     # always use a padded number as destination filename suffix
64     dst="$dst$file_prefix$(echo -n "0000000000$cur" | tail -c ${#total}).jpg"
65     echo "anonymizing \"$fn\" to \"$dst\" ($cur/$total)"
66     [ -f "$fn" ] || { err "source \"$fn\" does not exist and is skipped"; continue; }
67     [ -e "$dst" ] && { err "destination \"$dst\" for source \"$fn\" already exists, anonymization is skipped"; continue; }
68     
69     read w h << EOF
70 $(identify -format '%w %h' "$fn")
71 EOF
72     
73     # resize and distort
74     if [ $w -ge 100 ] && [ $h -ge 100 ]
75     then
76         if [ $w -ge 1000 ]; then dw=$(($w / 100)); else dw=10; fi
77         if [ $h -ge 1000 ]; then dh=$(($h / 100)); else dh=10; fi
78         
79         w=$(($w - 1))
80         h=$(($h - 1))
81         
82         convert "$fn" \
83             -colorspace RGB \
84             -distort Perspective "$(rand $dw) $(rand $dh) 0 0, $(($w - $(rand $dw))) $(rand $dh) $w 0, $(rand $dw) $(($h - $(rand $dh))) 0 $h, $(($w - $(rand $dw))) $(($h - $(rand $dh))) $w $h" \
85             -filter gaussian -define filter:support=5 -define filter:sigma=0.5 \
86             -attenuate 2 +noise Uniform \
87             -resize "$dst_size" \
88             -colorspace sRGB \
89             "$dst"
90     else
91         err "image is too small to be distorted and will just be filtered and resized"
92         convert "$fn" \
93             -colorspace RGB \
94             -filter gaussian -define filter:support=5 -define filter:sigma=0.5 \
95             -attenuate 2 +noise Uniform \
96             -resize "$dst_size" \
97             -colorspace sRGB \
98             "$dst"
99     fi
100     
101     # remove metadata
102     if [ -x "$(which jhead)" ]
103     then
104         jhead -purejpg -q "$dst" || err "removing meta-data with jhead failed"
105     fi
106     if [ -x "$(which exiftool)" ]
107     then
108         exiftool -overwrite_original -all= "$dst" || err "removing meta-data with exiftool failed"
109     fi
110
111     cur=$(($cur + 1))
112 done
113