1#############################################################################
2# Author:                                                                   #
3# ------                                                                    #
4#  Anton Kokalj                                  Email: Tone.Kokalj@ijs.si  #
5#  Department of Physical and Organic Chemistry  Phone: x 386 1 477 3523    #
6#  Jozef Stefan Institute                          Fax: x 386 1 477 3811    #
7#  Jamova 39, SI-1000 Ljubljana                                             #
8#  SLOVENIA                                                                 #
9#                                                                           #
10# Source: $XCRYSDEN_TOPDIR/Tcl/__file__
11# ------                                                                    #
12# Copyright (c) 2008 by Anton Kokalj                                        #
13#############################################################################
14
15proc determine_movie_encoders {} {
16    global xcMisc
17
18    set gif_encoder_priority_list   {convert gifsicle whirlgif}
19    set movie_encoder_priority_list {mencoder ppmtompeg}
20
21    if { [info exists xcMisc(gif_encoder)] } {
22	set gif_encoder_priority_list [linsert $gif_encoder_priority_list 0 [file tail $xcMisc(gif_encoder)]]
23    }
24    if { [info exists xcMisc(movie_encoder)] } {
25	set movie_encoder_priority_list [linsert $movie_encoder_priority_list 0 [file tail $xcMisc(movie_encoder)]]
26    }
27
28    foreach enc $gif_encoder_priority_list {
29	if { [info exists xcMisc($enc)] } {
30	    set xcMisc(gif_encoder) $enc
31	    break
32	}
33    }
34
35    foreach enc $movie_encoder_priority_list {
36	if { [info exists xcMisc($enc)] } {
37	    set xcMisc(movie_encoder) $enc
38	    break
39	}
40    }
41}
42
43
44# ------------------------------------------------------------------------
45#
46# AVI/MPEG movies
47#
48# ------------------------------------------------------------------------
49
50proc encode_movie {filelist outfile} {
51    global gifAnim xcMisc system
52
53    if { $gifAnim(temp_files_dir) == "pwd" } {
54	set dir $system(PWD)
55	cd $system(PWD)
56    } else {
57	set dir $system(SCRDIR)
58	cd $system(SCRDIR)
59    }
60
61    set cmdLine [cmdLine_$xcMisc(movie_encoder) $filelist $outfile $dir]
62
63    set cw [DisplayUpdateWidget "Encoding" "Encoding the movie"]
64    eval xcCatchExecReturnRedirectStdErr $cmdLine
65    destroy $cw
66}
67
68
69proc cmdLine_ppmtompeg {filelist outfile input_dir} {
70    global xcMisc
71    return "$xcMisc(ppmtompeg) [mpegCreateParamFile $outfile $input_dir [join $filelist\n]]"
72}
73
74
75proc cmdLine_mencoder {filelist outfile input_dir} {
76    global gifAnim xcMisc
77
78    if { [regexp {\.ppm[ \n\r,]|\.ppm$} $filelist] } {
79	# we need to convert all *.PPM files to *.PNG files
80	set cw [DisplayUpdateWidget "Converting" "Converting frame files to PNG format"]
81	foreach image $gifAnim(filelist) {
82	    set newfile [file rootname $image].png
83	    scripting::_printToFile_imageConvert $image $newfile
84	}
85	set tmplist $filelist
86	regsub -all -- {\.ppm} $tmplist .png filelist
87	destroy $cw
88    }
89
90    set delay [expr {$gifAnim(delay) <= 0.0 ? 1 : $gifAnim(delay)}]
91    set fps [expr 100.0 / $delay]
92
93    set cmdLine "$xcMisc(mencoder) mf://[join $filelist ,]"
94
95    if { [string toupper [file extension $outfile]] == ".AVI" } {
96	# create AVI file
97	append cmdLine " -mf fps=$fps -o $outfile -ovc lavc -lavcopts vcodec=mpeg4"
98    } else {
99	# create MPEG file
100	append cmdLine " -of mpeg -mf fps=$fps -o $outfile -ovc lavc -lavcopts vcodec=mpeg2video"
101    }
102
103    if { $gifAnim(edit_param) } {
104	set cmdLine [gifAnim:editParam $cmdLine]
105    }
106    return $cmdLine
107}
108
109
110# ------------------------------------------------------------------------
111#
112# Animated GIF
113#
114# ------------------------------------------------------------------------
115
116proc encode_gif {filelist outfile} {
117    global gifAnim xcMisc mesa_bg system
118
119    # determine the background color
120
121    if { $gifAnim(gif_transp) } {
122	if { ! [info exists mesa_bg(current)] } {
123	    set mesa_bg(current) \#000000
124	}
125	if { [string index $mesa_bg(current) 0] == "#" } {
126	    set bg_color $mesa_bg(current)
127	} else {
128	    set bg_color [rgb_f2h $mesa_bg(current)]
129	}
130	set gifAnim(bg_color) $bg_color
131    }
132
133    # construct the execution command-line for encoding
134
135    set cmdLine [cmdLine_$xcMisc(gif_encoder) $filelist $outfile]
136
137    # encode ...
138
139    if { $gifAnim(temp_files_dir) == "pwd" } {
140	cd $system(PWD)
141    } else {
142	cd $system(SCRDIR)
143    }
144    if { $gifAnim(edit_param) } {
145	set cmdLine [gifAnim:editParam $cmdLine]
146    }
147
148    puts stderr "cmdLine=$cmdLine"
149    flush stderr
150
151    set cw [DisplayUpdateWidget "Encoding" "Encoding the Animated-GIF movie"]
152    if { $xcMisc(gif_encoder) != "gifsicle" } {
153	eval xcCatchExecReturnRedirectStdErr $cmdLine
154    } else {
155	eval exec_gifsicle $cmdLine
156    }
157    destroy $cw
158}
159
160
161proc cmdLine_convert {filelist outfile} {
162    global gifAnim xcMisc
163
164    if { $gifAnim(gif_transp) } {
165	append comlin " -dispose Previous"
166    }
167
168    append comlin " $filelist -set delay $gifAnim(delay) -loop $gifAnim(loop)"
169
170    if { $gifAnim(gif_global_colormap) && !$gifAnim(gif_transp) } {
171	append comlin " +map"
172    }
173    if { $gifAnim(gif_transp) } {
174	append comlin " -transparent $gifAnim(bg_color)"
175    }
176    if { $gifAnim(gif_minimize) } {
177	append comlin " -layers optimize"
178    }
179    return [format "%s %s %s" $xcMisc(convert) $comlin $outfile]
180}
181
182
183proc cmdLine_gifsicle {filelist outfile} {
184    global gifAnim xcMisc
185
186    set flags "--no-warnings --delay $gifAnim(delay) --loopcount=$gifAnim(loop)"
187    if { $gifAnim(gif_transp) } {
188	append flags " --disposal background --transparent=$gifAnim(bg_color)"
189    }
190    if { $gifAnim(gif_minimize) } {
191	append flags " -O2"
192    }
193    if { $gifAnim(gif_global_colormap) } {
194	# ignored
195    }
196    return [format "%s %s %s > %s" $xcMisc(gifsicle) $flags $filelist $outfile]
197}
198
199
200proc cmdLine_whirlgif {filelist outfile} {
201    global gifAnim xcMisc
202
203    set flags " -time $gifAnim(delay) -loop $gifAnim(loop)"
204    if { $gifAnim(gif_minimize) } {
205	append flags " -minimize"
206    }
207    if { $gifAnim(gif_global_colormap) } {
208	append flags " -globalmap"
209    }
210    if { $gifAnim(gif_transp) } {
211	append flags " -disp prev -trans $gifAnim(bg_color)"
212    }
213
214    return [format "%s %s %s %s %s" $xcMisc(whirlgif) $flags -o $outfile $filelist]
215}
216
217
218proc exec_gifsicle {args} {
219    xcDebug -stderr "Executing: $args"
220    if { [catch {eval exec $args 2> gifsicle.stderr} errMsg] } {
221	# gifsicle returns wrong status of 1 when -transparent option
222	# is used
223	set msg [ReadFile gifsicle.stderr]
224	if { [string match {*Usage: gifsicle*} $msg] } {
225	    ErrorDialogInfo "while executing\nexec $args" $msg\n$errMsg
226	    uplevel 1 {
227		return 1
228	    }
229	}
230    }
231    return 0
232}