diff --git a/build/shared/tools/MovieMaker/src/processing/app/tools/MovieMaker.java b/build/shared/tools/MovieMaker/src/processing/app/tools/MovieMaker.java
index a64a6d35d..23c10a51d 100644
--- a/build/shared/tools/MovieMaker/src/processing/app/tools/MovieMaker.java
+++ b/build/shared/tools/MovieMaker/src/processing/app/tools/MovieMaker.java
@@ -35,11 +35,11 @@ import ch.randelshofer.media.quicktime.QuickTimeWriter;
* Hacked from Werner Randelshofer's QuickTimeWriter demo. The original version
* can be found here.
*
- * A more up-to-date version of the project seems to be
+ * A more up-to-date version of the project is
* here.
- * If someone would like to help us update the encoder, that'd be great.
+ * Problem is, it's too big, so we don't want to merge it into our code.
*
- * Broken out as a separate project because the license (CC) probably isn't
+ * Broken out as a separate project because the license (CC) probably isn't
* compatible with the rest of Processing and we don't want any confusion.
*
* Added JAI ImageIO to support lots of other image file formats [131008].
@@ -52,7 +52,7 @@ import ch.randelshofer.media.quicktime.QuickTimeWriter;
*
The dialog box is super ugly. It's a hacked up version of the previous
* interface, but I'm too scared to pull that GUI layout code apart.
* The 'None' compressor seems to have bugs, so just disabled it instead.
- * The 'pass through' option seems to be broken, so it's been removed.
+ * The 'pass through' option seems to be broken, so it's been removed.
* In its place is an option to use the same width/height as the originals.
* When this new 'pass through' is set, there's some nastiness with how
* the 'final' width/height variables are passed to the movie maker.
@@ -228,10 +228,10 @@ public class MovieMaker extends JFrame implements Tool {
chooseImageFolderButton.setText(Language.text("movie_maker.choose_button"));
//chooseImageFolderButton.addActionListener(formListener);
chooseImageFolderButton.addActionListener(new ActionListener() {
-
+
@Override
public void actionPerformed(ActionEvent e) {
- Chooser.selectFolder(MovieMaker.this,
+ Chooser.selectFolder(MovieMaker.this,
Language.text("movie_maker.select_image_folder"),
new File(imageFolderField.getText()),
new Chooser.Callback() {
@@ -249,10 +249,10 @@ public class MovieMaker extends JFrame implements Tool {
chooseSoundFileButton.setText(Language.text("movie_maker.choose_button"));
//chooseSoundFileButton.addActionListener(formListener);
chooseSoundFileButton.addActionListener(new ActionListener() {
-
+
@Override
public void actionPerformed(ActionEvent e) {
- Chooser.selectInput(MovieMaker.this,
+ Chooser.selectInput(MovieMaker.this,
Language.text("movie_maker.select_sound_file"),
new File(soundFileField.getText()),
new Chooser.Callback() {
@@ -269,14 +269,14 @@ public class MovieMaker extends JFrame implements Tool {
createMovieButton.setText(Language.text("movie_maker.create_movie_button"));
// createMovieButton.addActionListener(formListener);
createMovieButton.addActionListener(new ActionListener() {
-
+
@Override
public void actionPerformed(ActionEvent e) {
String lastPath = prefs.get("movie.outputFile", null);
File lastFile = lastPath == null ? null : new File(lastPath);
- Chooser.selectOutput(MovieMaker.this,
+ Chooser.selectOutput(MovieMaker.this,
Language.text("movie_maker.save_dialog_prompt"),
- lastFile,
+ lastFile,
new Chooser.Callback() {
@Override
void select(File file) {
@@ -295,7 +295,7 @@ public class MovieMaker extends JFrame implements Tool {
// public void run() {
// createMovie(target);
// }
-//
+//
// });
}
}
@@ -616,16 +616,23 @@ public class MovieMaker extends JFrame implements Tool {
Arrays.sort(imgFiles);
}
- // Check on first image, if we can actually do pass through
+ // Get the width and height if we're preserving size.
+ // Nullify bad Files so we don't get errors twice.
if (originalSize) {
- BufferedImage temp = readImage(imgFiles[0]);
- if (temp == null) {
- return new RuntimeException(Language.interpolate("movie_maker.error.cant_read", imgFiles[0].getAbsolutePath()));
- }
- width = temp.getWidth();
- height = temp.getHeight();
- if (width <= 0 || height <= 0) {
- return new RuntimeException(Language.interpolate("movie_maker.error.cant_read_maybe_bad", imgFiles[0].getName()));
+ for (int i = 0; true; ++i) {
+ // No images at all? No video then.
+ if (i >= imgFiles.length) {
+ throw new RuntimeException(Language.text("movie_maker.error.no_images_found"));
+ }
+
+ BufferedImage temp = readImage(imgFiles[i]);
+ if (temp == null) {
+ imgFiles[i] = null;
+ } else {
+ width = temp.getWidth();
+ height = temp.getHeight();
+ break;
+ }
}
}
@@ -642,7 +649,7 @@ public class MovieMaker extends JFrame implements Tool {
writeAudioOnly(movieFile, soundFile, streaming);
}
return null;
-
+
} catch (Throwable t) {
return t;
}
@@ -673,50 +680,89 @@ public class MovieMaker extends JFrame implements Tool {
}//GEN-LAST:event_createMovie
- /**
+ /**
* Read an image from a file. ImageIcon doesn't don't do well with some file
* types, so we use ImageIO. ImageIO doesn't handle TGA files created by
* Processing, so this calls our own loadImageTGA().
+ *
Prints errors itself.
+ * @return null on error; image only if okay.
*/
- private BufferedImage readImage(File file) throws IOException {
- // Make sure that we're using a ClassLoader that's aware of the ImageIO jar
- //Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
- //BufferedImage image = ImageIO.read(file);
- // rewritten to switch back to the default loader
- Thread current = Thread.currentThread();
- ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
- current.setContextClassLoader(getClass().getClassLoader());
- BufferedImage image = ImageIO.read(file);
- current.setContextClassLoader(origLoader);
+ private BufferedImage readImage(File file) {
+ try {
+ // Make sure that we're using a ClassLoader that's aware of the ImageIO jar
+ //Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ //BufferedImage image = ImageIO.read(file);
+ // rewritten to switch back to the default loader
+ Thread current = Thread.currentThread();
+ ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
+ current.setContextClassLoader(getClass().getClassLoader());
- /*
- String[] loadImageFormats = ImageIO.getReaderFormatNames();
- if (loadImageFormats != null) {
- for (String format : loadImageFormats) {
- System.out.println(format);
+ BufferedImage image;
+ try {
+ image = ImageIO.read(file);
+ } catch (IOException e) {
+ System.err.println(Language.interpolate("movie_maker.error.cant_read",
+ file.getAbsolutePath()));
+ return null;
}
- }
- */
- if (image == null) {
- String path = file.getAbsolutePath();
- String pathLower = path.toLowerCase();
- // Might be an incompatible TGA or TIFF created by Processing
- if (pathLower.endsWith(".tga")) {
- return loadImageTGA(file);
-
- } else if (pathLower.endsWith(".tif") || pathLower.endsWith(".tiff")) {
- throw new IOException(Language.text("movie_maker.error.avoid_tiff"));
+ current.setContextClassLoader(origLoader);
+
+ /*
+ String[] loadImageFormats = ImageIO.getReaderFormatNames();
+ if (loadImageFormats != null) {
+ for (String format : loadImageFormats) {
+ System.out.println(format);
+ }
}
+ */
+
+ if (image == null) {
+ String path = file.getAbsolutePath();
+ String pathLower = path.toLowerCase();
+ // Might be an incompatible TGA or TIFF created by Processing
+ if (pathLower.endsWith(".tga")) {
+ try {
+ return loadImageTGA(file);
+ } catch (IOException e) {
+ System.err.println(Language.interpolate("movie_maker.error.cant_read",
+ file.getAbsolutePath()));
+ return null;
+ }
+
+ } else if (pathLower.endsWith(".tif") || pathLower.endsWith(".tiff")) {
+ System.err.println(Language.interpolate("movie_maker.error.cant_read",
+ file.getAbsolutePath()) + " " +
+ Language.text("movie_maker.error.avoid_tiff"));
+ return null;
+
+ } else {
+ System.err.println(Language.interpolate("movie_maker.error.cant_read",
+ file.getAbsolutePath()));
+ return null;
+ }
+
+ } else {
+ if (image.getWidth() <= 0 || image.getHeight() <= 0) {
+ System.err.println(Language.interpolate("movie_maker.error.cant_read_maybe_bad",
+ file.getAbsolutePath()));
+ return null;
+ }
+ }
+ return image;
+
+ // Catch-all is sometimes needed.
+ } catch (RuntimeException e) {
+ System.err.println(Language.interpolate("movie_maker.error.cant_read", file.getAbsolutePath()));
+ return null;
}
- return image;
}
-
+
/** variable frame rate. */
private void writeVideoOnlyVFR(File movieFile, File[] imgFiles, int width, int height, double fps, QuickTimeWriter.VideoFormat videoFormat, /*boolean passThrough,*/ String streaming) throws IOException {
File tmpFile = streaming.equals("none") ? movieFile : new File(movieFile.getPath() + ".tmp");
- ProgressMonitor p = new ProgressMonitor(MovieMaker.this,
+ ProgressMonitor p = new ProgressMonitor(MovieMaker.this,
Language.interpolate("movie_maker.progress.creating_file_name", movieFile.getName()),
Language.text("movie_maker.progress.creating_output_file"),
0, imgFiles.length);
@@ -746,6 +792,8 @@ public class MovieMaker extends JFrame implements Tool {
int prevImgDuration = 0;
for (int i = 0; i < imgFiles.length && !p.isCanceled(); i++) {
File f = imgFiles[i];
+ if (f == null) continue;
+
p.setNote(Language.interpolate("movie_maker.progress.processing", f.getName()));
p.setProgress(i);
@@ -755,6 +803,8 @@ public class MovieMaker extends JFrame implements Tool {
} else {
//BufferedImage fImg = ImageIO.read(f);
BufferedImage fImg = readImage(f);
+ if (fImg == null) continue;
+
g.drawImage(fImg, 0, 0, width, height, null);
if (i != 0 && Arrays.equals(data, prevData)) {
prevImgDuration += duration;
@@ -871,6 +921,7 @@ public class MovieMaker extends JFrame implements Tool {
private void writeVideoAndAudio(File movieFile, File[] imgFiles, File audioFile,
int width, int height, double fps, QuickTimeWriter.VideoFormat videoFormat,
/*boolean passThrough,*/ String streaming) throws IOException {
+
File tmpFile = streaming.equals("none") ? movieFile : new File(movieFile.getPath() + ".tmp");
ProgressMonitor p = new ProgressMonitor(MovieMaker.this,
Language.interpolate("movie_maker.progress.creating_file_name", movieFile.getName()),
@@ -949,24 +1000,25 @@ public class MovieMaker extends JFrame implements Tool {
}
// Advance video to movie time
- while (imgIndex < imgFiles.length && qtOut.getTrackDuration(1) < movieTime) {
+ for (; imgIndex < imgFiles.length && qtOut.getTrackDuration(1) < movieTime; ++imgIndex) {
// catch up with video time
p.setProgress(imgIndex);
- p.setNote(Language.interpolate("movie_maker.progress.processing", imgFiles[imgIndex].getName()));
+ File f = imgFiles[imgIndex];
+ if (f == null) continue;
+
+ p.setNote(Language.interpolate("movie_maker.progress.processing", f.getName()));
//if (passThrough) {
if (false) {
- qtOut.writeSample(1, imgFiles[imgIndex], vsDuration);
+ qtOut.writeSample(1, f, vsDuration);
} else {
//BufferedImage fImg = ImageIO.read(imgFiles[imgIndex]);
- BufferedImage fImg = readImage(imgFiles[imgIndex]);
- if (fImg == null) {
- continue;
- }
+ BufferedImage fImg = readImage(f);
+ if (fImg == null) continue;
+
g.drawImage(fImg, 0, 0, width, height, null);
fImg.flush();
qtOut.writeFrame(1, imgBuffer, vsDuration);
}
- ++imgIndex;
}
}
if (streaming.equals("fastStart")) {
@@ -999,14 +1051,14 @@ public class MovieMaker extends JFrame implements Tool {
}
}
-
+
/**
- * Targa image loader for RLE-compressed TGA files.
- * Code taken from PApplet, any changes here should lead to updates there.
+ * Targa image loader for RLE-compressed TGA files.
+ * Code taken from PApplet, any changes here should lead to updates there.
*/
static private BufferedImage loadImageTGA(File file) throws IOException {
InputStream is = new FileInputStream(file);
-
+
try {
byte header[] = new byte[18];
int offset = 0;
@@ -1168,7 +1220,7 @@ public class MovieMaker extends JFrame implements Tool {
break;
case ARGB:
for (int i = 0; i < num; i++) {
- pixels[index++] = is.read() |
+ pixels[index++] = is.read() |
(is.read() << 8) | (is.read() << 16) | (is.read() << 24);
}
break;
@@ -1193,13 +1245,13 @@ public class MovieMaker extends JFrame implements Tool {
WritableRaster wr = image.getRaster();
wr.setDataElements(0, 0, w, h, pixels);
return image;
-
+
} finally {
is.close();
}
}
-
-
+
+
/**
* @param args the command line arguments
*/
@@ -1214,7 +1266,7 @@ public class MovieMaker extends JFrame implements Tool {
}
});
}
-
+
private JLabel aboutLabel;
private JButton chooseImageFolderButton;