@@ -212,18 +212,42 @@ class Tool
212212 // / @brief Converts all quads into triangles
213213 void quadsToTriangles ();
214214
215- #ifdef VDB_TOOL_USE_IMG_TO_MPEG
215+ #ifdef VDB_TOOL_USE_IMG_TO_MPEG
216216 // / @brief Convert multiple image files to a mpeg movie file
217+ // vdb_tool -sphere -for x=0,1,0.01 -slice X='{$x}' -end -img2mpeg input="slice_*.ppm" output=slices.mp4
218+ // vdb_tool -sphere -for x=0,1,0.01 -slice X='{$x}' -end -img2mpeg && open slices.mp4
217219 void imgToMpeg () {
218- std::string cmd (" ffmpeg -loglevel error -framerate 30 -i slice_%03d.ppm dragon_30fps_v2.mp4" ), logFile (" log.txt" );
219- cmd += " > " + logFile + " 2>&1" ;
220+ const int framerate = mParser .get <int >(" framerate" );
221+ const std::string input = mParser .get <std::string>(" input" );
222+ const std::string output = mParser .get <std::string>(" output" );
223+ const bool keep = mParser .get <bool >(" keep" );
224+ const std::string flip = mParser .get <std::string>(" flip" );
225+
226+ std::string cmd (" ffmpeg" ), log (" log.txt" );
227+ cmd += " -loglevel error" ;// only log error messages
228+ cmd += " -pattern_type glob" ;// support expanding shell-like wildcard patterns (globbing)
229+ cmd += " -framerate " + std::to_string (framerate);// specify frame rate
230+
231+ cmd += " -i \' " + input + " \' " ;// specify multiple input files as "input_*.ppm"
232+ if (flip==" vertical" ) {
233+ cmd += " -vf \" vflip\" " ;// flip vertical (up/down)
234+ } else if (flip==" horizontal" ) {
235+ cmd += " -vf \" hflip\" " ;// flip horizontal (left/right)
236+ } else if (flip==" 180" ) {
237+ cmd += " -vf \" vflip,hflip\" " ;// rotate 180
238+ } else if (flip!=" " ) {
239+ throw std::invalid_argument (" Tool::imgToMpeg: invalid flip argument: \" " +flip+" \" , expected \" vertical\" , \" horizontal\" or \" 180\" " );
240+ }
241+ cmd += " -y " + output;// overwrite output files without asking
242+ cmd += " > " + log + " 2>&1" ;// redirect stdout and stderr to log file
243+
220244 const int code = std::system (cmd.c_str ());
221245 if (code != 0 ) {
222246 std::stringstream ss;
223- ss << " \n Fatal error in Tool::imgToMpeg: " << code << " \n\" " << cmd << " \"\n " << std::ifstream (logFile ).rdbuf ();
247+ ss << " \n Fatal error in Tool::imgToMpeg: " << code << " \n\" " << cmd << " \"\n " << std::ifstream (log ).rdbuf ();
224248 throw std::runtime_error (ss.str ());
225249 }
226- std::system ((" rm " + logFile ).c_str ());
250+ std::system ((" rm " + log ).c_str ());
227251 }
228252 #endif
229253
@@ -464,9 +488,12 @@ void Tool::init()
464488
465489 #ifdef VDB_TOOL_USE_IMG_TO_MPEG
466490 mParser .addAction (
467- {" img2mpeg" }, " Convert all quads in mesh to triangles, assuming they are both planar and convex" ,
468- {{" geo" , " 0" , " 0" , " age (i.e. stack index) of the geometry to be processed. Defaults to 0, i.e. most recently inserted geometry." },
469- {" keep" , " " , " 1|0|true|false" , " toggle wether the input geometry is preserved or deleted after the conversion" }},
491+ {" img2mpeg" }, " Convert multiple images to an mpeg file" ,
492+ {{" framerate" , " 24" , " 30" , " desired frame rate of mpeg movie" },
493+ {" input" , " slice_*.ppm" , " input.avi" , " input image files" },
494+ {" output" , " slices.mp4" , " output.mp4" , " name out output mpeg file." },
495+ {" flip" , " " , " vertical|horizontal|180" , " flip output video vertical or horizontal or rotate it by 180" },
496+ {" keep" , " true" , " 1|0|true|false" , " toggle wether the input images are preserved or deleted after the conversion" }},
470497 [&](){mParser .setDefaults ();}, [&](){this ->imgToMpeg ();});
471498#endif
472499
@@ -780,13 +807,13 @@ void Tool::init()
780807 mParser .addAction (
781808 {" slice" }, " Generate images of slices of a VDB grid" ,
782809 {{" vdb" , " 0" , " 0" , " age (i.e. stack index) of the VDB grid to be processed. Defaults to 0, i.e. most recently inserted VDB." },
783- {" keep" , " " , " 1|0|true|false" , " toggle wether the input VDB is preserved or deleted after the processing" },
810+ {" keep" , " true " , " 1|0|true|false" , " toggle wether the input VDB is preserved or deleted after the processing" },
784811 {" file" , " slice" , " slice" , " name of ppm file(s) of slices" },
785812 {" force" , " 0" , " 1|0|true|false" , " force computations of min/max, else use expected values for LS and FOG volumes (default)" },
786813 {" image" , " 512x512" , " 1920x1080" , " image size defined in terms of pixel resolution" },
787814 {" X" , " 0.5" , " 1" , " One or more X-slices in range 0 -> 1. Defaults to 0.5, i.e. mid-point" },
788- {" Y" , " 0.5 " , " 1" , " One or more Y-slices in range 0 -> 1. Defaults to 0.5, i.e. mid-point" },
789- {" Z" , " 0.5 " , " 1" , " One or more Z-slices in range 0 -> 1. Defaults to 0.5, i.e. mid-point" }},
815+ {" Y" , " " , " 1" , " One or more Y-slices in range 0 -> 1. Defaults to 0.5, i.e. mid-point" },
816+ {" Z" , " " , " 1" , " One or more Z-slices in range 0 -> 1. Defaults to 0.5, i.e. mid-point" }},
790817 [&](){mParser .setDefaults ();}, [&](){this ->slice ();});
791818
792819 mParser .addAction (
0 commit comments