3 # generate-zooming-video - make a video from a big picture zooming datails
4 # Copyright (C) 2008 Aurélio A. Heckert
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
18 # Collect all args and create local variables:
20 if ( echo -n $arg | grep -q '^--.*=' ); then
21 key="$( echo -n "$arg" |
22 sed 's/^--\([^=]*\)=.*$/\1/; s/[^a-zA-Z0-9]/_/' )"
23 val="$( echo -n "$arg" |
24 sed 's/^--\([^=]*\)=\(.*\)$/\2/' )"
27 if ( echo -n $arg | grep -q '^--[^=]\+$' ); then
28 key="$( echo -n "$arg" |
29 sed 's/^--\(.*\)$/\1/; s/[^a-zA-Z0-9]/_/' )"
34 if ! test -e "$pic"; then
35 echo "Picture missed" >&2
39 eval "$( identify -format 'pic_w=%w\npic_h=%h' "$pic" )"
41 if ! test -e "$data_file"; then
42 echo "Data file missed" >&2
46 [ "$video_size" = "" ] && video_size=400x300
47 video_w=$( echo $video_size | sed 's/^\([0-9]*\)x.*$/\1/' )
48 video_h=$( echo $video_size | sed 's/^.*x\([0-9]*\)$/\1/' )
49 if [ "$video_w" = "" -o "$video_h" = "" ]; then
50 echo "Video size missed" >&2
54 output="$output_video"
55 replace_output="$replace_output_video"
56 if [ "$output" = "" ]; then
57 echo "Output video file missed" >&2
61 if test -e "$output" -a "$replace_output" != "true"; then
62 echo -n "Replace \"$output\"? [y,n] "
64 resp=$( echo "$resp" | tr y Y )
65 test "$resp" != "Y" && resp=N
67 if [ $resp = N ]; then
68 echo "So, please, restart with a new name."
74 echo "$@" | bc -l | sed 's/^\(-\?\)\./\10./; s/^$/0/'
78 calc "$@" | sed 's/\..*$//'
81 function test_calc() {
83 if [ "$r" = "$2" ]; then
88 echo "$1 = $2 ($err) => $( round "$@" )"
92 #test_calc '3 / 98700000'
98 #test_calc '-.0123' '-0.0123'
99 #test_calc '010 + 1' 11
100 #test_calc '0010 + 1' 11
102 function beault_num() {
103 sed 's/\.\(.*[^0]\)\?0*$/.\1/; s/\.$//'
107 vsd=$( calc "$video_h / $video_w" | beault_num )
109 [ "$zoom_out_pct" = "" ] && zoom_out_pct=50
110 zoom_out_pct=$( calc "$zoom_out_pct / 100" )
113 if [ "$zow" = "" -o "$zoh" = "" ]; then
114 zoh=$( round "$pic_h * $zoom_out_pct" )
115 zow=$( round "$zoh / $vsd" )
116 if [ $zow -gt $( round "$pic_w * $zoom_out_pct" ) ]; then
117 zow=$( round "$pic_w * $zoom_out_pct" )
118 zoh=$( round "$zow * $vsd" )
122 [ "$frames_stoped" = "" ] && frames_stoped=20
123 [ "$frames_moveing" = "" ] && frames_moveing=10
125 echo "Video configuration:
127 Pic Size: w:$pic_w h:$pic_h
128 Zoom Out Size: w:$zow h:$zoh
129 Frames in Detail: $frames_stoped
130 Frames Moving: $frames_moveing
131 Data file: $data_file
132 Output video: $output
133 Output Size: w:${video_w} h:${video_h} delta:$vsd
136 work_dir=$( mktemp -d )
138 cat "$data_file" | ( # start frame generator loop
141 old_x=$( round "$pic_w / 2" )
142 old_y=$( round "$pic_h / 2" )
145 oldz_w=$( round "$oldz_h / $vsd" )
146 if [ $oldz_w -gt $pic_w ]; then
148 oldz_h=$( round "$oldz_w * $vsd" )
152 # Generated with Linear function:
153 # step : Frame Step (Natural Numbers)
154 # sm_# : Step Moving in Frame Step (0..1 scale)
155 # Generated with Sigmoid function:
156 # szo_# : Step Old Zoom in Frame Step (0..1 scale)
157 # szn_# : Step New Zoom in Frame Step (0..1 scale)
161 for ( \$step=0; \$step<=$frames_moveing; \$step++ ) {
162 \$sm = \$step / $frames_moveing;
163 \$szo = \$e**(-(\$sm-0.25)*20) / ( 1 + ( \$e**(-(\$sm-0.25)*20) ) );
164 \$szo = 1 if \$sm == 0;
165 \$szo = 0 if \$sm >= 0.5;
166 \$szn = \$e**((\$sm-0.75)*20) / ( 1 + ( \$e**((\$sm-0.75)*20) ) );
167 \$szn = 1 if \$sm == 1;
168 \$szn = 0 if \$sm <= 0.5;
169 print \"sm_\$step=\$sm \t; szo_\$step=\$szo \t; szn_\$step=\$szn\n\"
175 function move_camera() {
176 mid_step=$( round "$frames_moveing / 2" )
177 for step in $( seq 0 $frames_moveing ); do
179 eval "sm=\$sm_$step ; szo=\$szo_$step ; szn=\$szn_$step"
180 if [ $step -le $mid_step ]; then
181 zw=$( calc "( $oldz_w * $szo ) + ( $zow * (1-$szo) )" )
182 zh=$( calc "( $oldz_h * $szo ) + ( $zoh * (1-$szo) )" )
184 zw=$( calc "( $zow * (1-$szn) ) + ( $zoom_w * $szn )" )
185 zh=$( calc "( $zoh * (1-$szn) ) + ( $zoom_h * $szn )" )
187 x=$( calc "( $old_x * (1-$sm) ) + ( $goto_x * $sm )" | beault_num )
188 y=$( calc "( $old_y * (1-$sm) ) + ( $goto_y * $sm )" | beault_num )
189 x1=$( round "$x - ( $zw / 2 )" )
190 x2=$( round "$x + ( $zw / 2 )" )
191 y1=$( round "$y - ( $zh / 2 )" )
192 y2=$( round "$y + ( $zh / 2 )" )
193 echo -e " frame:$frame \tstep:$step \tsm:$sm \tx:$x \ty:$y"
194 #echo -e " szo:$szo \tszn:$szn \tzw=$zw \tzh=$zh"
195 echo -e " x1=$x1 \t x2=$x2 \t y1=$y1 \t y2=$y2"
196 if [ $x1 -lt 0 ]; then
200 if [ $x2 -gt $pic_w ]; then
201 x1=$(( $x1 - ( $x2 - $pic_w ) ))
204 if [ $y1 -lt 0 ]; then
208 if [ $y2 -gt $pic_h ]; then
209 y1=$(( $y1 - ( $y2 - $pic_h ) ))
212 echo -e " x1=$x1 \t x2=$x2 \t y1=$y1 \t y2=$y2"
214 -crop $( round $zw )x$( round $zh )+$( round $x1 )+$( round $y1 ) \
215 +repage -resize "${video_w}x${video_h}!" \
216 -quality 100 $work_dir/f_$frame.jpg
221 eval "$( echo "$line" | sed "s/'/\´/g; s/^\([^\s]*\),\([^\s]*\) \([^\s]*\) \(.*\)$/goto_x='\1'\ngoto_y='\2'\nzoom_w='\3'\nname='\4'/" )" #'
222 zoom_h=$( round "$zoom_w * $vsd" )
223 echo "Zooming $name (${old_x},${old_y}:${oldz_w}x${oldz_h} -> ${goto_x},${goto_y}:${zoom_w}x${zoom_h})"
226 for step in $( seq 2 $frames_stoped ); do
229 cp $work_dir/f_$last_frame.jpg $work_dir/f_$frame.jpg
238 goto_x=$( round "$pic_w / 2" )
239 goto_y=$( round "$pic_h / 2" )
241 zoom_w=$( round "$zoom_h / $vsd" )
242 if [ $zoom_w -gt $zoom_w ]; then
244 zoom_h=$( round "$zoom_w * $vsd" )
246 echo "Zooming The End (${old_x},${old_y}:${oldz_w}x${oldz_h} -> ${goto_x},${goto_y}:${zoom_w}x${zoom_h})"
249 ) # end frame generator loop
251 echo "Generating the movie..."
254 if ffmpeg -i "$work_dir/f_%d.jpg" "$output"; then
255 echo " Done: $output"