wok view sane-backends/stuff/tazpanel/sane.cgi @ rev 21769

sane-backends: enlarge preview image
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Jul 01 12:04:05 2019 +0200 (2019-07-01)
parents ab1b43f95995
children 808a9e7827f1
line source
1 #!/bin/sh
2 #
3 # Scanner CGI interface - Scan documents via a browser
4 #
5 # (C) 2015 SliTaz GNU/Linux - BSD License
6 #
8 # Common functions from libtazpanel
9 . lib/libtazpanel
10 get_config
12 #------
13 # menu
14 #------
16 case "$1" in
17 menu)
18 TEXTDOMAIN_original=$TEXTDOMAIN
19 export TEXTDOMAIN='sane'
21 cat <<EOT
22 <li><a data-icon="text" href="sane.cgi"$(groups | grep -q scanner ||
23 echo ' data-root')>$(_ 'Scanner')</a></li>
24 EOT
25 export TEXTDOMAIN=$TEXTDOMAIN_original
26 exit
27 esac
29 TITLE="$(_ 'TazPanel - Hardware') - $(_ 'Scanner')"
31 inrange() {
32 local n=$1
33 [ $1 -lt $2 ] && n=$2
34 [ $1 -gt $3 ] && n=$3
35 echo $n
36 }
38 getgeometry() {
39 CMD=""
40 ARGS=""
41 for i in x y l t ; do
42 j=$(inrange $(xPOST geometry_$i) $(xPOST ${i}_min) $(xPOST ${i}_max))
43 eval "geometry_$i=$j"
44 CMD="$CMD -$i $j"
45 ARGS="$ARGS $j"
46 done
47 for i in $(POST) ; do
48 case $i in
49 preview|format|resolution|res_min|res_max|l_min|l_max);;
50 geometry_l|t_min|t_max|geometry_t|x_min|x_max|geometry_x);;
51 y_min|y_max|geometry_y|tmpreview|device|params);;
52 *) v="$(xPOST $i)"; i="--${i//_/-}"
53 case "$v" in
54 '') ;;
55 yes|no) CMD="$CMD $i=$v" ;;
56 *) CMD="$CMD $i '$v'" ;;
57 esac
58 esac
59 done
60 resolution=${1:-0}
61 if [ $resolution -eq 0 ]; then
62 resolution=$(xPOST res_min)
63 width=$(GET width)
64 [ ${geometry_x:-0} -le 0 ] && geometry_x=$(xPOST x_max)
65 while [ $((${resolution:=150} * ${geometry_x%.*})) -lt ${width:-8192} ]; do
66 resolution=$(($resolution * 2))
67 done
68 fi
69 case "$(xPOST mode)" in
70 *lack*|*ineart*) mode="-monochrome" ;;
71 *ray*) mode="-colorspace gray" ;;
72 *) mode="" ;;
73 esac
74 [ -d tmp ] || ln -s /tmp tmp
75 case "$device" in
76 fake*) f=$(ls fake-sane/*.png | sed q)
77 [ -s "$f" ] || f=/usr/share/images/slitaz-banner.png
78 c="$(echo $ARGS $(identify $f | sed \
79 's/.* \([0-9]*\)x.*/\1/') $(GET width) $(POST x_max) | awk '
80 function a(x) { return int(($x * $5)/ $7); }
81 { printf "%dx%d+%d+%d -resize %dx%d",a(1),a(2),a(3),a(4),$6,int(($2*$6)/$1)}
82 ')"
83 suf="png"; [ "$1" ] && suf="pnm"
84 cat <<EOT
85 if convert -crop $c $mode $f /tmp/sane$$.$suf ; then
86 cat /tmp/sane$$.$suf
87 rm -f /tmp/sane$$.$suf
88 else
89 cat $f
90 fi 2> /dev/null
91 EOT
92 ;;
93 *) echo -n "scanimage -d '$(echo $device | sed 's/,.*//')' --resolution '$(inrange $resolution $(xPOST res_min) $(xPOST res_max))dpi'$CMD"
94 if [ -z "$1" -a "$(which convert)" ]; then
95 echo -n "> /tmp/sane$$.pnm ; convert -resize "
96 echo $ARGS 1024 | awk '{ printf "%dx%d",$5,int(($2*$5)/$1)}'
97 echo -n " /tmp/sane$$.pnm /tmp/sane$$.png ;"
98 echo -n "cat /tmp/sane$$.png ; rm -f /tmp/sane$$.pn?"
99 fi
100 esac
101 }
103 imgformat() {
104 tmp=$(mktemp -u -t tazsane.XXXXXX)
105 while read key name type exe pkg cmd ; do
106 case "$key" in
107 \#*) continue
108 esac
109 case "$1" in
110 list)
111 echo -n "<option value=\"$key\""
112 disabled=""
113 for i in ${exe//|/ }; do
114 [ "$(which $i 2> /dev/null)" ] ||
115 disabled=" disabled title=\"$i not found: install package $pkg\""
116 done
117 echo -n "$disabled"
118 [ "$key" == "pnm" ] &&
119 echo -n " title=\"not supported by most browsers\""
120 echo ">$key" ;;
121 *)
122 case "$key" in
123 $(xPOST format)|'*')
124 case "$HTTP_USER_AGENT" in
126 # Tazweb has no download support
127 TazWe*) rm -f /tmp/$name
128 eval "$(getgeometry $(xPOST resolution)) $cmd >/tmp/$name" 2> $tmp.err
129 if [ -s /tmp/$name ]; then
130 info="Stored in /tmp/$name ($(stat -c %s /tmp/$name) bytes)."
131 else
132 error="$(sed 's|$|<br />|' $tmp.err)"
133 [ "$error" ] || error="I/O error"
134 fi
135 rm -f $tmp.* ;;
137 # Others should work
138 *) header "Content-Type: $type" \
139 "Content-Disposition: attachment; filename=$name" \
141 eval "$(getgeometry $(xPOST resolution)) $cmd"
142 rm -f $tmp.*
143 exit ;;
144 esac ;;
145 esac ;;
146 esac
147 done <<EOT
148 #png tazsane.png image/png pnm2png|convert imagemagick > $tmp.pnm; [ "$(which pnm2png)" ] && pnm2png < $tmp.pnm || convert $tmp.pnm png:-
149 png tazsane.png image/png convert imagemagick > $tmp.pnm; convert $tmp.pnm png:-
150 jpeg tazsane.jpg image/jpeg convert imagemagick > $tmp.pnm; convert $tmp.pnm jpg:-
151 jpeg2000 tazsane.jp2 image/jpeg2000-image convert imagemagick > $tmp.pnm; convert $tmp.pnm jp2:-
152 tiff tazsane.tiff image/tiff convert imagemagick > $tmp.pnm; convert $tmp.pnm tiff:-
153 ps tazsane.ps application/postscript convert imagemagick > $tmp.pnm; convert -page A4+0+0 $tmp.pnm ps:-
154 pdf tazsane.pdf image/pdf convert imagemagick > $tmp.pnm; convert $tmp.pnm pdf:-
155 ocr1 tazsane-OCR1.txt text/plain gocr gocr | gocr -
156 ocr2 tazsane-OCR2.txt text/plain tesseract tesseract-ocr | tesseract stdin stdout
157 pnm tazsane.pnm image/pnm true slitaz
158 EOT
159 }
161 xPOST() {
162 [ "$preview" == "reset" ] || POST $@
163 }
165 tmpreview="$(POST tmpreview)"
166 find tmp/ -name 'tazsane*' -mmin +60 -prune -exec rm -f {} \;
168 device="$(POST device)"
169 preview="$(POST preview)"
170 info=""
171 error=""
173 case " $(POST) " in
174 *\ reset\ *)
175 unset device tmpreview
176 preview="reset" ;;
177 *\ preview\ *)
178 [ "$tmpreview" ] || tmpreview=$(mktemp -u -t tazsane.XXXXXX).png
179 tmp=$(mktemp -u -t tazsane.XXXXXX)
180 eval "$(getgeometry)" > $tmp.pnm 2> $tmp.err
181 if [ -s "$tmp.pnm" ]; then
182 convert $tmp.pnm $tmpreview > /dev/null 2>&1 ||
183 pnm2png < $tmp.pnm > $tmpreview ||
184 cp $tmp.pnm $tmpreview
185 else
186 error="$(sed 's|$|<br />|' $tmp.err)"
187 rm -f $tmpreview
188 fi
189 rm -f $tmp.pnm $tmp.err ;;
190 *\ scan\ *)
191 imgformat download ;;
192 esac
194 header
195 xhtml_header
196 [ -n "$error" ] && msg warn "$error"
197 [ -n "$info" ] && msg tip "$info"
198 if [ -z "$device" ]; then
199 suggested=""
200 while read exe pkg msg; do
201 [ "$(which $exe 2> /dev/null)" ] && continue
202 suggested="$suggested
203 <li><a href=\"/user/pkgs.cgi?info=$pkg\">$pkg</a>&nbsp;$msg</li>"
204 done <<EOT
205 convert imagemagick $(_ "to preview images and support more image formats (recommended)")
206 gocr gocr $(_ "a basic optical character recognition")
207 tesseract tesseract-ocr $(_ "a better optical character recognition")
208 EOT
209 [ "$suggested" ] &&
210 msg tip "$(_ "You may need to install:") <ol>$suggested</ol>"
211 all="$(scanimage -f '%d,%v %m|'|\
212 cat - sane-fake.log fake-sane/sane-fake.log |sed 's/|/\n/g')"
213 case "$(echo "$all" | wc -l)" in
214 1) if [ -z "$all" ]; then
215 msg warn "$(_ "No scanner found")"
216 msg tip "$(_ "You can test this GUI with ")\
217 <a href=\"/user/pkgs.cgi?info=fake-sane\">fake-sane</a>"
218 xhtml_footer
219 exit 0
220 fi
221 if [ "$suggested" ]; then
222 cat <<EOT
223 <section>
224 <header>
225 <form name="scanner" method="post">
226 <input type="hidden" name="device" value="$all">
227 Scanner ${all#*,}
228 <button data-icon="start">Continue</button>
229 </form>
230 </header>
231 </section>
232 EOT
233 xhtml_footer
234 exit 0
235 fi
236 device="${all%|}" ;;
237 *)
238 cat <<EOT
239 <section>
240 <header>
241 <form name="scanner" method="post">
242 Scanner
243 <select name="device" size=1>
244 EOT
245 echo "$all" | awk -F, '{ if (NF > 0) print "<option value=\"" $0 "\">" 1+i++ " - " $2 }'
246 cat <<EOT
247 </select>
248 <button data-icon="start">$(_ "Continue")</button>
249 </form>
250 </header>
251 </section>
252 EOT
253 xhtml_footer
254 exit 0 ;;
255 esac
256 fi
258 cat <<EOT
259 <section>
260 <form name="parameters" method="post" style="width:100%">
262 <header>
263 $(echo $device | sed 's/.*,//')
264 <div class="float-right">
265 <button name="scan" data-icon="start">$(_ "Scan")</button>
266 <button name="reset" data-icon="refresh">$(_ "Reset")</button>
267 <button name="preview" data-icon="view">$(_ "Preview")</button>
268 </div>
269 </header>
271 <table style="width:100%">
272 <tr>
273 <td title="Sets the file format for the scanned image">
274 <fieldset><legend>$(_ 'Format')</legend>
275 <select name="format" size=1>
276 $(imgformat list)
277 </select>
278 </fieldset>
279 </td>
280 EOT
282 if [ "$(xPOST params)" ]; then
283 params="$(xPOST params | uudecode)"
284 else
285 params="$({
286 cat "$(echo $device | sed 's/,.*//').log" 2> /dev/null ||
287 scanimage --help -d "$(echo $device | sed 's/,.*//')"
288 } | dos2unix | sed 's|\[=| [|;s/||/|/g' | awk '
289 function minmax()
290 {
291 inactive=1
292 if (match($2,"[0-9]")) {
293 i=$2; sub(/\.\..*/,"",i)
294 j=$2; sub(/.*\.\./,"",j)
295 sub(/\..*/,"",j); sub(/[dm%].*/,"",j)
296 k=$0; sub(/.* \[/,"",k); sub(/\].*/,"",k)
297 printf("\n%s",$1 " " int(k) " " int(i) " " int(j))
298 inactive=0
299 }
300 }
302 function enum()
303 {
304 i=$0
305 inactive=1
306 if (index(i,"|")) {
307 sub(/^ *--*[a-z-]* */,"",i)
308 sub(/\[\(/,"",i); sub(/\)\]/,"",i)
309 sub(/dpi .*/,"",i); gsub(/ \[.*\].*/,"",i)
310 k=$0; sub(/.* \[/,"",k); sub(/\].*/,"",k)
311 gsub(/ /,"=",k)
312 gsub(/ /,"=",i)
313 printf("\n%s",$1 " " k " enum " i)
314 inactive=0
315 }
316 else minmax()
317 }
319 {
320 if (/scanimage --help/) end=1
321 if (end != 0) next
322 if (/:$/) parse=0
323 if (/Scan mode/ || /Mode/ || /Advanced/ || /Geometry/) parse=1
324 if (parse != 1) next
325 if (/\[inactive\]/) { inactive=1; next }
326 if (match("-l-t-x-y", $1)) minmax()
327 else if (/^ --/) enum()
328 else if (!/:$/ && inactive == 0) printf(" %s",$0)
329 } END { print "" }
330 ' | sed 1d)"
331 fi
332 output="$(n=$(echo "$params" | wc -l); echo "$params" | \
333 while read name def min max help; do
334 name="${name#-}"
335 name="${name#-}"
336 name="${name//-/_}"
337 help="$(echo $help | sed 's| | |g;s|"|\&#34|g')"
338 def="${def//=/ }"
339 max="${max//=/ }"
340 if [ "$min" == "enum" ]; then
341 res_min=1000000
342 res_max=0
343 echo "<td title=\"$help\"><fieldset><legend>$name</legend>"
344 echo -n "<select name=\"$name\" size=1"
345 [ "$name" == "resolution" ] && echo -n " onchange=showGeometry()"
346 echo ">"
347 IFS="|"; set -- $max ; unset IFS
348 while [ "$1" ]; do
349 echo -n "<option value=\"$1\""
350 [ "$(xPOST $name)" == "$1" ] && echo -n " selected"
351 [ -z "$(xPOST $name)" -a "$def" == "$1" ] && echo -n " selected"
352 echo ">$(_ "$1")"
353 if [ "$name" == "resolution" ]; then
354 [ $res_max -lt $1 ] && res_max=$1
355 [ $res_min -gt $1 ] && res_min=$1
356 fi
357 shift
358 done
359 echo "</select>"
360 else
361 [ "$(xPOST $name)" ] && def=$(xPOST $name)
362 [ $def -lt $min ] && def=$min
363 [ $def -gt $max ] && def=$max
364 f="<fieldset><legend>$(_ "$name")</legend><input type=\"range\" min=\"$min\" max=\"$max\" name=\"$name\" value=\"$def\""
365 u=""
366 case "$name" in
367 x|y|l|t) cat <<EOT
368 :${name}_max=$max
369 <input type="hidden" name="${name}_min" value="$min">
370 <input type="hidden" name="${name}_max" value="$max">
371 EOT
372 while read name2 n2 id val; do
373 [ "$name" == "$name2" ] || continue
374 [ "$(xPOST geometry_$name)" ] &&
375 val="$(xPOST geometry_$name)"
376 f="<fieldset><legend>$(_ "$n2")</legend><input name=\"geometry_$name\" id=\"$id\" value=\"$val\""
377 u="&nbsp;mm"
378 break
379 done <<EOT
380 l X-Offset x 0
381 t Y-Offset y 0
382 x Width width $max
383 y Height height $max
384 EOT
385 esac
386 [ "$name" == "resolution" ] && f="$f onchange=showGeometry()"
387 echo "<td>$f type=\"text\" title=\"$min .. $max. $help\" size=4 maxlength=4>$u"
388 res_min=$min
389 res_max=$max
390 fi
391 case "$name" in
392 resolution) cat <<EOT
393 <input type="hidden" name="res_min" value="$res_min">
394 <input type="hidden" name="res_max" value="$res_max">
395 &nbsp;dpi
396 EOT
397 esac
398 echo "</filedset></td>"
399 n=$(($n - 2))
400 case "$n" in
401 1|2) echo "</tr><tr>"
402 esac
403 done)"
404 echo "$output" | sed '/^:/d'
406 org_x=$(xPOST geometry_x); [ "$org_x" ] || org_x=$(echo "$output" | sed '/^:x_max=/!d;s/.*=//')
407 org_y=$(xPOST geometry_y); [ "$org_y" ] || org_y=$(echo "$output" | sed '/^:y_max=/!d;s/.*=//')
409 cat <<EOT
410 </tr>
411 </table>
412 <input type="hidden" name="tmpreview" value="$tmpreview">
413 <input type="hidden" name="device" value="$device">
414 <input type="hidden" name="params" value="$(echo "$params" | uuencode -m -)">
415 <script language="JavaScript" type="text/javascript">
416 <!--
417 function setGeometry(x,y) {
418 document.parameters.geometry_x.value = x;
419 document.parameters.geometry_y.value = y;
420 cropSetFrameByInput();
421 }
423 function showGeometry() {
424 var resolution = document.parameters.resolution.value;
425 if (resolution) {
426 resolution /= 25.4;
427 var x = Math.floor(document.parameters.geometry_x.value * resolution);
428 var y = Math.floor(document.parameters.geometry_y.value * resolution);
429 alert((Math.round(x * y / 100000)/10) + ' Mpixels\n' + x + 'x' + y);
430 }
431 }
432 -->
433 </script>
435 <footer align="center">
436 EOT
437 awk -vox=$org_x -voy=$org_y 'END {
438 x=210*4; y=297*4; n=0; cnt=0;
439 while (cnt < 9) {
440 if (ox +1 >= x && oy +1 >= y) {
441 print "&nbsp;<a href=\"javascript:setGeometry(" x "," y ")\">DIN-A" n "</a>"
442 cnt++
443 }
444 if (ox +1 >= x && oy +1 >= y) {
445 print "&nbsp;<a href=\"javascript:setGeometry(" y "," x ")\">DIN-A" n "L</a>"
446 cnt++
447 }
448 tmp=x; x=y/2; y=tmp
449 n++
450 }
451 }' < /dev/null
453 cat <<EOT
454 </footer>
455 </form>
456 </section>
457 EOT
459 [ -s "$tmpreview" ] && cat <<EOT
460 <div margin="15px" style="overflow-x: auto">
461 <script type="text/javascript" src="lib/crop.js"></script>
462 <img src="$tmpreview" style="width:100%" onload=cropInit(this,'x','y','width','height')>
463 </div>
464 EOT
465 xhtml_footer