Capture to jpg

Hi. I need to add a function where the user can press a key and take a screen dump, saved as an image (e.g. jpg). Is this possible and how?

I dont know if Xith3D has a class specifically for this but you can do this via the java.awt.Robot and javax.imageio.ImageIO class.

Example:


import javax.imageio.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
public class Example {
	protected static void capture() {
		GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
		Robot r = null;
		try {
			r = new Robot(gd);
		}
		catch (AWTException e) {
			e.printStackTrace();
			return;
		}
		DisplayMode dm = gd.getDisplayMode();
		BufferedImage b = r.createScreenCapture(new Rectangle(0,0,dm.getWidth(),dm.getHeight()));
		try {
			ImageIO.write(b,"jpg",new FileOutputStream("screen.jpg"));
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String args[]) {
		capture();
	}
}

Unfortunately ImageIO doesn’t seem to save JPEGs with the highest quality. However, if you write PNGs (which I dont think is fully supported prior to 1.5) the image will be lossless.

one thing, the previous code I posted takes a screenshot of the entire screen (so if your app isn’t full-screen, you’ll be capturing the other parts of the screen that have nothing to do with your app). You can use this modified version of capture() to capture just a particular Window:


protected void capture(Window w) {
	GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
	Robot r = null;
	try {
		r = new Robot(gd);
	}
	catch (AWTException e) {
		e.printStackTrace();
		return;
	}
	DisplayMode dm = gd.getDisplayMode();
	BufferedImage b = r.createScreenCapture(w.getBounds());
	try {
		ImageIO.write(b,"jpg",new FileOutputStream("screen.jpg"));
	}
	catch (IOException e) {
		e.printStackTrace();
	}
}

Xith3D does provide this and it is really easy 8)


View v;
Canvas3D canvas;

// ...

String filename = "myfilename.png";
view.getSnapshot(canvas, filename);


Some nifty formatting for the filename


String filename = System.getProperty("home.dir") + System.getProperty("file.separator") + "MYPROJECT" + 
     (new SimpleDateFormat("_yyyy-MM-dd-HHmmss")).format(new GregorianCalendar().getTime()) + ".png";

That will create the shot in the user’s home dir (as opposed to the working dir, of course this is up to you) named: “MYPROJECT_2005-06-06-163101.png”.

I think I will add this question to the FAQ.

Cheers,

Will.

For your information, this is actually possible.

This is the code I use in my photo album processing program Gallery Mage:


	/**
	 * Writes the given image data to a JPEG image file, with the given quality
	 * @param toWrite the image to write
	 * @param fileout name of the file
	 * @param quality JPEG quality percentage (0 == worst, 1 == best)
	 * 
	 * @throws IOException if there was an error writing the image
	 */
	public static void writeJpegImage(BufferedImage toWrite, String fileout, float quality) throws IOException {
	    
		ImageOutputStream ios = ImageIO.createImageOutputStream(new File(fileout));
		
		ImageWriter writer = null;
		Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
		if (iter.hasNext()) {
		    writer = (ImageWriter)iter.next();
		}
		
		writer.setOutput(ios);
		ImageWriteParam iwparam = writer.getDefaultWriteParam();
		iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
		//System.out.println(iwparam.getCompressionQuality()) ;
		iwparam.setCompressionQuality(quality) ;
		writer.write(null, new IIOImage(toWrite, null, null), iwparam);
		ios.flush();
		writer.dispose();
		ios.close();
	}

You can also find that solution by looking up “ugly” in your dictionary :wink:

Cheers,

Will.

aha! I was thinking ImageIO SHOULD be able to set quality, just didn’t know where it was

thanks for pointing this out :wink:

Thanks for the quick reply. You are the greatest!

Btw. I got an 11. for a project involving xith3d and jmf (3d, video and motion detection). I owe much of this to you people who made xith so intuitive!

No worries. I really wish there was a cleaner solution though. Something that doesn’t require one to write a utility method.

Will.

You’re welcome. Well done on your project (I assume 11 is a good score :)), please share the details, it’s always interesting to learn how people are using Xith3D.

Cheers,

Will.

Hi. 11 is a great score. It’s equal to an A :slight_smile: Still can’t believe it.

The source code is a mess because I only had two months to create it program, but I’ll upload the part of the report that describes the program in a day or so.

A summery: A webcam gets an image and detects red colour (the user of the program will wear a red light). This is mapped to a grid and this grid is used to control the view. If the views position matches a given variable (vector), the render is stopped and a new frame is created in which an mpeg2 movie is played. The motion detection is then used to move forward and backwards in the movie and when the movie ends, the frame is closed and the render is started again. It’s supposed to be an interactive movie. There were some bugs in the end because caused by JMF. For some reason it has problems moving in a movie precisely enough for my needs. Something about the setMediaTime() doesn’t really move to the precise timeframe.

http://www.harme.dk/engine/inside.pdf

For anyone interested, a small part of the report concerning the program