#!/usr/bin/tclsh set imagetype miff set graytype pgm set colortype ppm set xsize 1920 set ysize 1440 set maxdiv 8 set stepsize 1.6 # Various options set spin [expr {int(rand()*2)}] set stack [expr {int(rand()*2)}] set flip_channels [expr {int(rand() * 2)}] # Image acquisition method: default TV source, channels 2..72 set method fetch_tv set meth_args {2 72} # Acquire image from URL, e.g. a webcam proc fetch_web {geomx geomy sources} { global imagetype global colortype set source [expr {int(rand()*[llength $sources])}] set site [lindex $sources $source] # If we get an animated GIF, average the images. puts "wget -O- [list $site] | convert -verbose -average - in.$imagetype" puts "mogrify -verbose -matte -geometry ${geomx}x${geomy} -normalize in.$imagetype" } # Acquire image from current X session proc fetch_desk {geomx geomy} { global maxdiv global xsize global ysize global imagetype set mydiv [expr {rand() * $maxdiv + 1}] set inx [expr {int($xsize/$mydiv)}] set iny [expr {int($ysize/$mydiv)}] set startx [expr {int(rand() * ($xsize - $inx))}] set starty [expr {int(rand() * ($ysize - $iny))}] puts "rm -f in.xwd" puts "xwd -silent -root -icmap > in.xwd || convert -verbose x:root in.xwd || exit 1" puts "convert -verbose -crop ${inx}x${iny}+${startx}+${starty} -geometry ${geomx}x${geomy} -normalize in.xwd in.$imagetype" } # Acquire image from TV tuner with optional channel-changing proc fetch_tv {geomx geomy channel_low channel_high} { global flip_channels global colortype global imagetype if {$flip_channels} { puts "v4lctl setchannel [expr {int(rand() * ($channel_high - $channel_low + 1) + $channel_low)}] >&2" } puts "rm -f capture.$colortype" puts "streamer -n ntsc -f $colortype -s 640x480 -r 1 -t 1 -o capture.$colortype >&2" puts "convert -verbose -matte -geometry ${geomx}x${geomy} -normalize capture.$colortype in.$imagetype >&2" } # Process command-line arguments foreach {xsize ysize maxdiv stepsize method meth_args} $argv break # Effects on matte layer and final image proc mogrify_effect {kind file} { global maxdiv global xsize # Random effect just before conversion set radius [expr rand()*3+1] set radius [expr {$radius*$radius}] set stddev [expr rand()*8 ] set gamma [expr rand()*4.9+.1 ] set spercent [expr rand()*200-100 ] set percent2 [expr rand()*200 ] set percent3 [expr rand()*200 ],[expr rand()*200 ],[expr rand()*200 ] set percent [expr rand()*100 ] set angle [expr rand()*360 ] set sangle [expr rand()*360-180 ] set wavelen [expr {$xsize/int(rand()*$maxdiv+1)}] set amplitude [expr {int(rand()*$wavelen/1.6)} ] set noisetype [lindex {Uniform Gaussian Multiplicative Impulse Laplacian Poisson} [expr int(rand()*6)]] set smalltheta [expr int(rand()*30-15) ] set colors [expr {int(rand()*254)+2}] set effects {} # lappend effects "+contrast" # lappend effects "-contrast" # lappend effects "-despeckle" # lappend effects "-enhance" # lappend effects "-noise ${radius}" # lappend effects "-sharpen ${radius}x${stddev}" lappend effects "+noise ${noisetype}" lappend effects "-blur ${radius}x${stddev}" lappend effects "-implode ${percent}" lappend effects "-paint ${radius}" lappend effects "-shade ${angle}x${angle}" lappend effects "-spread ${radius}" lappend effects "-swirl ${sangle}" # Some effects are suitable for the plasma matte layers # others are suitable for the final image if {![string compare $kind final]} { # Effects for the final image # All plasmas and masks are pre-equalized lappend effects "-equalize" # Slightly misaligned look lappend effects "-rotate ${smalltheta}" # Total conversion to grayscale lappend effects "-colors $colors -colorspace gray" } else { # Effects for non-final-images lappend effects "-implode -${percent}" } if {![string compare $kind mask]} { # Effects for rotation masks } else { # Effects for non-rotation-masks lappend effects "-colors $colors" # Rotation masks are already monochrome with single edge lappend effects "-charcoal ${radius}" lappend effects "-edge ${radius}" lappend effects "-emboss ${radius}x${stddev}" lappend effects "-gamma ${gamma}" lappend effects "-modulate ${percent3}" lappend effects "-monochrome" # Can't invert mask data lappend effects "-negate" lappend effects "-solarize ${percent}" } if {![string compare $kind plasma]} { # Effects for plasmas lappend effects "-cycle $colors" lappend effects "-threshold ${percent}" } else { # Effects for non-plasmas lappend effects "-wave ${amplitude}x${wavelen}" } set effect [lindex $effects [expr {int(rand()*[llength $effects])}]] puts "mogrify -verbose $effect $file" } # Get one image proc get_image {geomx geomy placex placey} { global imagetype global graytype global colortype global xsize global ysize global spin global maxdiv global method global meth_args set plasmasize 1 while {($plasmasize < 2*$geomx || $plasmasize < 2*$geomy) && ($plasmasize < $xsize && $plasmasize < $ysize)} { incr plasmasize $plasmasize } puts "rm -f in.$imagetype" # Acquire image eval [list $method $geomx $geomy] $meth_args # Don't do the rest in the shell if the image capture failed puts "if \[ -s in.$imagetype \]; then" if {$spin} { set rotation [expr {int(rand() * 360)}] } else { set rotation [expr {int(rand() * 4) * 90}] } puts "rm -f new.$imagetype plasma.$graytype mask.$graytype compositemask.$graytype" # Rotate scaled image puts "mogrify -verbose -matte -rotate $rotation in.$imagetype" # Extract matte layer after rotate puts "convert -verbose -layer matte in.$imagetype mask.$graytype" # Matte effects for mask mogrify_effect mask mask.$graytype # Create plasma at least that big puts "convert -verbose -sample ${plasmasize}x${plasmasize}! -equalize plasma:fractal plasma.$graytype" # Matte effects for plasma mogrify_effect plasma plasma.$graytype # Add plasma # ImageMagick bug workaround: this should be 'minus', but is 'plus' because of a bug. puts "combine -verbose -compose minus plasma.$graytype mask.$graytype compositemask.$graytype" # Join images in the usual way puts "combine -verbose -compose over -geometry +${placex}+${placey} out.$imagetype in.$imagetype compositemask.$graytype new.$imagetype" # Done. puts "mv -f new.$imagetype out.$imagetype" # Debug # puts "display out.$imagetype" # Don't do the above in the shell if the image capture failed puts "fi" } # Set up shell puts { ulimit -t 600 ulimit -f 80000 ulimit -m 160000 ulimit -v 160000 ulimit -s 160000 ulimit -d 160000 } puts "echo -n 2224222422242224 | tr '01234' '\\0\\100\\200\\300\\377' | convert -verbose -size 2x2 -geometry ${xsize}x${ysize}! rgba:- out.$imagetype" set div 1 set commands {} # Divide output image area and assign get_image calls for {set step 1} {$div<=$maxdiv} {set div [expr {$div * $stepsize}]} { set ystep [expr int($ysize/$div)] for {set y 0} {$y+$ystep<=$ysize} {incr y $ystep} { set xstep [expr int($xsize/$div)] for {set x 0} {$x+$xstep<=$xsize} {incr x $xstep} { lappend commands [list get_image $xstep $ystep $x $y] } } } # Order get_image calls while {[llength $commands]} { if {$stack} { set index 0 } else { set index [expr {int(rand() * [llength $commands])}] } eval [lindex $commands $index] set commands [lreplace $commands $index $index] } # Cherry on top mogrify_effect final out.$imagetype # Convert final image puts "convert -verbose -quality 90 -crop [expr {int($xsize/2)}]x[expr {int($ysize/2)}]+[expr {int($xsize/4)}]+[expr {int($ysize/4)}] out.$imagetype out.jpg" # Clean up puts "rm -f in.$imagetype in.$colortype out.$imagetype new.$imagetype plasma.$graytype mask.$graytype" puts "rm -f compositemask.$graytype black.$imagetype capture.$colortype"