All websites with weather information also show animations of the changes in the last few hours. This is a simple example on how to use TCL and create your own personal animations that could span longer periods and animate at different speeds. It could also be used to create time-lapse sequences from webcam images. I am using it on Windows so it probably needs some fixes for Unix/Linux. Before you can see any animation you need to let the program collect images for a few hours. # # sat_pics.tcl - download,show,save,animate weather images # # S.Mimmi 2007 # package require http #################### Configuration ###################### # Web Proxy data (remove comment, configure if needed) #http::config -proxyhost hostname -proxyport port_num # URLs of the images to use, the index will be the filename array set Url { IR-enh http://weather.unisys.com/satellite/sat_ir_enh_us.gif Sat-sfc http://weather.unisys.com/satellite/sat_sfc_map.gif Visible http://weather.unisys.com/satellite/sat_vis_us.gif Wat-vap http://weather.unisys.com/satellite/sat_wv_us.gif Sfc-dT24h http://weather.unisys.com/surface/sfc_con_24temp.gif Sat-rad http://weather.unisys.com/satellite/sat_ir_rad.gif US-curr http://image.weather.com/images/maps/current/curwx_600x405.jpg US-temp http://image.weather.com/images/maps/current/acttemp_600x405.jpg } # Initial image to load set Opt(cur_pic) US-curr # Init checkbutton to display on desktop background (1=display) set Opt(back) 0 # Minutes to wait before downloading new image set Opt(ref_rate) 20 # Milliseconds to wait before next image in slideshow set Opt(cyc_rate) 250 # How many pictures to cycle thru (all newer than cyc_hours) set Opt(cyc_hours) 60 # Number of days to store images set Opt(keep_days) 14 # Where to store images set Opt(img_path) "[pwd]/wea_img" # Start GUI set Opt(use_gui) 1 # Where is irfanView (if running on windows) set Opt(iview) "C:/Graphics/IrfanView/i_view32.exe" set Opt(screen_size) "(1280,1024)" # Where is xloadimage (if running on Unix) set Opt(xload) "/usr/bin/xloadimage" ###################### End configuration ############################# # Load user defaults (remove file after changing Opt() defaults above) if {$::tcl_platform(platform) == "windows"} { set ini_file "$env(HOME)/sat_pic.ini" } else { set ini_file "$env(HOME)/.sat_picrc" } catch {source $ini_file} if {$Opt(ref_rate) < 10} {set Opt(ref_rate) 10} if {[catch {set Url([set Opt(cur_pic)])}]} { set Opt(cur_pic) [lindex [array names Url] 0] } ####################### Procedures ################################### # Get image from web proc get_image { url } { for {set i 1} {$i < 4} {incr i} { set um [http::geturl $url -timeout [expr {1000 + $i * 3000}]] http::wait $um set ncode [http::ncode $um] if { $ncode == 200 } { break } else { http::cleanup $um } } if {$i == 4} { set htstat [http::status $um] wm title . "$htstat - code = $ncode" http::cleanup $um return {} } set pic [http::data $um] http::cleanup $um return $pic } # Get and save all images proc get_all_images { } { global Opt Url foreach img_id [array names Url] { set pic [get_image $Url($img_id)] if {$pic != {}} { save_img [get_file_name $img_id] $pic } } } # Filename used to store image proc get_file_name {img_id} { global Opt Url set ext [file extension $Url($img_id)] set secs [clock seconds] set mins [string index [clock format $secs -format "%M"] 0]0 return [clock format $secs -format "$Opt(img_path)/${img_id}_%Y%m%d_%H$mins$ext"] } # Get current image, display and save, # if repeat != 0 then start the timer for next download and get full set proc show_image { {repeat 0} } { global Opt Url set img_id $Opt(cur_pic) set url $Url($img_id) # Get the image set pic [get_image $url] # If picture found if { $pic != {} } { # Use our file identifiers since filenames from Web can change set filename [get_file_name $img_id] # Display in window if { $Opt(use_gui) } { wm title . [file tail $filename] catch {image delete wea_img} image create photo wea_img -data $pic wm sizefrom . program .l configure -image wea_img set Opt(cur_idx) 0 } # Save image: use our identifiers since filenames from Web can change set image_file [save_img $filename $pic] # After the image is saved check if need to change the background if {$Opt(back)} { load_background $image_file } } if { $repeat } { # get a new image after ref_rate min after [expr {$Opt(ref_rate) * 60000}] show_image 1 # get full set get_all_images } } proc show_img_file { f } { wm title . [file tail $f] set fd [open $f r] fconfigure $fd -translation binary -encoding binary set pic [read $fd] close $fd catch {image delete wea_img} image create photo wea_img -data $pic .l configure -image wea_img } # Cycle thru images previously downloaded proc cycle_img {} { global Opt set name $Opt(cur_pic) set files [lsort [glob -directory $Opt(img_path) ${name}*]] set cyctime [expr {[clock seconds] - $Opt(cyc_hours) * 3600}] # Show images from the last cyc_hours foreach f $files { if { [file mtime $f] > $cyctime } { show_img_file $f # wait before next image set state ok after $Opt(cyc_rate) set state tout vwait state } } set Opt(cur_idx) 0 } # View old images with the back/forward buttons proc prev_img { step } { global Opt set name $Opt(cur_pic) set files [lsort [glob -directory $Opt(img_path) ${name}*]] incr Opt(cur_idx) $step if {$Opt(cur_idx) >= [llength $files]} { set Opt(cur_idx) [expr {[llength $files] - 1}] } elseif {$Opt(cur_idx) < 0} { set Opt(cur_idx) 0 } show_img_file [lindex $files end-$Opt(cur_idx)] } # Save the image proc save_img { filename pic } { # skip if already present if {![file exists $filename]} { set fd [open $filename w] fconfigure $fd -translation binary -encoding binary puts $fd $pic close $fd set filename [dup_remove $filename] } return $filename } # Remove dup file (checking previous, return name of file kept) proc dup_remove { filename } { global Opt set file_glob [string range [file tail $filename] 0 end-9] set files [lsort [glob -directory $Opt(img_path) ${file_glob}* ]] set prev_file [lindex $files end-1] if {$prev_file == ""} { return $filename } set f_size [file size $prev_file] if {$f_size == [file size $filename]} { set fd [open $filename r] fconfigure $fd -translation binary -encoding binary set data1 [read $fd $f_size] close $fd set fd [open $prev_file r] fconfigure $fd -translation binary -encoding binary set data2 [read $fd $f_size] close $fd if {$data1 == $data2} { file delete $filename return $prev_file } } return $filename } # Use helper to show image on desktop wallpaper proc load_background { filename } { global Opt if {$::tcl_platform(platform) == "windows"} { exec -- $Opt(iview) [file nativename $filename] /resize=$Opt(screen_size) /resample /aspectratio /sharpen=15 /wall=0 /killmesoftly & } elseif {$::tcl_platform(platform) == "unix"} { exec -- $Opt(xload) [file nativename $filename] -onroot -colors 32 & } } # Remove files older than Opt(keep_days) proc cleanup_old_files { } { global Opt # 60 * 60 * 24 = 86400 s/day set oldtime [expr {[clock seconds] - $Opt(keep_days) * 86400}] # scan all files and remove files modified more than keep_days ago set files [glob -directory $Opt(img_path) *] foreach f $files { if { [file mtime $f] < $oldtime } { file delete $f } } # tomorrow again after 86400000 cleanup_old_files } # Save configuration on exit proc write_ini { filename } { global Opt set fd [open $filename w] foreach item [lsort [array names Opt]] { puts $fd "set Opt($item) \t\"$Opt($item)\"" } close $fd } ####################################################### # GUI ####################################################### if { $Opt(use_gui) } { package require Tk package require Img image create bitmap play_bm -data " #define play_width 12 #define play_height 13 static char play_bits = { 0x00,0x00,0x08,0x00,0x18,0x00,0x38,0x00,0x78,0x00,0xf8,0x00,0xf8, 0x01,0xf8,0x00,0x78,0x00,0x38,0x00,0x18,0x00,0x08,0x00,0x00,0x00 }" frame .b pack .b -side top -padx 2 -fill x image create photo wea_img -width 900 -height 650 label .l -image wea_img pack .l -side bottom -fill both foreach i [lsort [array names Url]] { set wn [string tolower $i] button .b.$wn -text $i -command "set Opt(cur_pic) $i; show_image" pack .b.$wn -side left } # Wallpaper checkbutton .b.b -text Wall. -variable Opt(back) pack .b.b -side right # History and Animation frame .b.an pack .b.an -side right -padx 2 button .b.an.bk -text < -command {prev_img 1} button .b.an.fw -text > -command {prev_img -1} label .b.an.l -text "Hrs" entry .b.an.cyce -width 3 -textvariable Opt(cyc_hours) button .b.an.go -image play_bm -command cycle_img scale .b.an.sc -orient horizontal -width 10 -length 110 -showvalue 0 \ -from 4 -to 1000 -variable Opt(cyc_rate) -tickinterval 0 entry .b.an.cycr -width 4 -textvariable Opt(cyc_rate) pack .b.an.bk .b.an.fw -side left pack .b.an.l .b.an.cyce .b.an.go .b.an.sc .b.an.cycr -side left wm protocol . WM_DELETE_WINDOW {write_ini $ini_file; exit} wm resizable . 0 0 } # Check if the image dir exists if {![file isdirectory $Opt(img_path)]} { file mkdir $Opt(img_path) } # Start periodic downloads and show image if enabled http::config -useragent "MSIE 5.0" show_image 1 # Check if old files need to be removed after 5000 cleanup_old_files [Category Application] | [Category Science] | [Category Animation]