3 # vidwhacker, for xscreensaver. Copyright (c) 1998 Jamie Zawinski.
5 # This script grabs a frame of video, then uses various pbm filters to
6 # munge the image in random nefarious ways, then uses xv to put it on
7 # the root window. This works out really nicely if you just feed some
8 # random TV station into it...
10 # The video grabbing part is SGI-specific -- if you want to use this on
11 # another system, add a new clause to the grab() procedure.
14 # Process command-line args...
23 tmp_rgb=$tmp-00000.rgb
45 echo "usage: $0 [ -root | -verbose | -stdin ]" >&2
54 if [ "$onroot" = true ]; then
55 xvargs="$xvargs -root -rmode 5 -noresetroot -rfg black -rbg black -viewonly"
57 xvargs="$xvargs -geom +0+0"
60 screen_width=`xdpyinfo | sed -n 's/.* dimensions: *\([0-9]*\).*/\1/p'`
65 rm -f $tmp_rgb $tmp_ppm1 $tmp_ppm2 $tmp_ppm3 $tmp_ppm4
74 # Grab a frame of video.
78 if [ $uname = IRIX ]; then
80 # SGI's "vidtomem" returns an SGI RGB image of the default video input,
81 # and has stupid non-overridable ouput-file-naming conventions. So, let
82 # it write its file; and then convert it to a pgm.
86 sgitopnm $tmp_rgb > $tmp_ppm1
88 # Cut off the close-captioning blips in the NTSC overscan region. YMMV.
89 # | pnmcut 12 7 695 477
91 elif [ $uname = Linux ]; then
93 # Marcus Herbert says the following works with his Connectix Qcam.
94 # Don't have qcam? Well, do something else then... and send me a patch.
99 echo "$0: don't know how to grab video on this OS." >&2
106 # Use perl to pick a random foreground/background color in pbm's syntax.
110 printf("#%02x%02x%02x-#%02x%02x%02x",
116 120+int(rand()*135))'
119 # Frobnicate the image in some random way.
123 w_h=`head -2 $tmp_ppm1 | tail -1`
124 width=`echo $w_h | awk '{print $1}'`
125 height=`echo $w_h | awk '{print $2}'`
127 N=`perl -e 'srand; print int(rand() * 17)'`
129 if [ "$verbose" = true ]; then
130 echo "mode $N..." >&2
134 ppmtopgm $tmp_ppm1 | pgmedge | pgmtoppm `randcolor` | ppmnorm
136 elif [ $N = 1 ]; then
141 elif [ $N = 2 ]; then
142 ppmtopgm $tmp_ppm1 | pgmoil | pgmtoppm `randcolor`
144 elif [ $N = 3 ]; then
145 ppmrelief $tmp_ppm1 | ppmtopgm | pgmedge | ppmrelief | ppmtopgm |
146 pgmedge | pnminvert | pgmtoppm `randcolor`
148 elif [ $N = 4 ]; then
149 ppmspread 71 $tmp_ppm1 > $tmp_ppm2
150 pnmarith -add $tmp_ppm1 $tmp_ppm2
152 elif [ $N = 5 ]; then
153 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
154 pnmarith -multiply $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3
155 pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2
156 pnmarith -multiply $tmp_ppm1 $tmp_ppm2
158 elif [ $N = 6 ]; then
159 N2=`perl -e 'srand; print int(rand() * 3)'`
161 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
162 elif [ $N2 = 1 ]; then
163 pnmflip -tb $tmp_ppm1 > $tmp_ppm2
165 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
166 pnmflip -tb $tmp_ppm2 > $tmp_ppm3
167 cp $tmp_ppm3 $tmp_ppm2
170 pnmarith -difference $tmp_ppm1 $tmp_ppm2
172 elif [ $N = 7 ]; then
175 ppmtopgm $tmp_ppm1 | pgmedge > $tmp_ppm2
176 pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3
177 cp $tmp_ppm3 $tmp_ppm1
181 elif [ $N = 8 ]; then
182 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
183 pnmarith -multiply $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmnorm | pnminvert
185 elif [ $N = 9 ]; then
186 pnmflip -lr $tmp_ppm1 > $tmp_ppm2
187 pnmarith -subtract $tmp_ppm1 $tmp_ppm2 | ppmrelief | ppmtopgm | pgmedge
189 elif [ $N = 10 ]; then
190 ppmtopgm $tmp_ppm1 | pgmbentley | pgmtoppm `randcolor`
192 elif [ $N = 11 ]; then
193 pgmcrater -number 20000 -height $height -width $width | pgmtoppm `randcolor` > $tmp_ppm2
194 pnmarith -difference $tmp_ppm1 $tmp_ppm2 > $tmp_ppm3
195 pnmflip -tb $tmp_ppm3 | ppmnorm > $tmp_ppm2
196 pnmarith -multiply $tmp_ppm1 $tmp_ppm2
198 elif [ $N = 12 ]; then
199 ppmshift 30 $tmp_ppm1 | ppmtopgm | pgmoil | pgmedge | pgmtoppm `randcolor` > $tmp_ppm2
200 pnmarith -difference $tmp_ppm1 $tmp_ppm2
202 elif [ $N = 13 ]; then
203 ppmpat -madras $width $height | pnmdepth 255 > $tmp_ppm2
204 pnmarith -difference $tmp_ppm1 $tmp_ppm2
206 elif [ $N = 14 ]; then
207 ppmpat -tartan $width $height | pnmdepth 255 > $tmp_ppm2
208 pnmarith -difference $tmp_ppm1 $tmp_ppm2
210 elif [ $N = 15 ]; then
211 ppmpat -camo $width $height | pnmdepth 255 | ppmshift 50 > $tmp_ppm2
212 pnmarith -multiply $tmp_ppm1 $tmp_ppm2
214 elif [ $N = 16 ]; then
215 pgmnoise $width $height | pgmedge | pgmtoppm `randcolor` > $tmp_ppm2
216 pnmarith -difference $tmp_ppm1 $tmp_ppm2 | pnmdepth 255 | pnmsmooth
223 # Grab a frame and frob it. leave it in $tmp_ppm3.
228 while [ ! -f $tmp_ppm1 ]; do
229 if [ "$use_stdin" != true ]; then
232 cp $tmp_ppm0 $tmp_ppm1
237 frob | pnmscale -width $screen_width > $tmp_ppm3
238 rm -f $tmp_ppm1 $tmp_ppm2
242 # Kill off the xv subprocess, if it's running
245 if [ "$pid" != "" ]; then
247 if [ "$verbose" = true ]; then
248 echo "killing pid $pid..." >&2
251 # need to do this to avoid "6898 Terminated" messages!
252 # apparently one can't redirect the output of the builtin `kill' command.
253 # ( sh -c "kill $pid" ) >/dev/null 2>/dev/null </dev/null
255 # wtf? that doesn't work either. Is it writing to /dev/tty??
262 # called when this process is signalled (for cleanup)
265 if [ "$verbose" = true ]; then
266 echo "trapped signal!" >&2
277 trap my_trap 0 1 2 3 6 9 13
279 if [ "$use_stdin" = true ]; then
285 # Loop grabbing and frobbing images.
287 # If we're running on the root, run xv in the foreground (with -exit)
290 # If we're running in a window, spawn xv in the background; then when
291 # it's time to put up the new image, kill off the currently-running xv.
293 if [ "$verbose" = true ]; then
301 if [ ! -s $tmp_ppm3 ]; then
302 echo "$0: no image grabbed" >&2
305 pnmtosgi < $tmp_ppm3 > $tmp_ppm2
308 if [ -s $tmp_ppm2 ]; then
309 if [ "$verbose" = true ]; then
310 echo "launching xv $xvargs $tmp_ppm2" >&2
314 # cat the file so that we can nuke it without racing against xv.
315 cat $tmp_ppm2 | xv $xvargs - &
329 # to find stray xv data:
330 # xwininfo -root -children|grep 'xv image comments' | awk '{print "xkill -id ", $1}'