mirror of https://github.com/rusefi/jzy3d-api.git
improve gif export
This commit is contained in:
parent
787e9c27be
commit
ec1fb2444d
|
@ -3,6 +3,7 @@ package org.jzy3d.io;
|
|||
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -152,11 +153,13 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
|||
|
||||
protected void scheduleImageExport(BufferedImage image, boolean isLastImage) {
|
||||
// try {
|
||||
|
||||
numberSubmittedImages.incrementAndGet();
|
||||
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
numberSubmittedImages.incrementAndGet();
|
||||
numberOfPendingImages.incrementAndGet();
|
||||
|
||||
// System.out.println("Adding image to GIF (pending tasks " + pendingTasks.get() + ")");
|
||||
|
@ -170,8 +173,12 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
|||
* image.getHeight()-20); graphics.dispose();
|
||||
*/
|
||||
|
||||
doAddFrameByRunnable(image, isLastImage);
|
||||
|
||||
try {
|
||||
doAddFrameByRunnable(image, isLastImage);
|
||||
}
|
||||
catch(Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
numberOfPendingImages.decrementAndGet();
|
||||
|
||||
}
|
||||
|
@ -183,9 +190,9 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
|||
*/
|
||||
}
|
||||
|
||||
protected abstract void doAddFrameByRunnable(BufferedImage image, boolean isLastImage);
|
||||
protected abstract void doAddFrameByRunnable(BufferedImage image, boolean isLastImage) throws IOException;
|
||||
|
||||
protected abstract void closeOutput();
|
||||
protected abstract void closeOutput() throws IOException;
|
||||
|
||||
public TicToc getTimer() {
|
||||
return timer;
|
||||
|
|
|
@ -176,21 +176,23 @@ public class AnimatedGifEncoder {
|
|||
/**
|
||||
* Flushes any pending data and closes output file. If writing to an
|
||||
* OutputStream, the stream is not closed.
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean finish() {
|
||||
public boolean finish() throws IOException {
|
||||
if (!started)
|
||||
return false;
|
||||
boolean ok = true;
|
||||
started = false;
|
||||
try {
|
||||
|
||||
//try {
|
||||
out.write(0x3b); // gif trailer
|
||||
out.flush();
|
||||
if (closeStream) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
ok = false;
|
||||
}
|
||||
//} catch (IOException e) {
|
||||
// ok = false;
|
||||
//}
|
||||
|
||||
// reset for subsequent use
|
||||
transIndex = 0;
|
||||
|
|
|
@ -1,16 +1,30 @@
|
|||
package org.jzy3d.io.gif;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.io.IOException;
|
||||
import org.jzy3d.io.AWTImageExporter;
|
||||
import org.jzy3d.io.AbstractImageExporter;
|
||||
import org.jzy3d.maths.TicToc;
|
||||
import org.jzy3d.maths.Utils;
|
||||
|
||||
/**
|
||||
* An image exporter able to create a gif animation out of frame exported by a renderer.
|
||||
*
|
||||
* Delay between frames should remain superior to 50 miliseconds.
|
||||
*
|
||||
* @see {@link AbstractImageExporter}
|
||||
*
|
||||
* @author Martin Pernollet
|
||||
*
|
||||
*/
|
||||
public class GifExporter extends AbstractImageExporter implements AWTImageExporter {
|
||||
protected File outputFile;
|
||||
protected AnimatedGifEncoder encoder;
|
||||
|
||||
protected boolean applyWhiteBackground = true;
|
||||
|
||||
protected TicToc timer = new TicToc();
|
||||
|
||||
public GifExporter(File outputFile) {
|
||||
|
@ -21,6 +35,10 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
|||
super(gifFrameRateMs);
|
||||
|
||||
this.outputFile = outputFile;
|
||||
|
||||
if(!outputFile.getParentFile().exists()) {
|
||||
outputFile.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
this.encoder = new AnimatedGifEncoder();
|
||||
this.encoder.start(outputFile.getAbsolutePath());
|
||||
|
@ -32,14 +50,25 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAddFrameByRunnable(BufferedImage image, boolean isLastImage) {
|
||||
protected void doAddFrameByRunnable(BufferedImage image, boolean isLastImage) throws IOException {
|
||||
|
||||
if (debug) {
|
||||
timer.toc();
|
||||
System.out.println("GifExporter : Adding image to GIF " + numberSubmittedImages.get() + " at " + timer.elapsedSecond());
|
||||
}
|
||||
|
||||
encoder.addFrame(image);
|
||||
if(applyWhiteBackground) {
|
||||
BufferedImage imageWithBg = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
|
||||
Graphics2D g = (Graphics2D)imageWithBg.getGraphics();
|
||||
g.fillRect(0, 0, image.getWidth(), image.getHeight());
|
||||
g.drawImage(image, 0, 0, null);
|
||||
g.dispose();
|
||||
encoder.addFrame(imageWithBg);
|
||||
}
|
||||
else {
|
||||
encoder.addFrame(image);
|
||||
}
|
||||
|
||||
|
||||
if (debug) {
|
||||
timer.toc();
|
||||
|
@ -54,7 +83,7 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void closeOutput() {
|
||||
protected void closeOutput() throws IOException {
|
||||
encoder.finish();
|
||||
|
||||
if (debug)
|
||||
|
@ -65,6 +94,21 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
|||
public File getOutputFile() {
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
public double progress() {
|
||||
int submit = getNumberSubmittedImages().intValue();
|
||||
int saved = getNumberOfSavedImages().intValue();
|
||||
return 100f * saved / submit;
|
||||
}
|
||||
|
||||
public void progressToConsole() {
|
||||
int submit = getNumberSubmittedImages().intValue();
|
||||
int saved = getNumberOfSavedImages().intValue();
|
||||
double progress = 100f * saved / submit;
|
||||
|
||||
System.out.println(Utils.num2str(progress, 3) + " % progress : " + saved + " saved " + submit + " submit");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.jzy3d.painters.IPainter;
|
|||
* @author Martin Pernollet
|
||||
*/
|
||||
public class Rotate implements Transformer {
|
||||
protected float angle;
|
||||
protected Coord3d rotate;
|
||||
|
||||
/**
|
||||
* Initialize a Rotation of angle degrees around the vector (x,y,z)
|
||||
|
@ -62,7 +64,4 @@ public class Rotate implements Transformer {
|
|||
public void setRotate(Coord3d rotate) {
|
||||
this.rotate = rotate;
|
||||
}
|
||||
|
||||
private float angle;
|
||||
private Coord3d rotate;
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@ import com.jogamp.opengl.util.FPSAnimator;
|
|||
|
||||
public class NativeAnimator implements IAnimator {
|
||||
protected com.jogamp.opengl.util.AnimatorBase animator;
|
||||
|
||||
public static final int DEFAULT_FRAME_PER_SECOND = 10;
|
||||
|
||||
public NativeAnimator(GLAutoDrawable canvas) {
|
||||
// animator = new com.jogamp.opengl.util.Animator(canvas);
|
||||
animator = new FPSAnimator(canvas, 10);
|
||||
animator = new FPSAnimator(canvas, DEFAULT_FRAME_PER_SECOND);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,7 +23,11 @@ public class NativeAnimator implements IAnimator {
|
|||
animator.stop();
|
||||
}
|
||||
|
||||
public FPSAnimator getAnimator() {
|
||||
return (FPSAnimator)animator;
|
||||
public com.jogamp.opengl.util.AnimatorBase getAnimator() {
|
||||
return animator;
|
||||
}
|
||||
|
||||
public void setAnimator(com.jogamp.opengl.util.Animator animator) {
|
||||
this.animator = animator;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue