I'd like to use Processing to render a visualization on the server side (headlessly, with no GUI ). The Processing sketch is static (ie does not animate), so I only need to grab the first frame, and I'd like to serve this result out to the users of our web application on-demand.
I've searched around a bit on the processing.org forums and it's been suggested that Processing is not intended to be launched headlessly. The only hack I've seen to do it is one involving launching a headless X11 display:
Xvfb :2 &
export DISPLAY=":2"
./myapp
killall -9 Xvfb
.. Which is not going to work for us as we'd like to have a pure-Java solution and can't always guarantee an X renderer on the server-side.
How do I do this in pure Java?
Xvfb is likely to be faster than a java renderer, and a hardware-accelerated X server will be the fastest by a large margin, but if you want a 'pure' java solution you could try the Pure Java AWT Toolkit .
EDIT: Here's a boot command line example lifted from here :
java -Xbootclasspath:JDK/jre/lib/rt.jar:LIB/pja.jar -Dawt.toolkit=com.eteks.awt.PJAToolkit -Djava.awt.graphicsenv=com.eteks.java2d.PJAGraphicsEnvironment -Djava.awt.fonts=JDK/jre/lib/fonts mainclassname args
Create a standard headless Java app, create a PGraphics object in it(1) and perform all of your drawing operations on that. Then save the PGraphics object to disk as an image file using .save().
1 You may need to obtain this from a PApplet, I'm not sure if you can create it directly.
The code will look mode or less like this:
PApplet applet = new PApplet();
PGraphics g = applet.createGraphics(200, 400, PApplet.JAVA2D) // same params as size()
g.beginDraw();
g.ellipse // ... etc, your drawing goes here
g.endDraw();
g.save("filename.png");
The solution from Ollie Glass ceased to work because the constructor of PApplet/Applet
checks whether the environment is headless or not, ie -Djava.awt.headless=true
.
So there is no way of creating a PApplet object in the first place.
Instead, create your PGraphics
directly. For instance, to draw everything into a pdf
PGraphics pdf = new PGraphicsPDF();
pdf.setPrimary(false);
pdf.setPath(filename);
pdf.setSize(sizeX, sizeY);
// pdf.setParent(new PApplet()); This is intentionally NOT called.
pdf.beginDraw();
// draw everything
pdf.dispose();
pdf.endDraw();
Adding text will still throw an exception since the underlying PGraphics
calls its parent
(the PApplet
) for some helper methods. However, this hasn't been set because we are not allowed to create a PApplet
in the first place.
A solution is to get rid of these function calls is creating you own version of PGraphicsPDF
. For example
class MyPGraphicsPDF extends PGraphicsPDF{
@Override
public float textAscent() {
if (textFont == null) {
defaultFontOrDeath("textAscent");
}
Font font = (Font) textFont.getNative();
//if (font != null && (textFont.isStream() || hints[ENABLE_NATIVE_FONTS])) {
if (font != null) {
FontMetrics metrics = this.getFontMetrics(font);
return metrics.getAscent();
}
return super.textAscent();
}
@Override
public float textDescent() {
if (textFont == null) {
defaultFontOrDeath("textDescent");
}
Font font = (Font) textFont.getNative();
//if (font != null && (textFont.isStream() || hints[ENABLE_NATIVE_FONTS])) {
if (font != null) {
FontMetrics metrics = this.getFontMetrics(font);
return metrics.getDescent();
}
return super.textDescent();
}
public FontMetrics getFontMetrics(Font font) {
FontManager fm = FontManagerFactory.getInstance();
return sun.font.FontDesignMetrics.getMetrics(font);
}
}
textAscent()
and textDescent()
are copies of the code from PGraphics
with the change of not calling getFontMetrics(Font font)
from the non-existing parent
PApplet
. Instead both redirect to the third method that reimplements the missing helper method of PApplet
as a slightly shorter version of java.awt.Component.getFontMetrics(Font font)
.
Hope that helps.
Would be nice to have a native headless version of processing when explicitely calling for a file as drawing board.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.