Frederic Pariente wrote:
>
> Dear all,
>
> I found in the archive many threads on how capturing the image of an canvas3d
> using readRaster(). I tried with no success: nullPointerException, deadlocks,
> etc. Can a generous soul send me some code that shows how it works (not only the
> overriden postSwap method but also the calling method)?
>
> My goal is to work around the JInternalFrame/Canvas3D problem, switching b/w a
> still image and the canvas3d when selecting/deactivating the internal frame. I'm
> sure someone has done it out there.
>
Hi - what follows is probably more than you need, and duplicates other
code fragments
people have posted, but it's the whole thing (except PickText3DGeometry,
which is one of
the example programs that comes with J3D) - it should work with other
examples,
etc., I would think; I use it a bit...
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;
import javax.media.j3d.BranchGroup;
import java.awt.*;
import java.awt.event.*;
import sd.atc.d3.TimeCanvas3D;
import sd.atc.d3.XRendererAdapter;
public class XPickText3DGeometry extends PickText3DGeometry {
TimeCanvas3D c; // times, saves images to disk, etc.
public XPickText3DGeometry() {
setLayout(new BorderLayout());
c = new TimeCanvas3D(null,new XRendererAdapter());
c.setAutoStats (10000);
add("Center", c);
Panel pButtons = new Panel();
add ("South", pButtons);
Button bPrint = new Button ("save");
bPrint.addActionListener (new ActionListener () {
int i = 0;
public void actionPerformed (ActionEvent e) {
c.saveFrame ("c:\\images\\savedframes\\x"+i+".jpg");
i++;
}
});
pButtons.add(bPrint);
SimpleUniverse u = new SimpleUniverse(c);
BranchGroup scene = createSceneGraph(c);
// This will move the ViewPlatform back a bit so the
// objects in the scene can be viewed.
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new XPickText3DGeometry(), 700, 500);
}
}
The idea is, you can move the things around until you like them, then
save the
current screen image to a disk file (method TimeCanvas3D.saveFrame).
For your purposes, you probably just want to get the image (not save to
disk).
Method TimeCanvas3D.getCanvasImage does this.
(XRenderer, XRendererAdapter are just to get more hooks.)
So here's the rest:
// XRenderer
package sd.atc.d3;
import java.awt.*;
import javax.media.j3d.*;
public interface XRenderer {
public void preRender (GraphicsContext3D gc);
public void postRender (GraphicsContext3D gc);
public void postSwap (GraphicsContext3D gc);
public void renderField(int fieldDesc,GraphicsContext3D gc );
}
//XRendererAdapter
package sd.atc.d3;
import java.awt.*;
import javax.media.j3d.*;
import sd.atc.d3.XRenderer;
public class XRendererAdapter implements XRenderer {
public void preRender (GraphicsContext3D gc) {
}
public void postRender (GraphicsContext3D gc) {
}
public void postSwap (GraphicsContext3D gc) {
}
public void renderField(int fieldDesc,GraphicsContext3D gc ) {
}
}
//TimeCanvas3D
package sd.atc.d3;
import java.io.*;
import java.awt.*;
import java.text.*;
import java.awt.image.BufferedImage;
import javax.media.j3d.*;
import com.sun.image.codec.jpeg.*;
import sun.awt.image.codec.*;
import sd.atc.d3.XRenderer;
import sd.atc.d3.XRendererAdapter;
public class TimeCanvas3D extends Canvas3D {
GraphicsContext3D gc;
XRenderer renderer;
boolean saveFrame = false;
NumberFormat nf;
public TimeCanvas3D (GraphicsConfiguration g) {
this (g,null);
}
public TimeCanvas3D (GraphicsConfiguration g, XRenderer xr) {
super(g);
renderer = xr;
gc = getGraphicsContext3D();
nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);
}
String saveFileName = null;
public void saveFrame(String fileName) {
saveFileName = fileName;
saveFrame = true;
}
public void saveFrame() {
saveFrame = true;
}
double t1, // system time when 1st render is called
t2;
int renderCt = 0,
renderInx = 0;
double[] last20 = new double[20];
public double[] getLast20 () { return last20; }
public double getRenderStartTime () { return t1; }
public int getRenderCt () { return renderCt; }
public int getRenderInx () { return renderInx; }
public void resetRenderCt () { renderCt = 0; }
Thread tStats = null;
boolean tStatsStop = false;
public void setAutoStats (final int i) {
if (i < 1) { // don't do it...
if (tStats == null)
return;
if (tStats.isAlive()) {
tStatsStop = true;
// tStats.stop();
return;
}
return;
}
if (tStats != null && tStats.isAlive())
tStatsStop = true;
// tStats.stop();
tStats = new Thread () {
public void run () {
for (;;) {
try {sleep(i);} catch (Exception e) {;}
if (renderCt > 0)
System.out.println (getStats());
if (tStatsStop) {
tStatsStop = false;
return;
}
}
}
};
tStats.start();
}
public float getFPS () {
double[] times = getLast20();
int ct = getRenderCt();
int inx = getRenderInx()-1;
if (inx < 0)
inx = times.length - 1;
double t1 = getRenderStartTime();
double totTime = (times[inx] - t1) / 1000;
double fps = ct / totTime;
return (float)fps;
}
public float getRecentFPS () {
double[] times = getLast20();
int inx2 = getRenderInx()-1;
if (inx2 < 0)
inx2 = times.length - 1;
int inx1 = inx2+1;
if (inx1 >= times.length)
inx1 = 0;
double totTime = (times[inx2] - times[inx1]) / 1000;
double fps = times.length / totTime;
return (float)fps;
}
public String getStats() {
double[] times = getLast20();
int ct = getRenderCt();
int inx = getRenderInx()-1;
if (inx < 0)
inx = times.length - 1;
double t1 = getRenderStartTime();
double totTime = (times[inx] - t1) / 1000;
double fps = ct / totTime;
String msg = "Frames: " + ct + " Time: " + totTime +
" FPS: " + nf.format(fps) + " (avg); " +
nf.format(getRecentFPS()) + " (last 20)";
return msg;
}
public Window savedFrame = null;
public void postSwap() {
if (saveFrame) {
BufferedImage img = getCanvasImage();
if (saveFileName != null)
writeImage (saveFileName, img);
saveFrame = false;
}
if (renderer != null)
renderer.postSwap (gc);
}
public BufferedImage getCanvasImage () {
GraphicsContext3D ctx = getGraphicsContext3D();
Raster ras = new Raster();
ras.setType (Raster.RASTER_COLOR);
ras.setCapability (Raster.ALLOW_IMAGE_READ);
Dimension d = getSize();
ras.setSize (d);
ras.setImage (new ImageComponent2D(ImageComponent2D.FORMAT_RGB,
d.width, d.height));
ctx.readRaster(ras);
// Now strip out the image info
ImageComponent2D img_src = ras.getImage();
// DepthComponent depth = ras.getDepthComponent();
return img_src.getImage();
}
public void writeImage (String fileName, BufferedImage bi) {
try {
createDir (fileName);
File file = new File(fileName);
FileOutputStream out = new FileOutputStream(file);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
param.setQuality(1.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(bi);
out.close();
}
catch (Exception ex) {
System.out.println ("Error writing image to file " + fileName +
": " + ex.toString());
ex.printStackTrace();
}
}
public boolean createDir (String fileName) {
int i = fileName.lastIndexOf ('\\');
if (i > -1) {
String dir = fileName.substring (0, i);
File f = new File (dir);
return f.mkdirs(); // creates all dirs in file's pathname
// System.out.println ("mkdirs on: " + dir +"; rc = " + b);
}
return true;
}
public void preRender () {
renderCt++;
if (renderCt == 1)
t1 = System.currentTimeMillis();
else {
last20[renderInx++] = System.currentTimeMillis();
if (renderInx == last20.length)
renderInx = 0;
}
if (renderer != null)
renderer.preRender (gc);
}
public void postRender () {
if (renderer != null)
renderer.postRender (gc);
}
public void renderField(int fieldDesc) {
if (renderer != null)
renderer.renderField (fieldDesc, gc);
}
} // end class TimeCanvas3D
Hope this helps
Best regards,
Pat Gleason
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA3D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".