mirror of https://github.com/rusefi/jzy3d-api.git
Allow configuring background color of GifExporter
This commit is contained in:
parent
394386df52
commit
9bb0e35f3c
|
@ -36,43 +36,52 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
||||||
protected AtomicInteger numberOfSkippedImages = new AtomicInteger(0);
|
protected AtomicInteger numberOfSkippedImages = new AtomicInteger(0);
|
||||||
protected AtomicInteger numberOfSavedImages = new AtomicInteger(0);
|
protected AtomicInteger numberOfSavedImages = new AtomicInteger(0);
|
||||||
|
|
||||||
protected int frameRateMs;
|
protected int frameDelayMs;
|
||||||
|
|
||||||
protected boolean debug = false;
|
protected boolean debug = false;
|
||||||
|
|
||||||
|
|
||||||
// protected int numberOfSubmittedImages = 0;
|
// protected int numberOfSubmittedImages = 0;
|
||||||
|
|
||||||
public AbstractImageExporter(int frameRateMs) {
|
public AbstractImageExporter(int frameDelayMs) {
|
||||||
this.frameRateMs = frameRateMs;
|
this.frameDelayMs = frameDelayMs;
|
||||||
this.timer = new TicToc();
|
this.timer = new TicToc();
|
||||||
this.executor = Executors.newSingleThreadExecutor();
|
this.executor = Executors.newSingleThreadExecutor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void export(BufferedImage image) {
|
public void export(BufferedImage image) {
|
||||||
// init timer
|
|
||||||
if (previousImage == null) {
|
if (previousImage == null) {
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// init timer
|
||||||
|
|
||||||
timer.tic();
|
timer.tic();
|
||||||
|
|
||||||
scheduleImageExport(image);
|
scheduleImageExport(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// or check time spent since image changed
|
|
||||||
else {
|
else {
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// ... or check time spent since image changed
|
||||||
|
|
||||||
timer.toc();
|
timer.toc();
|
||||||
double elapsed = timer.elapsedMilisecond();
|
double elapsed = timer.elapsedMilisecond();
|
||||||
// System.out.println("ELAPSED : " + elapsed);
|
int elapsedGifFrames = (int) Math.floor(elapsed / frameDelayMs);
|
||||||
int elapsedGifFrames = (int) Math.floor(elapsed / frameRateMs);
|
|
||||||
|
|
||||||
// Image pops too early
|
// ---------------------------------------------------------------
|
||||||
|
// Image pops too early, skip it
|
||||||
|
|
||||||
if (elapsedGifFrames == 0) {
|
if (elapsedGifFrames == 0) {
|
||||||
previousImage = image;
|
previousImage = image;
|
||||||
|
|
||||||
numberOfSkippedImages.incrementAndGet();
|
numberOfSkippedImages.incrementAndGet();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image is in [gifFrameRateMs; 2*gifFrameRateMs]
|
// ---------------------------------------------------------------
|
||||||
|
// Image is in [gifFrameRateMs; 2*gifFrameRateMs], schedule export
|
||||||
|
|
||||||
else if (elapsedGifFrames == 1) {
|
else if (elapsedGifFrames == 1) {
|
||||||
scheduleImageExport(previousImage);
|
scheduleImageExport(previousImage);
|
||||||
|
|
||||||
|
@ -80,7 +89,13 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
||||||
|
|
||||||
timer.tic();
|
timer.tic();
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// Time as elapsed for more than 1 image, schedule multiple export
|
||||||
|
// of the same image to fill the gap
|
||||||
|
|
||||||
|
else {
|
||||||
for (int i = 0; i < elapsedGifFrames; i++) {
|
for (int i = 0; i < elapsedGifFrames; i++) {
|
||||||
scheduleImageExport(previousImage);
|
scheduleImageExport(previousImage);
|
||||||
}
|
}
|
||||||
|
@ -132,21 +147,12 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (InterruptedException e1) {
|
} catch (InterruptedException e1) {
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for the process to finish and return when done.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* public boolean awaitTermination() { return terminate(0, null); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
protected void scheduleImageExport(BufferedImage image) {
|
protected void scheduleImageExport(BufferedImage image) {
|
||||||
scheduleImageExport(image, false);
|
scheduleImageExport(image, false);
|
||||||
}
|
}
|
||||||
|
@ -160,8 +166,6 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
numberOfPendingImages.incrementAndGet();
|
|
||||||
|
|
||||||
// System.out.println("Adding image to GIF (pending tasks " + pendingTasks.get() + ")");
|
// System.out.println("Adding image to GIF (pending tasks " + pendingTasks.get() + ")");
|
||||||
// pendingTasks.incrementAndGet();
|
// pendingTasks.incrementAndGet();
|
||||||
|
|
||||||
|
@ -179,7 +183,6 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
||||||
catch(Exception e) {
|
catch(Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
numberOfPendingImages.decrementAndGet();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,10 +205,6 @@ public abstract class AbstractImageExporter implements AWTImageExporter {
|
||||||
return numberSubmittedImages;
|
return numberSubmittedImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtomicInteger getNumberOfPendingImages() {
|
|
||||||
return numberOfPendingImages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AtomicInteger getNumberOfSkippedImages() {
|
public AtomicInteger getNumberOfSkippedImages() {
|
||||||
return numberOfSkippedImages;
|
return numberOfSkippedImages;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import java.awt.Graphics2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.jzy3d.colors.AWTColor;
|
||||||
|
import org.jzy3d.colors.Color;
|
||||||
import org.jzy3d.io.AWTImageExporter;
|
import org.jzy3d.io.AWTImageExporter;
|
||||||
import org.jzy3d.io.AbstractImageExporter;
|
import org.jzy3d.io.AbstractImageExporter;
|
||||||
import org.jzy3d.maths.TicToc;
|
import org.jzy3d.maths.TicToc;
|
||||||
|
@ -23,7 +25,8 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
||||||
protected File outputFile;
|
protected File outputFile;
|
||||||
protected AnimatedGifEncoder encoder;
|
protected AnimatedGifEncoder encoder;
|
||||||
|
|
||||||
protected boolean applyWhiteBackground = true;
|
protected Color backgroundColor = null;
|
||||||
|
// protected boolean applyWhiteBackground = true;
|
||||||
|
|
||||||
protected TicToc timer = new TicToc();
|
protected TicToc timer = new TicToc();
|
||||||
|
|
||||||
|
@ -31,8 +34,8 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
||||||
this(outputFile, DEFAULT_FRAME_RATE_MS); // 1 frame per sec
|
this(outputFile, DEFAULT_FRAME_RATE_MS); // 1 frame per sec
|
||||||
}
|
}
|
||||||
|
|
||||||
public GifExporter(File outputFile, int gifFrameRateMs) {
|
public GifExporter(File outputFile, int gifFrameDelayMs) {
|
||||||
super(gifFrameRateMs);
|
super(gifFrameDelayMs);
|
||||||
|
|
||||||
this.outputFile = outputFile;
|
this.outputFile = outputFile;
|
||||||
|
|
||||||
|
@ -42,7 +45,7 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
||||||
|
|
||||||
this.encoder = new AnimatedGifEncoder();
|
this.encoder = new AnimatedGifEncoder();
|
||||||
this.encoder.start(outputFile.getAbsolutePath());
|
this.encoder.start(outputFile.getAbsolutePath());
|
||||||
this.encoder.setDelay(gifFrameRateMs);
|
this.encoder.setDelay(gifFrameDelayMs);
|
||||||
this.encoder.setRepeat(1000);
|
this.encoder.setRepeat(1000);
|
||||||
this.encoder.setQuality(8);
|
this.encoder.setQuality(8);
|
||||||
|
|
||||||
|
@ -69,17 +72,24 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
||||||
+ timer.elapsedSecond());
|
+ timer.elapsedSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applyWhiteBackground) {
|
// If a background color is defined, create an image with this background color before export
|
||||||
|
if (backgroundColor!=null) {
|
||||||
|
java.awt.Color awtColor = AWTColor.toAWT(backgroundColor);
|
||||||
|
|
||||||
BufferedImage imageWithBg =
|
BufferedImage imageWithBg =
|
||||||
new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
|
new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
|
||||||
|
|
||||||
Graphics2D g = (Graphics2D) imageWithBg.getGraphics();
|
Graphics2D g = (Graphics2D) imageWithBg.getGraphics();
|
||||||
|
g.setColor(awtColor);
|
||||||
g.fillRect(0, 0, image.getWidth(), image.getHeight());
|
g.fillRect(0, 0, image.getWidth(), image.getHeight());
|
||||||
g.drawImage(image, 0, 0, null);
|
g.drawImage(image, 0, 0, null);
|
||||||
g.dispose();
|
g.dispose();
|
||||||
encoder.addFrame(imageWithBg);
|
|
||||||
} else {
|
image = imageWithBg;
|
||||||
encoder.addFrame(image);
|
}
|
||||||
}
|
|
||||||
|
// Do export as animated gif frame
|
||||||
|
encoder.addFrame(image);
|
||||||
|
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
@ -88,10 +98,12 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
||||||
+ timer.elapsedSecond());
|
+ timer.elapsedSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close output if this is our last image
|
||||||
if (isLastImage) {
|
if (isLastImage) {
|
||||||
closeOutput();
|
closeOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update counters to monitor task progress
|
||||||
numberOfSavedImages.incrementAndGet();
|
numberOfSavedImages.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,5 +136,15 @@ public class GifExporter extends AbstractImageExporter implements AWTImageExport
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color getBackgroundColor() {
|
||||||
|
return backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBackgroundColor(Color backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package org.jzy3d.chart;
|
package org.jzy3d.chart;
|
||||||
|
|
||||||
public interface IAnimator {
|
public interface IAnimator {
|
||||||
|
public static final int DEFAULT_FRAME_PER_SECOND = 10;
|
||||||
|
|
||||||
public void start();
|
public void start();
|
||||||
|
|
||||||
public void stop();
|
public void stop();
|
||||||
|
|
|
@ -3,7 +3,7 @@ package org.jzy3d.chart;
|
||||||
import org.jzy3d.plot3d.rendering.canvas.EmulGLCanvas;
|
import org.jzy3d.plot3d.rendering.canvas.EmulGLCanvas;
|
||||||
|
|
||||||
public class EmulGLAnimator implements IAnimator {
|
public class EmulGLAnimator implements IAnimator {
|
||||||
private static final int RENDERING_LOOP_PAUSE = 100;
|
private static final int RENDERING_LOOP_PAUSE = 1000/DEFAULT_FRAME_PER_SECOND;
|
||||||
protected EmulGLCanvas canvas;
|
protected EmulGLCanvas canvas;
|
||||||
protected Thread t;
|
protected Thread t;
|
||||||
protected boolean loop = false;
|
protected boolean loop = false;
|
||||||
|
|
|
@ -6,7 +6,6 @@ import com.jogamp.opengl.util.FPSAnimator;
|
||||||
public class NativeAnimator implements IAnimator {
|
public class NativeAnimator implements IAnimator {
|
||||||
protected com.jogamp.opengl.util.AnimatorBase animator;
|
protected com.jogamp.opengl.util.AnimatorBase animator;
|
||||||
|
|
||||||
public static final int DEFAULT_FRAME_PER_SECOND = 10;
|
|
||||||
|
|
||||||
public NativeAnimator(GLAutoDrawable canvas) {
|
public NativeAnimator(GLAutoDrawable canvas) {
|
||||||
// animator = new com.jogamp.opengl.util.Animator(canvas);
|
// animator = new com.jogamp.opengl.util.Animator(canvas);
|
||||||
|
|
Loading…
Reference in New Issue