perturbation based calculations
[maximus:emndl.git] / emndl.sh
1 #!/bin/bash
2 #
3 #    emndl -- exponentially transformed Mandelbrot Set renderer
4 #    Copyright (C) 2011,2012  Claude Heiland-Allen <claude@mathr.co.uk>
5 #
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.
10 #
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.
15 #
16 #    You should have received a copy of the GNU General Public License
17 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 TIME0="$(date --iso=s)"
21 E="$(dirname "$(readlink -f "$0")")"
22 OUT="emndl_${TIME0}"
23
24 version()
25 {
26 cat << EOF
27 emndl.sh git (GPL) 2011,2012  Claude Heiland-Allen <claude@mathr.co.uk>
28 EOF
29 }
30
31 usage()
32 {
33 cat << EOF
34 usage options:
35     --help -h -?    show this message and exit
36     --version       show version and exit
37
38 input options:
39     --auto bits     find an interesting point with precision 'bits'
40     --re real       choose coordinates
41     --im imag
42     --period p
43     --size sz
44
45 render options:
46     --quality q     horizontal size, (5 - 11)
47     --threads t     number of worker threads (1 - ?, default 2)
48
49 image options:
50     --png           generate full size PNG
51     --jpeg          generate thumbnail JPEG
52
53 video options:
54     --aspect w:h    output aspect (4:3, 16:9)
55     --speed s       zoom speed (default 1)
56     --dvd           generate PAL DVD (SD)
57     --mkv           generate Matroska (HD)
58     --ogv           generate Theora (LD)
59
60 other options:
61     --quiet         less output
62     --verbose       more output
63 EOF
64 }
65
66 if [ "x$*" == "x" ]
67 then
68   version
69   cat << EOF
70 Try \`emndl.sh --help' for usage information.
71 EOF
72   exit 0
73 fi
74
75 TEMP=`getopt -o '' --long help,version,auto:,re:,im:,period:,size:,quality:,threads:,png,jpeg,aspect:,speed:,dvd,mkv,ogv,quiet,verbose -n 'emndl.sh' -- "$@"`
76 if [ $? != 0 ]
77 then
78   echo "error 1 in getopt" >&2
79   exit 1
80 fi
81
82 eval set -- "$TEMP"
83
84 AUTO=0
85 AUTOBITS="128"
86 REAL=0
87 REALCOORD="0.0"
88 IMAG=0
89 IMAGCOORD="0.0"
90 PER=0
91 PERIOD=1
92 SZ=0
93 SIZE=1
94 QUALITY="8"
95 THREADS="2"
96 PNG=0
97 JPEG=0
98 ASPECT="16:9"
99 SPEED="1"
100 DVD=0
101 MKV=0
102 OGV=0
103 VERBOSE=1
104
105 while true
106 do
107   case "$1" in
108     --help|-h|-\?) usage ; exit 0 ;;
109     --version) version ; exit 0 ;;
110     --auto) AUTO=1 ; AUTOBITS="$2" ; shift 2 ;;
111     --re) REAL=1 ; REALCOORD="$2" ; shift 2 ;;
112     --im) IMAG=1 ; IMAGCOORD="$2" ; shift 2 ;;
113     --period) PER=1; PERIOD="$2" ; shift 2 ;;
114     --size) SZ=1; SIZE="$2" ; shift 2 ;;
115     --quality) QUALITY="$2" ; shift 2 ;;
116     --threads) THREADS="$2" ; shift 2 ;;
117     --png) PNG=1 ; shift ;;
118     --jpeg) JPEG=1 ; shift ;;
119     --aspect) ASPECT="$2" ; shift 2 ;;
120     --speed) SPEED="$2" ; shift 2 ;;
121     --dvd) DVD=1 ; shift ;;
122     --mkv) MKV=1 ; shift ;;
123     --ogv) OGV=1 ; shift ;;
124     --quiet) VERBOSE=0 ; shift ;;
125     --verbose) VERBOSE=2 ; shift ;;
126     --) shift ; break ;;
127     *) echo "error 2 in getopt" >&2 ; exit 1 ;;
128   esac
129 done
130
131 (
132
133 case "$ASPECT" in
134   4:3) WIDE=0 ;;
135   16:9) WIDE=1 ;;
136   *) echo "aspect $ASPECT not recognized" >&2 ; exit 1 ;;
137 esac
138
139 case "$QUALITY" in
140   5) WIDTH=32 ;;
141   6) WIDTH=64 ;;
142   7) WIDTH=128 ;;
143   8) WIDTH=256 ;;
144   9) WIDTH=512 ;;
145   10) WIDTH=1024 ;;
146   11) WIDTH=2048 ;;
147   *) echo "quality $QUALITY not recognized" >&2 ; exit 1 ;;
148 esac
149
150 if [ $AUTO -eq 1 ]
151 then
152   # FIXME
153   TEMP="$("${E}/emndl_automu" "${AUTOBITS}" "${PERIOD}" "${REALCOORD}" "${IMAGCOORD}" 2>/dev/null | while read b p r i s ; do if (( "${p}" > 256)) ; then echo "${r} ${i} ${p}" ; break ; else echo "${r} ${i} ${p}" 1>&2 ; fi ; done)"
154   REALCOORD="$(echo "${TEMP}" | sed 's|^\([^ ]*\) .*$|\1|')"
155   IMAGCOORD="$(echo "${TEMP}" | sed 's|^[^ ]* \([^ ]*\) .*$|\1|')"
156   PERIOD="$(echo "${TEMP}" | sed 's|^[^ ]* [^ ]* \([^ ]*\)$|\1|')"
157 fi
158
159 if [ $VERBOSE -gt 0 ]
160 then
161   cat << EOF
162 AUTO=$AUTO
163 AUTOBITS=$AUTOBITS
164 REAL=$REAL
165 REALCOORD=$REALCOORD
166 IMAG=$IMAG
167 IMAGCOORD=$IMAGCOORD
168 PER=$PER
169 PERIOD=$PERIOD
170 SZ=$SZ
171 SIZE=$SIZE
172 QUALITY=$QUALITY
173 THREADS=$THREADS
174 PNG=$PNG
175 JPEG=$JPEG
176 ASPECT=$ASPECT
177 SPEED=$SPEED
178 DVD=$DVD
179 MKV=$MKV
180 OGV=$OGV
181 VERBOSE=$VERBOSE
182
183 WIDE=$WIDE
184 WIDTH=$WIDTH
185 E=$E
186 OUT=$OUT
187 EOF
188 fi
189
190 mkdir "${OUT}"
191 cd "${OUT}"
192
193 if [ $VERBOSE -gt 0 ] ; then echo "calculating.." ; fi
194 "${E}/emndl_calculate" "out.emndl" "${WIDTH}"
195
196 if [ $VERBOSE -gt 0 ] ; then echo "finalizing.." ; fi
197 "${E}/emndl_finalize" "out.emndl" "dwell-neq.f" "distance.f" "domain.f"
198
199 if [ $VERBOSE -gt 0 ] ; then echo "equalizing.." ; fi
200 "${E}/emndl_equalize" "dwell-neq.f" "dwell.f"
201
202 if [ $VERBOSE -gt 0 ] ; then echo "computing depth.." ; fi
203 DEPTH="$(( $(stat -c '%s' "dwell.f") / (WIDTH * WIDTH * 4) ))"
204 if [ $VERBOSE -gt 0 ] ; then echo "DEPTH=${DEPTH}" ; fi
205
206 if [ $VERBOSE -gt 0 ] ; then echo "downscaling.." ; fi
207 for p in dwell distance domain
208 do
209   cat "${p}.f" "/dev/zero" | head -c "$(( WIDTH * WIDTH * (DEPTH + 1) * 4 ))" > "${p}-00.f"
210 done
211 for q in $(seq "0" "$((QUALITY - 1))")
212 do
213   for p in dwell distance domain
214   do
215     "${E}/emndl_downscale" "${p}" "$(( 1 << (QUALITY - q) ))" < "${p}-$(printf "%02d" "$((q))").f" > "${p}-$(printf "%02d" "$((q + 1))").f"
216   done
217 done
218
219 if [ $VERBOSE -gt 0 ] ; then echo "colourizing.." ; fi
220 for q in $(seq 0 "${QUALITY}")
221 do
222   f="$(printf "%02d" "${q}").f"
223   r="${f%f}raw"
224   "${E}/emndl_colourize" "dwell-${f}" "distance-${f}" "domain-${f}" "${r}"
225   w="$(( 1 << (QUALITY - q) ))"
226   h="$(( w * (DEPTH + 1) ))"
227   ( echo -e "P6\n${w} ${h} 255" && cat "${r}" ) > "emndl.${f%f}ppm"
228 done
229
230 if [ $VERBOSE -gt 0 ] ; then echo "making images.." ; fi
231 if [ $PNG  -eq 1 ] ; then convert "emndl.00.ppm" "out.png" ; fi
232 if [ $JPEG -eq 1 ] ; then convert "emndl.00.ppm" -thumbnail 64x "out.jpeg" ; fi
233
234 if [ $VERBOSE -gt 0 ] ; then echo "making videos.." ; fi
235 if [ $DVD -eq 1 ] ; then mkfifo dvd.fifo ; ( cat dvd.fifo | y4mscaler -v 0 -O preset=dvd_wide -O yscale=1/1 | mpeg2enc -v 0 -f 8 -q 3 -b 8000 -B 768 -D 9 -g 9 -G 15 -P -R 2 -o "video.m2v" ) & fi
236 if [ $MKV -eq 1 ] ; then mkfifo mkv.fifo ; ( cat mkv.fifo | ffmpeg -f yuv4mpegpipe -b 2500000 -i - video.mkv ) & fi
237 if [ $OGV -eq 1 ] ; then mkfifo ogv.fifo ; ( cat ogv.fifo | ffmpeg2theora -x 512 -y 288 -o video.ogv - >/dev/null 2>&1 ) & fi
238 if [ $((DVD + MKV + OGV)) -gt 0 ]
239 then
240   "${E}/emndl_unwarp" emndl 1050 576 "${SPEED}" 2>audio.raw |
241   "${E}/emndl_ppmtoy4m" 1050 576 |
242   if [ $DVD -eq 1 ] ; then tee -a dvd.fifo ; else cat ; fi |
243   if [ $MKV -eq 1 ] ; then tee -a mkv.fifo ; else cat ; fi |
244   if [ $OGV -eq 1 ] ; then tee -a ogv.fifo ; else cat ; fi > /dev/null
245 fi
246
247 wait
248
249 if [ $VERBOSE -gt 0 ] ; then echo "making soundtrack.." ; fi
250 if [ $((DVD + MKV + OGV)) -gt 0 ]
251 then
252   ecasound -q -f:f32_le,2,48000,i -i:audio.raw -f:s16_le,2,48000,i -o:audio-raw.wav
253   if [ "x$(pwd | tr -cd "[:space:]\\{}")" == "x" ]
254   then
255     pd -path . -r 48000 -batch -open "${E}/../share/emndl/emndl_loader.pd" -send "emndl audio-raw.wav $(pwd)/audio.wav"
256   else
257     echo "warning: dir \`$(pwd)' contains bad chars, aborting"
258     exit
259   fi
260 fi
261 if [ $DVD -eq 1 ]
262 then
263   twolame --quiet -b 224 audio.wav audio.mp2
264   mplex -v 0 -f 8 -V -o out.mpeg video.m2v audio.mp2
265 fi
266 if [ $MKV -eq 1 ]
267 then
268   flac --best --verify audio.wav -o audio.flac
269   mkv-merge -o out.mkv video.mkv audio.flac
270 fi
271 if [ $OGV -eq 1 ]
272 then
273   oggenc --quiet -b 192 -o audio.ogg audio.wav
274   oggz-merge -o out.ogv video.ogv audio.ogg
275 fi
276
277 cd ..
278 TIME1="$(date --iso=s)"
279
280 if [ $VERBOSE -gt 0 ]
281 then
282   echo "${TIME0}  begin"
283   echo "${TIME1}  end"
284 fi
285
286 ) 2>&1 | tee "${OUT}.log"
287
288 exit 0