zoomer-0.1/0000755000175000017500000000000011050352360012246 5ustar auriumauriumzoomer-0.1/zoomer0000755000175000017500000002350711050352360013516 0ustar auriumaurium#!/bin/bash # Zoomer - Generate a video from a picture zooming each selected detail # Copyright (C) 2008 Aurélio A. Heckert # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # Version 0.1 # Collect all args and create local variables: for arg in "$@"; do if ( echo -n $arg | grep -q '^--.*=' ); then key="$( echo -n "$arg" | sed 's/^--\([^=]*\)=.*$/\1/; s/[^a-zA-Z0-9]/_/' )" val="$( echo -n "$arg" | sed 's/^--\([^=]*\)=\(.*\)$/\2/' )" eval "$key=\"$val\"" fi if ( echo -n $arg | grep -q '^--[^=]\+$' ); then key="$( echo -n "$arg" | sed 's/^--\(.*\)$/\1/; s/[^a-zA-Z0-9]/_/' )" eval "$key=true" fi done [ "$debug" != "true" ] && debug="false" [ "$use_zenity" != "true" ] && use_zenity="false" if ( $debug && $use_zenity ); then echo "Can't use Zenity when debuging" >&2 use_zenity="false" fi function show_loading() { if $use_zenity; then zenity --progress --width=400 --title=Zoomer --text="Generating Frames..." --auto-close else cat fi } term_w=$COLUMNS test "$term_w" = "" && term_w=80 $debug && echo "Term columns: $term_w" if ! test -e "$pic"; then echo "Picture missed" >&2 exit 1 fi eval "$( identify -format 'pic_w=%w\npic_h=%h' "$pic" )" if ! test -e "$data_file"; then data_file="$data" fi if ! test -e "$data_file"; then echo "Data file missed" >&2 exit 1 fi [ "$video_size" = "" ] && video_size=400x300 video_w=$( echo $video_size | sed 's/^\([0-9]*\)x.*$/\1/' ) video_h=$( echo $video_size | sed 's/^.*x\([0-9]*\)$/\1/' ) if [ "$video_w" = "" -o "$video_h" = "" ]; then echo "Video size missed" >&2 exit 1 fi if [ "$output" = "" ]; then output="$output_video" fi if [ "$replace_output" = "" ]; then replace_output="$replace_output_video" fi if [ "$output" = "" ]; then echo "Output video file missed" >&2 exit 1 fi if test -e "$output" -a "$replace_output" != "true"; then echo -n "Replace \"$output\"? [y,n] " read -sn 1 resp resp=$( echo "$resp" | tr y Y ) test "$resp" != "Y" && resp=N echo $resp if [ $resp = N ]; then echo "So, please, restart with a new name." exit 0 fi fi function calc() { echo "$@" | bc -l | sed 's/^\(-\?\)\./\10./; s/^$/0/' } function round() { calc "$@" | sed 's/\..*$//' } function test_calc() { r=$( calc "$1" ) if [ "$r" = "$2" ]; then err=Ok else err=Error fi echo "$1 = $2 ($err) => $( round "$@" )" } #test_calc '0 + 0' #test_calc '0 + 1' #test_calc '3 / 98700000' #test_calc '0.102030' #test_calc '80 * 2' #test_calc '80.8 * 2' #test_calc '-123' #test_calc '-.123' #test_calc '-.0123' '-0.0123' #test_calc '010 + 1' 11 #test_calc '0010 + 1' 11 function beault_num() { sed 's/\.\(.*[^0]\)\?0*$/.\1/; s/\.$//' } # Video Size Delta: vsd=$( calc "$video_h / $video_w" | beault_num ) [ "$zoom_out_pct" = "" ] && zoom_out_pct=50 zoom_out_pct=$( calc "$zoom_out_pct / 100" ) # Zoom Out Size: if [ "$zow" = "" -o "$zoh" = "" ]; then zoh=$( round "$pic_h * $zoom_out_pct" ) zow=$( round "$zoh / $vsd" ) if [ $zow -gt $( round "$pic_w * $zoom_out_pct" ) ]; then zow=$( round "$pic_w * $zoom_out_pct" ) zoh=$( round "$zow * $vsd" ) fi fi [ "$frames_stoped" = "" ] && frames_stoped=20 [ "$frames_moveing" = "" ] && frames_moveing=10 [ "$font_size" = "" ] && font_size=20 tot_details=$( wc -l $data_file | sed 's/^\([0-9]*\) .*$/\1/' ) tot_frames=$(( ($tot_details+1)*($frames_moveing+1) + $tot_details*($frames_stoped-1) )) $debug && echo "Video configuration: Picture: $pic Pic Size: w:$pic_w h:$pic_h Data file: $data_file Zoom Out Size: w:$zow h:$zoh Frames in Detail: $frames_stoped Frames Moving: $frames_moveing Tot Details: $tot_details Tot Frames: $tot_frames Font Size : $font_size Output video: $output Output Size: w:${video_w} h:${video_h} delta:$vsd " work_dir=$( mktemp -d ) thunar $work_dir & cat "$data_file" | ( # start frame generator loop f=0 old_x=$( round "$pic_w / 2" ) old_y=$( round "$pic_h / 2" ) oldz_h=$pic_h oldz_w=$( round "$oldz_h / $vsd" ) if [ $oldz_w -gt $pic_w ]; then oldz_w=$pic_w oldz_h=$( round "$oldz_w * $vsd" ) fi # Variables: # Generated with Linear function: # step : Frame Step (Natural Numbers) # sm_# : Step Moving in Frame Step (0..1 scale) # Generated with Sigmoid function: # szo_# : Step Old Zoom in Frame Step (0..1 scale) # szn_# : Step New Zoom in Frame Step (0..1 scale) eval "$( perl -e " \$e=2.7182818284; for ( \$step=0; \$step<=$frames_moveing; \$step++ ) { \$sm = \$step / $frames_moveing; \$szo = \$e**(-(\$sm-0.25)*20) / ( 1 + ( \$e**(-(\$sm-0.25)*20) ) ); \$szo = 1 if \$sm == 0; \$szo = 0 if \$sm >= 0.5; \$szn = \$e**((\$sm-0.75)*20) / ( 1 + ( \$e**((\$sm-0.75)*20) ) ); \$szn = 1 if \$sm == 1; \$szn = 0 if \$sm <= 0.5; print \"sm_\$step=\$sm \t; szo_\$step=\$szo \t; szn_\$step=\$szn\n\" } " )" function show_pct() { pct=$( calc "( $frame * 100 ) / $tot_frames" ) if [ "$loading_type" = "pct" ]; then echo $( round $pct ) else for i in $(seq $term_w ); do echo -n ' '; done echo -ne "\r Zooming \"$name\" - frame $frame of $tot_frames" echo -ne " - $( echo $pct | sed 's/\(.....\).*/\1/' )%\r" fi } function move_camera() { mid_step=$( round "$frames_moveing / 2" ) for step in $( seq 0 $frames_moveing ); do let frame++ eval "sm=\$sm_$step ; szo=\$szo_$step ; szn=\$szn_$step" if [ $step -le $mid_step ]; then zw=$( calc "( $oldz_w * $szo ) + ( $zow * (1-$szo) )" ) zh=$( calc "( $oldz_h * $szo ) + ( $zoh * (1-$szo) )" ) else zw=$( calc "( $zow * (1-$szn) ) + ( $zoom_w * $szn )" ) zh=$( calc "( $zoh * (1-$szn) ) + ( $zoom_h * $szn )" ) fi x=$( calc "( $old_x * (1-$sm) ) + ( $goto_x * $sm )" | beault_num ) y=$( calc "( $old_y * (1-$sm) ) + ( $goto_y * $sm )" | beault_num ) x1=$( round "$x - ( $zw / 2 )" ) x2=$( round "$x + ( $zw / 2 )" ) y1=$( round "$y - ( $zh / 2 )" ) y2=$( round "$y + ( $zh / 2 )" ) $debug && echo -e " frame:$frame \tstep:$step \tsm:$sm \tx:$x \ty:$y" $debug && echo -e " szo:$szo \tszn:$szn \tzw=$zw \tzh=$zh" if [ $x1 -lt 0 ]; then x2=$(( $x2 - $x1 )) x1=0 fi if [ $x2 -gt $pic_w ]; then x1=$(( $x1 - ( $x2 - $pic_w ) )) x2=$pic_w fi if [ $y1 -lt 0 ]; then y2=$(( $y2 - $y1 )) y1=0 fi if [ $y2 -gt $pic_h ]; then y1=$(( $y1 - ( $y2 - $pic_h ) )) y2=$pic_h fi $debug && echo -e " x1=$x1 \t x2=$x2 \t y1=$y1 \t y2=$y2" convert "$pic" \ -crop $( round $zw )x$( round $zh )+$( round $x1 )+$( round $y1 ) \ +repage -resize "${video_w}x${video_h}!" $work_dir/frame.png if [ $(round "$sm*100") -lt 50 ]; then alfa=$( round "100 - ( $sm * 200 )" ) if [ "$old_name_png" != "" ]; then composite -dissolve ${alfa}x100 -gravity South \ "$old_name_png" $work_dir/frame.png \ -quality 100 $work_dir/f_$frame.jpg else convert $work_dir/frame.png -quality 100 $work_dir/f_$frame.jpg fi else alfa=$( round "( $sm * 200 ) - 100" ) if [ "$name_png" != "" ]; then composite -dissolve ${alfa}x100 -gravity South \ "$name_png" $work_dir/frame.png \ -quality 100 $work_dir/f_$frame.jpg else convert $work_dir/frame.png -quality 100 $work_dir/f_$frame.jpg fi fi rm $work_dir/frame.png $debug || show_pct done } svg=$work_dir/nome.svg function generate_name_file() { f="font-family:sans-serif; font-size:${font_size}px; font-weight:bold" s="stroke:#000; stroke-width:$( calc "$font_size / 10" )px" s="$s;stroke-linejoin:round; stroke-linecap:round" echo " $name $name $name " > $svg inkscape --export-png="$1" --export-area-drawing --without-gui $svg >/dev/null } frame=0 while read line; do eval "$( echo "$line" | sed "s/'/\´/g; s/^\([^\s]*\),\([^\s]*\) \([^\s]*\) \(.*\)$/goto_x='\1'\ngoto_y='\2'\nzoom_w='\3'\nname='\4'/" )" #' zoom_h=$( round "$zoom_w * $vsd" ) $debug && echo "Zooming $name (${old_x},${old_y}:${oldz_w}x${oldz_h} -> ${goto_x},${goto_y}:${zoom_w}x${zoom_h})" if [ "$name" = "-" ]; then name_png="" else name_png="$work_dir/name_$name.png" generate_name_file "$name_png" fi move_camera last_frame=$frame for step in $( seq 2 $frames_stoped ); do let frame++ # copy the frame cp $work_dir/f_$last_frame.jpg $work_dir/f_$frame.jpg $debug || show_pct done $debug && echo "" old_x=$goto_x old_y=$goto_y oldz_w=$zoom_w oldz_h=$zoom_h old_name_png="$name_png" done goto_x=$( round "$pic_w / 2" ) goto_y=$( round "$pic_h / 2" ) zoom_h=$pic_h zoom_w=$( round "$zoom_h / $vsd" ) if [ $zoom_w -gt $zoom_w ]; then zoom_w=$pic_w zoom_h=$( round "$zoom_w * $vsd" ) fi name="The End" name_png="" $debug && echo "Zooming The End (${old_x},${old_y}:${oldz_w}x${oldz_h} -> ${goto_x},${goto_y}:${zoom_w}x${zoom_h})" move_camera ) | show_loading # end frame generator loop if $debug; then echo "Generating the movie..." else echo "" fi rm "$output" >&2 if ffmpeg -i "$work_dir/f_%d.jpg" "$output"; then $debug && echo " Done: $output" #rm -r $work_dir else echo "Ups..." >&2 fi