995c5a6dbbcaaae2b9b06405634619ac4d19f957
[dja/scandal.git] / scan2pages.sh
1 #!/bin/bash
2
3 function usage {
4 cat >&2 << __EOF__ 
5 Usage: $0 [-vfpsmut] [-d depth] pdffile outdir
6 Convert pdffile - a pdf of scanned facing pages - to a set of images in outdir,
7 each with only one page.
8 OPTIONS:
9         -v: Be verbose.
10         -d depth: Use given depth. Default is 1. Unpaper can only handle up to 8.
11         -D dpi: Use given DPI. Colour scans on library scanners are usually 300, bw 400. 
12         -s: skip masking/trimming. Overrides -m.
13         -f: Forceably redo everything.
14         -p: Forceably redo pdf conversion. Implies options below, equivalent to -f.
15         -m: Forceably redo masking/trimming and other preprocessing. Impiles options below.
16         -u: Forceably redo unpaper processing. Implies option below. IGNORED
17         -t: Forceably redo final trimming and cleaning. IGNORED
18 __EOF__
19 }
20
21 ## Setup and utilities ##
22 # Mac OS X doesn't have seq. It has jot instead.
23 Linux_seq="seq"
24 Darwin_seq="jot -"
25 if [[ $(uname) == "Darwin" ]]; then my_seq=$Darwin_seq;
26 else my_seq=$Linux_seq;
27 fi;
28
29
30 ## Process flags ##
31 forcepdf=
32 forcemask=
33 forceunpaper=
34 forceclean=
35 convertflags=
36 unpaperflags=
37 depthflags="-depth 1"
38 dpi=
39 skipmask=
40 verbose=
41 while getopts 'vd:sfpmuc' OPTION
42 do
43         case $OPTION in
44         v)      verbose=1
45                 convertflags="$convertflags -verbose"
46                 unpaperflags="$unpaperflags -v --time"
47                 ;;
48         d)      depthflags="-depth $OPTARG"
49                 ;;
50         D)      dpi=$OPTARG
51                 ;;
52         s)      skipmask=1;
53                 ;;
54         f)      forcepdf=1; forcemask=1; forceunpaper=1; forceclean=1
55                 ;;
56         p)      forcepdf=1; forcemask=1; forceunpaper=1; forceclean=1
57                 ;;
58         m)      forcemask=1; forceunpaper=1; forceclean=1
59                 ;;
60         u)      forceunpaper=1; forceclean=1
61                 ;;
62         t)      forceclean=1
63                 ;;
64 #       b)      bflag=1
65 #               bval="$OPTARG"
66 #               ;;
67         ?)      usage
68                 exit 2
69                 ;;
70         esac
71 done
72 shift $(($OPTIND - 1))
73
74 # check we have an input and output!
75 if [[ $# != 2 ]]; then
76         echo "Wrong number of parameters (2 required, $# given: [$@])" >&2
77         usage
78         exit 2
79 fi
80
81 file=$1
82 dir=$2
83
84 filedir=$(dirname $1)
85 base=$(basename $1 .pdf)
86
87 # make the output dir
88 mkdir -p $dir
89
90 # figure out the number of pages
91 dscname=$dir/${base}.dsc
92 pdf2dsc $file $dscname || exit 1
93 pages=$(awk '$1 ~ "%%Pages" {print $2}' $dscname)
94 echo "Got $pages page(s)."
95 rm $dscname
96
97 # guess at DPI, unless it's been set
98 # the scans do not seem to accurately reflect their resolution.
99 if [[ "$dpi" = "" ]]; then
100         # %k gives the number of colours/shades in the image.
101         # 2 for b/w, and the scanner seems to default to 400 dpi for that
102         # 256 for greyscale, which has to be selected manually (so I'm assuming 300 for no good reason)
103         # 31564 for colour, which defaults to 300
104         if [[ $( convert $file[0] -format "%k" info: || exit 1 ) == 2 ]]; then
105                 dpi=400;
106         else
107                 dpi=300
108         fi
109         if [[ $verbose == 1 ]]; then
110                 echo "DPI guessed at $dpi."
111         fi
112 fi
113
114 # process pages 1 by 1 to avoid convert gobbling all the memory
115 for pg in `$my_seq 1 $pages`; do
116         echo "Processing page $pg."
117         
118         pgn=$(printf '%03d' $pg)
119         
120         # convert from pdf
121         origpnm=$dir/pg-${pgn}.pnm
122         if [[ ! $([ -e $origpnm ]) || $forcepdf ]]; then
123                 convert $convertflags $depthflags -density $dpi $file[$(expr $pg - 1)] \
124                         $origpnm || exit 1
125         fi;
126         
127         # preprocess it!
128         preppnm=$dir/pg-pp-${pgn}.pnm
129         if [[ ! $skipmask && ( ! $([ -e $preppnm ]) || $forcemask ) ]]; then
130                 # create mask: 
131                 # ... downscale, blur,
132                 convert $convertflags -resize 25% -depth 8 -blur 10 $origpnm $dir/pg-mask-${pgn}.pnm ||exit 1
133
134                 # ... get crop co-ords. They're off by ~2 as I don't know how to
135                 # properly correct for the border.
136                 cropcords=$(convert -border 1x1 -bordercolor '#000' -resize 400% -trim -fuzz 90% -format "%wx%h%O" $dir/pg-mask-${pgn}.pnm info: || exit 1)
137                 
138                 # ... crop and despeckle? the final pre-prepared image
139                 convert $convertflags -crop $cropcords $origpnm $preppnm || exit 1
140         elif [[ $skipmask ]]; then
141                 cp $origpnm $preppnm
142         fi;
143         
144         #unpaper it
145         #names go a bit funny here
146         #also, ignore flags starting here
147         unppnm=$dir/upg-${pgn}-%01d.pnm
148         unpaper $unpaperflags --layout double --overwrite --no-blackfilter -ni 10 -op 2 $preppnm $unppnm || exit 1
149
150         # final convert and clean
151         convert $convertflags $dir/upg-${pgn}-?.pnm $dir/upg-${pgn}-%01d.tiff || exit 1
152         
153         
154 done
155
156 mkdir $dir/pages
157 mv $dir/upg-*.tiff $dir/pages
158         

UCC git Repository :: git.ucc.asn.au