From 57255405b5a630678e42f20565da4287d7910694 Mon Sep 17 00:00:00 2001
From: M McWilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 13:18:14 -0700
Subject: [PATCH 01/10] Ignore nexe files from building

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 7e51146..a0b655f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 tmp/*
 temp/*
+.nexe
\ No newline at end of file

From c65f08d86c57839589d581435fe8225d5fa88712 Mon Sep 17 00:00:00 2001
From: M McWilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 13:58:37 -0700
Subject: [PATCH 02/10] Use latest node version with nexe and add lcok file

---
 package-lock.json |  5 +++++
 package.json      | 16 ++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)
 create mode 100644 package-lock.json

diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..c529078
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,5 @@
+{
+  "name": "v2f",
+  "version": "1.0.0",
+  "lockfileVersion": 1
+}
diff --git a/package.json b/package.json
index d57d4d2..f221e0c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "v2f",
-  "version": "1.0.0",
+  "version": "1.0.1",
   "description": "Turn a video into strips of precise 16mm-size stills",
   "main": "v2f.js",
   "scripts": {
@@ -8,12 +8,12 @@
   },
   "author": "mmcwilliams",
   "license": "MIT",
-  "nexe" : {
-	  "output" : "../video_to_page_nexe/v2f",
-	  "runtime": {
-			"ignoreFlags": true,
-			"framework" : "nodejs",
-			"version" : "5.0.0"
-		}
+  "nexe": {
+    "output": "../video_to_page_nexe/v2f",
+    "runtime": {
+      "ignoreFlags": true,
+      "framework": "nodejs",
+      "version": "8.6.0"
+    }
   }
 }

From 36c4875d1b664700e36ea8c594d62e76801a9467 Mon Sep 17 00:00:00 2001
From: M McWilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 14:00:12 -0700
Subject: [PATCH 03/10] Update project readme and a readme file for explaining
 the source.

---
 Readme.md      |  7 +++++--
 docs/Readme.md | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 2 deletions(-)
 create mode 100644 docs/Readme.md

diff --git a/Readme.md b/Readme.md
index e3a5c59..23c196f 100644
--- a/Readme.md
+++ b/Readme.md
@@ -3,7 +3,7 @@ v2f
 
 Convert video to 16mm-sized strips of frames. For transferring to acetate and other experimental needs.
 
-Look how easy it is to use:
+Use the distributed binary
 
     ./v2f ./path_to_video.mov 300
 
@@ -22,7 +22,7 @@ Releases
 Dependencies
 ------------
 
-- node.js (or use a compiled version)
+- node.js (or use a [released version](https://github.com/sixteenmillimeter/v2f/releases/))
 - libav
 - ImageMagick
 
@@ -37,11 +37,14 @@ Ubuntu
 
 	apt-get install libav imagemagick
 
+
+
 Contribute
 ----------
 
 - Issue Tracker: https://github.com/sixteenmillimeter/v2f/issues
 - Source Code: https://github.com/sixteenmillimeter/v2f
+- Home Page: https://sixteenmillimeter.com/projects/v2f
 
 Support
 -------
diff --git a/docs/Readme.md b/docs/Readme.md
new file mode 100644
index 0000000..e1e1c82
--- /dev/null
+++ b/docs/Readme.md
@@ -0,0 +1,36 @@
+## Functions
+
+<dl>
+<dt><a href="#convert">convert(path, dpi, length)</a></dt>
+<dd><p>Turn video into sheet of images</p>
+</dd>
+<dt><a href="#stitch">stitch(loc, dim)</a></dt>
+<dd><p>Stitch rendered frames into strips</p>
+</dd>
+</dl>
+
+<a name="convert"></a>
+
+## convert(path, dpi, length)
+Turn video into sheet of images
+
+**Kind**: global function  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| path | <code>String</code> | file path (absolute) |
+| dpi | <code>Integer</code> | target printing dpi |
+| length | <code>Integer</code> | strip length in frames |
+
+<a name="stitch"></a>
+
+## stitch(loc, dim)
+Stitch rendered frames into strips
+
+**Kind**: global function  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| loc | <code>String</code> | Path of folder containing frames |
+| dim | <code>Object</code> | Dimensions object |
+

From ff8d0a5f93720db66a9aae75b895b1f298e30efd Mon Sep 17 00:00:00 2001
From: M McWilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 14:01:25 -0700
Subject: [PATCH 04/10] Es6 refactor, more to come. Will be re-structuring 
 v2f.js to handle multiple formats and better manage files in different
 locations.

---
 v2f.js | 166 +++++++++++++++++++++++++++++++--------------------------
 1 file changed, 91 insertions(+), 75 deletions(-)

diff --git a/v2f.js b/v2f.js
index d85a056..e1b7983 100755
--- a/v2f.js
+++ b/v2f.js
@@ -1,103 +1,119 @@
-var exec = require('child_process').exec,
-	fs = require('fs'),
-	_tmp = './temp';
+/*jshint strict: true, esversion:6, node: true, asi: true*/
 
-//var frame_height = 7.61;
-//var frame_height = 7.49;
-var frame_height = 7.62;
-var frame_padding = 0;
+'use strict'
+const exec = require('child_process').exec
+const fs = require('fs')
+const _tmp = './temp'
 
-var frame_dimensions = function (dpi) {
-	var h = Math.round(frame_height * (dpi / 25.4)),
-		w = Math.round(10.5 * (dpi / 25.4)),
-		o = Math.round(16 * (dpi / 25.4));
-	return {h: h, w: w, o: o, dpi: dpi};
-};
+//var frame_height = 7.61
+//var frame_height = 7.49
+let frame_height = 7.62
+let frame_padding = 0
 
-/*
-convert() - Turn video into sheet of images
+class Dimensions{
+	constructor (film, dpi) {
+		const IN = dpi / 25.4
+		this.h = Math.round(film.frame_height * IN)
+		this.w = Math.round(film.a * IN)
+		this.o = Math.round(film.b * IN)
+		this.dpi = dpi
+		this.film = film
+	}
+}
 
-@param: path - file path (absolute)
-@param: dpi - target printing dpi
-@param: length - strip length in frames
+/** *
+ * Turn video into sheet of images
 
+ * @function
+ * @param {String} 	path  file path (absolute)
+ * @param {Integer} dpi target printing dpi
+ * @param {Integer} length strip length in frames
+ * 
 */
-var convert = function (path, dpi) {
-	'use strict';
-	var dim = frame_dimensions(dpi),
-		file = path.split('/').pop(),
-		loc = _tmp + '/',
-		execStr = 'avconv -i "' + path + '" -s ' + dim.w + 'x' + dim.h + ' -qscale 1 "' + loc + 'sequence_%04d.jpg"';
+function convert (path, dpi) {
+	const film = { frame_height: frame_height, a : 10.5, b : 16}
+	const dim = new Dimensions(film, dpi)
+	const file = path.split('/').pop()
+	const loc = _tmp + '/'
+	const execStr = `avconv -i "${path}" -s ${dim.w}x${dim.h} -qscale 1 "${loc}sequence_%04d.jpg"`
 
-	console.log('Converting ' + file + '...');
-	console.log('Exporting all frames with aspect ratio: ' + (dim.w / dim.h) + '...');
+	console.log(`Converting  ${file}...`)
+	console.log(`Exporting all frames with aspect ratio:  ${dim.w / dim.h} ...`)
 
-	fs.mkdirSync(_tmp);
+	fs.mkdirSync(_tmp)
 
-	exec(execStr, function (ste, std) {
+	exec(execStr, (ste, std) => {
 		if (ste) {
-			return errorHandle(ste);
+			return errorHandle(ste)
 		}
-		console.log('Frames exported successfully!');
-		stitch(loc.substring(0, loc.length - 1), dim);
-	});
-};
+		console.log('Frames exported successfully!')
+		stitch(loc.substring(0, loc.length - 1), dim)
+	})
+}
 
-var stitch = function (loc, dim) {
-	'use strict';
-	var length = Math.floor((11 * dim.dpi) / dim.h) - 1,
-		width = Math.floor((8.5 * dim.dpi / dim.o)) - 1,
-		page = 0,
-		pageCount = 0,
-		cmd = 'find "' + loc + '" -type f -name "sequence_*.jpg"',
-	find_cb = function (ste, std) {
+/** *
+ * Stitch rendered frames into strips
+
+ * @function
+ * @param {String} 	loc   Path of folder containing frames
+ * @param {Object}  dim   Dimensions object
+ * 
+*/
+
+function stitch (loc, dim) {
+	const length = Math.floor((11 * dim.dpi) / dim.h) - 1
+	const width = Math.floor((8.5 * dim.dpi / dim.o)) - 1
+	let page = 0
+	let pageCount = 0
+	let cmd = `find "${loc}" -type f -name "sequence_*.jpg"`
+	function find_cb (ste, std) {
 		if (ste) {
-			return errorHandle(ste);
+			return errorHandle(ste)
 		}
-		var frames = std.split('\n'),
-			execStr = 'montage ',
-		montage_cb = function (stee, stdd) {
+		const frames = std.split('\n')
+		let execStr = 'montage '
+		function montage_cb (stee, stdd) {
 			if (stee) {
-				return errorHandle(ste);
+				return errorHandle(ste)
 			}
 
-			console.log('Created page_' + pageCount + '.jpg!');
-			pageCount++;
+			console.log(`Created page_${pageCount}.jpg!`)
+			pageCount++
 			if (pageCount === page) {
 				console.log('Cleaning up...');
-				setTimeout(function () {
-					exec('find "' + loc + '" -type f -name "sequence_*.jpg" -delete', function () {
-						fs.rmdirSync(_tmp);
-						console.log('Done!');
-					});
-				}, 1000);
+				setTimeout(() => {
+					exec(`find "${loc}" -type f -name "sequence_*.jpg" -delete`,  () => {
+						fs.rmdirSync(_tmp)
+						console.log('Done!')
+					})
+				}, 1000)
 			}
 		};
-		for (var i = 0; i < frames.length; i++) {
-			execStr += frames[i] + ' ';
+		for (let i = 0; i < frames.length; i++) {
+			execStr += frames[i] + ' '
 			if ((i + 1) % (width * length) === 0 || i === frames.length - 1) {
-				execStr += '\ -tile 1x' + length + '  -geometry ' + dim.w + 'x' + dim.h + '+' + Math.round((dim.o - dim.w) / 2) + '+0 miff:- |\  \nmontage - -geometry +0+0 -tile ' + width + 'x1 -density ' + dim.dpi + ' "./page_' + page + '.jpg"';
-				exec(execStr, montage_cb);
-				execStr = 'montage ';
-				page++;
+				execStr += '\ -tile 1x' + length + '  -geometry ' + dim.w + 'x' + dim.h + '+' + Math.round((dim.o - dim.w) / 2) + '+0 miff:- |\  \nmontage - -geometry +0+0 -tile ' + width + 'x1 -density ' + dim.dpi + ' "./page_' + page + '.jpg"'
+				exec(execStr, montage_cb)
+				execStr = 'montage '
+				page++
 			}
 		}
-	};
-
-	loc = _tmp;
-
-	console.log('Stitching frames into sheets...');
-	console.log('Sheets will contain ' + width + 'x' + length + ' frames...');
-	exec(cmd, find_cb);
-};
-var errorHandle = function (err) {
-	'use strict';
-	if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){
-		console.error(err);
-	} else {
-		console.error('Error running program. Run in verbose mode for more info (-v,--verbose)');
 	}
-	process.exit(1);
+
+	loc = _tmp
+
+	console.log('Stitching frames into sheets...')
+	console.log(`Sheets will contain ${width}x${length} frames...`)
+	exec(cmd, find_cb)
+};
+
+var errorHandle = function (err) {
+	if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){
+		console.error(err)
+	} else {
+		console.error('Error running program. Run in verbose mode for more info (-v,--verbose)')
+	}
+	process.exit(1)
 };
 
 process.on('uncaughtException', function (err) {

From 79b099b05891f48e906a82c427a84317826cfe43 Mon Sep 17 00:00:00 2001
From: mmcwilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 17:21:38 -0400
Subject: [PATCH 05/10] Update version in package-lock

---
 package-lock.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package-lock.json b/package-lock.json
index c529078..db68590 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
 {
   "name": "v2f",
-  "version": "1.0.0",
+  "version": "1.0.1",
   "lockfileVersion": 1
 }

From 20930513f9df8a6674cd265c92350a192247fc25 Mon Sep 17 00:00:00 2001
From: mmcwilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 19:58:21 -0400
Subject: [PATCH 06/10] Check if local temp file, if not, make one

---
 v2f.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/v2f.js b/v2f.js
index e1b7983..68766cb 100755
--- a/v2f.js
+++ b/v2f.js
@@ -40,7 +40,7 @@ function convert (path, dpi) {
 	console.log(`Converting  ${file}...`)
 	console.log(`Exporting all frames with aspect ratio:  ${dim.w / dim.h} ...`)
 
-	fs.mkdirSync(_tmp)
+	if (!fs.existsSync(_tmp)) fs.mkdirSync(_tmp)
 
 	exec(execStr, (ste, std) => {
 		if (ste) {

From 5cdd191f35a014a9f9a8fbdf71ee9854e5192c6d Mon Sep 17 00:00:00 2001
From: mmcwilliams <hi@mmcwilliams.com>
Date: Wed, 11 Oct 2017 20:06:27 -0400
Subject: [PATCH 07/10] Use system tmp, to prevent files from accumulating in
 the local directory

---
 v2f.js | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/v2f.js b/v2f.js
index 68766cb..b91d356 100755
--- a/v2f.js
+++ b/v2f.js
@@ -3,7 +3,7 @@
 'use strict'
 const exec = require('child_process').exec
 const fs = require('fs')
-const _tmp = './temp'
+const _tmp = '/tmp'
 
 //var frame_height = 7.61
 //var frame_height = 7.49
@@ -88,7 +88,7 @@ function stitch (loc, dim) {
 					})
 				}, 1000)
 			}
-		};
+		}
 		for (let i = 0; i < frames.length; i++) {
 			execStr += frames[i] + ' '
 			if ((i + 1) % (width * length) === 0 || i === frames.length - 1) {
@@ -105,7 +105,7 @@ function stitch (loc, dim) {
 	console.log('Stitching frames into sheets...')
 	console.log(`Sheets will contain ${width}x${length} frames...`)
 	exec(cmd, find_cb)
-};
+}
 
 var errorHandle = function (err) {
 	if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){
@@ -116,22 +116,22 @@ var errorHandle = function (err) {
 	process.exit(1)
 };
 
-process.on('uncaughtException', function (err) {
-	errorHandle(err);
-});
+process.on('uncaughtException', err => {
+	errorHandle(err)
+})
 
 
 if (typeof process.argv[2] === 'undefined') {
-	console.error('No path to video defined');
-	process.exit(1);
+	console.error('No path to video defined')
+	process.exit(1)
 }
 
 if (typeof process.argv[3] === 'undefined') {
-	process.argv[3] = 300;
-	console.log('Using default 300dpi');
+	process.argv[3] = 300
+	console.log('Using default 300dpi')
 }
 
-convert(process.argv[2], process.argv[3]);
+convert(process.argv[2], process.argv[3])
 
 /*
 

From 7cb27e7bea18c4bbf39bd69c1e1e766f2d4b9a30 Mon Sep 17 00:00:00 2001
From: mmcw-dev <hi@mmcwilliams.com>
Date: Fri, 27 Oct 2017 13:28:06 -0400
Subject: [PATCH 08/10] Install async and commander

---
 package-lock.json | 23 ++++++++++++++++++++++-
 package.json      |  6 +++++-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index db68590..6845444 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,26 @@
 {
   "name": "v2f",
   "version": "1.0.1",
-  "lockfileVersion": 1
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "async": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
+      "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==",
+      "requires": {
+        "lodash": "4.17.4"
+      }
+    },
+    "commander": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+      "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
+    },
+    "lodash": {
+      "version": "4.17.4",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+      "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
+    }
+  }
 }
diff --git a/package.json b/package.json
index f221e0c..bc91983 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,11 @@
     "runtime": {
       "ignoreFlags": true,
       "framework": "nodejs",
-      "version": "8.6.0"
+      "version": "8.7.0"
     }
+  },
+  "dependencies": {
+    "async": "^2.5.0",
+    "commander": "^2.11.0"
   }
 }

From 73775da9d1282bad184a03c6e99ff767013433d5 Mon Sep 17 00:00:00 2001
From: mmcw-dev <hi@mmcwilliams.com>
Date: Sun, 29 Oct 2017 23:52:14 -0400
Subject: [PATCH 09/10] Finished changes required to resolve issue #1 and issue
 #2. Added super16 and 35mm (4 perf) image sizes

---
 .gitignore |   1 +
 v2f.js     | 266 +++++++++++++++++++++++++++++++----------------------
 2 files changed, 157 insertions(+), 110 deletions(-)

diff --git a/.gitignore b/.gitignore
index a0b655f..aa4b8ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+node_modules
 tmp/*
 temp/*
 .nexe
\ No newline at end of file
diff --git a/v2f.js b/v2f.js
index b91d356..0ef9b9c 100755
--- a/v2f.js
+++ b/v2f.js
@@ -1,53 +1,103 @@
 /*jshint strict: true, esversion:6, node: true, asi: true*/
 
 'use strict'
+const cmd = require('commander')
+const async = require('async')
 const exec = require('child_process').exec
 const fs = require('fs')
-const _tmp = '/tmp'
+const path = require('path')
 
-//var frame_height = 7.61
-//var frame_height = 7.49
-let frame_height = 7.62
-let frame_padding = 0
+const TMP = '/tmp/v2f/'
 
 class Dimensions{
-	constructor (film, dpi) {
+	constructor (filmStr, dpi) {
 		const IN = dpi / 25.4
-		this.h = Math.round(film.frame_height * IN)
-		this.w = Math.round(film.a * IN)
-		this.o = Math.round(film.b * IN)
+		const film = this._gauge(filmStr)
+
+		this.h = Math.round(film.h * IN) //frame height
+		this.w = Math.round(film.w * IN) //frame width
+		this.o = Math.round(film.o * IN) //space between columns
 		this.dpi = dpi
 		this.film = film
 	}
+
+	_gauge (film) {
+		if (film === '16mm') {
+			return {
+				h: 7.62,
+				w : 10.5,
+				o : 16
+			}
+		} else if (film === 'super16'){
+			return {
+				h: 7.62,
+				w : 12.75,
+				o : 16
+			}
+		} else if (film === '35mm') {
+			return {
+				h : 19.05,
+				w : 22,
+				o : 35
+			}
+		} else {
+			error('Film type not found, see --help for more info')
+		}
+	}
+}
+
+/**
+ * 
+ *
+ * @function
+ * @param {Object} Commander object
+ */
+function initialize (command) {
+	const dpi = command.dpi || 300
+	const film = command.film || '16mm'
+	const input = command.input || command.args[0] || error('No input file, see --help for more info')
+	const output = command.output || command.args[1] || error('No ouput directory, see --help for more info')
+	const dim = new Dimensions(film, dpi)
+
+	if (!fs.existsSync(input)) error(`Video "${input}" cannot be found`)
+
+	async.series([
+		next => {
+			convert(input, dim, next)
+		},
+		next => {
+			stitch(output, dim, next)
+		},
+		cleanup
+	], () => {
+		console.log(`Finished creating pages`)
+	})
 }
 
 /** *
- * Turn video into sheet of images
-
+ * Create image sequence from source video, using
+ * 
  * @function
- * @param {String} 	path  file path (absolute)
- * @param {Integer} dpi target printing dpi
- * @param {Integer} length strip length in frames
+ * @param {String} 		input  	file path (absolute)
+ * @param {Integer} 	dpi 	target printing dpi
+ * @param {Integer} 	length 	strip length in frames
  * 
 */
-function convert (path, dpi) {
-	const film = { frame_height: frame_height, a : 10.5, b : 16}
-	const dim = new Dimensions(film, dpi)
-	const file = path.split('/').pop()
-	const loc = _tmp + '/'
-	const execStr = `avconv -i "${path}" -s ${dim.w}x${dim.h} -qscale 1 "${loc}sequence_%04d.jpg"`
+function convert (input, dim, next) {
+	const file = input.split('/').pop()
+	const execStr = `avconv -i "${input}" -s ${dim.w}x${dim.h} -qscale 1 "${TMP}v2f_sequence_%04d.jpg"`
 
 	console.log(`Converting  ${file}...`)
-	console.log(`Exporting all frames with aspect ratio:  ${dim.w / dim.h} ...`)
+	console.log(`Exporting all frames with aspect ratio:  ${dim.w / dim.h}...`)
 
-	if (!fs.existsSync(_tmp)) fs.mkdirSync(_tmp)
+	if (!fs.existsSync(TMP)) fs.mkdirSync(TMP)
 
 	exec(execStr, (ste, std) => {
 		if (ste) {
-			return errorHandle(ste)
+			return error(ste)
 		}
 		console.log('Frames exported successfully!')
-		stitch(loc.substring(0, loc.length - 1), dim)
+		next()
 	})
 }
 
@@ -55,114 +105,110 @@ function convert (path, dpi) {
  * Stitch rendered frames into strips
 
  * @function
- * @param {String} 	loc   Path of folder containing frames
- * @param {Object}  dim   Dimensions object
+ * @param {String}	 	output   	Path of folder containing frames
+ * @param {Object}	  	dim   		Dimensions object
+ * @param {Function}	next		Async lib callback function
  * 
 */
-
-function stitch (loc, dim) {
+function stitch (output, dim, next) {
 	const length = Math.floor((11 * dim.dpi) / dim.h) - 1
 	const width = Math.floor((8.5 * dim.dpi / dim.o)) - 1
+	const loc = TMP.substring(0, TMP.length - 1)
+	const diff = Math.round((dim.o - dim.w) / 2)
 	let page = 0
 	let pageCount = 0
-	let cmd = `find "${loc}" -type f -name "sequence_*.jpg"`
-	function find_cb (ste, std) {
-		if (ste) {
-			return errorHandle(ste)
-		}
-		const frames = std.split('\n')
-		let execStr = 'montage '
-		function montage_cb (stee, stdd) {
-			if (stee) {
-				return errorHandle(ste)
-			}
-
-			console.log(`Created page_${pageCount}.jpg!`)
-			pageCount++
-			if (pageCount === page) {
-				console.log('Cleaning up...');
-				setTimeout(() => {
-					exec(`find "${loc}" -type f -name "sequence_*.jpg" -delete`,  () => {
-						fs.rmdirSync(_tmp)
-						console.log('Done!')
-					})
-				}, 1000)
-			}
-		}
-		for (let i = 0; i < frames.length; i++) {
-			execStr += frames[i] + ' '
-			if ((i + 1) % (width * length) === 0 || i === frames.length - 1) {
-				execStr += '\ -tile 1x' + length + '  -geometry ' + dim.w + 'x' + dim.h + '+' + Math.round((dim.o - dim.w) / 2) + '+0 miff:- |\  \nmontage - -geometry +0+0 -tile ' + width + 'x1 -density ' + dim.dpi + ' "./page_' + page + '.jpg"'
-				exec(execStr, montage_cb)
-				execStr = 'montage '
-				page++
-			}
-		}
-	}
-
-	loc = _tmp
+	let cmd = `find "${loc}" -type f -name "v2f_sequence_*.jpg"`
 
 	console.log('Stitching frames into sheets...')
 	console.log(`Sheets will contain ${width}x${length} frames...`)
-	exec(cmd, find_cb)
+
+	exec(cmd, (ste, std) => {
+		if (ste) {
+			return error(ste)
+		}
+		let jobs = []
+		let cmds = []
+		let frames = std.split('\n')
+		let execStr = 'montage '
+		let pagePath = ``
+		let i = 0
+
+		frames = frames.filter(elem => {
+			if (elem.indexOf('find: ') === -1) {
+				return elem
+			}
+		})
+		frames.sort()
+		for (let frame of frames) {
+			execStr += `${frame} `
+			if ((i + 1) % (width * length) === 0 || i === frames.length - 1) {
+				pagePath = path.join(output, `./page_${pad(page)}.jpg`)
+				execStr += `\ -tile 1x${length} -geometry ${dim.w}x${dim.h}+${diff}+0 miff:- |\  \nmontage - -geometry +0+0 -tile ${width}x1 -density ${dim.dpi} "${pagePath}"`
+				console.log(execStr)
+				process.exit()
+				cmds.push(execStr)
+				execStr = 'montage '
+				page++
+			}
+			i++
+		}
+		jobs = cmds.map(cmd => {
+			return cb => {
+				exec(cmd, (err, std, ste) => {
+					if (err) {
+						return error(err)
+					}
+					console.log(`Created page of ${width}x${length} frames!`)
+					cb()
+				})
+			}
+		})
+		async.series(jobs, next)
+	})
 }
 
-var errorHandle = function (err) {
+function cleanup (next) {
+	console.log('Cleaning up...');
+	exec(`rm -r "${TMP}"`,  (err) => {
+		if (err) console.error(err)
+		if (next) next()
+	})
+}
+
+function pad (n) {
+	return ('00000' + n).slice(-5)
+}
+
+var error = function (err) {
 	if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){
 		console.error(err)
 	} else {
 		console.error('Error running program. Run in verbose mode for more info (-v,--verbose)')
 	}
 	process.exit(1)
-};
+}
 
 process.on('uncaughtException', err => {
-	errorHandle(err)
+	error(err)
 })
 
+//convert(process.argv[2], process.argv[3])
 
-if (typeof process.argv[2] === 'undefined') {
-	console.error('No path to video defined')
-	process.exit(1)
+//fix for nexe
+let args = [].concat(process.argv)
+if (args[1].indexOf('v2f.js') === -1) {
+	args.reverse()
+	args.push('node')
+	args.reverse()
 }
 
-if (typeof process.argv[3] === 'undefined') {
-	process.argv[3] = 300
-	console.log('Using default 300dpi')
-}
+cmd.arguments('<input> <output>')
+	.version('1.1.0')
+	.option('-i, --input <path>', 'Video source to print to film strip, anything that avconv can read')
+	.option('-o, --output <path>', 'Output directory, will print images on A4 standard paper file')
+	.option('-d, --dpi <dpi>', 'DPI output pages')
+	.option('-f, --film <gauge>', 'Choose film gauge: 16mm, super16, 35mm')
+	.option('-v, --verbose', 'Run in verbose mode')
+	.parse(args)
 
-convert(process.argv[2], process.argv[3])
-
-/*
-
-	INSTALLATION AND RUNNING
-
-*/
-
-//Install in this order to satisfy requirements: GCC required by MacPorts, etc.
-
-//Install Node         http://nodejs.org/dist/v0.10.22/node-v0.10.22.pkg
-//Install GCC          https://github.com/kennethreitz/osx-gcc-installer#option-1-downloading-pre-built-binaries
-//Install MacPorts     http://www.macports.org/install.php
-//Install ImageMagick  in terminal type "sudo port install ImageMagick"
-//Install avconv        -see below
-
-/*
-Download and unzip http://libav.org/releases/libav-9.6.tar.gz
-in terminal type "cd " and drag in unzipped folder and hit enter
-in terminal copy "sudo port install yasm zlib bzip2 faac lame speex libogg libvorbis libtheora libvpx x264 XviD openjpeg15 opencore-amr freetype" (without quotes) hit enter
-in terminal copy "./configure \ --enable-gpl --enable-libx264 --enable-libxvid \ --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb \ --enable-nonfree --enable-libfaac \ --enable-libmp3lame --enable-libspeex --enable-libvorbis --enable-libtheora --enable-libvpx \ --enable-libopenjpeg --enable-libfreetype --enable-doc --enable-gnutls --enable-shared" hit enter
-(if that gives errors just use "./configure" and hit enter)
-in terminal copy "make && sudo make install" hit enter
-
-	that will install it
-*/
-
-//run by going to terminal typing "node " dragging this script into the terminal, dragging the video into the terminal and adding a DPI value and hitting enter
-//the command should look something like this:
-//node /Users/stenzel/Desktop/video_to_page.js /Users/stenzel/Desktop/PaulRobeson/Paul\ Robeson\ discusses\ Othello.mp4 600
-
-
-//Get the absolute path of any file by dragging it into terminal and copying the results
-//Must be enclosed by ''
-//Will generate pages and frames in same folder as source video
+initialize(cmd)
\ No newline at end of file

From 65b89efa2eef49c64eaf3bc62f8b0533e46b4ce4 Mon Sep 17 00:00:00 2001
From: mmcw-dev <hi@mmcwilliams.com>
Date: Sun, 29 Oct 2017 23:56:35 -0400
Subject: [PATCH 10/10] Update project to version 1.1 for release.

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index bc91983..b080177 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "v2f",
-  "version": "1.0.1",
+  "version": "1.1.0",
   "description": "Turn a video into strips of precise 16mm-size stills",
   "main": "v2f.js",
   "scripts": {