import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.image.BufferedImage; import javax.swing.JFrame; import vxp.PixelSource; import vxp.QTLivePixelSource; import vxp.VideoListener; /** * @author DanO *This is a sample class that students can extend to create interesting web cams */ public class VideoWindow extends JFrame implements WindowListener, VideoListener, KeyListener, MouseListener { /**This is reference to a PixelSource object from vxp.jar*/ PixelSource ps; /**This is handy for testing performance*/ long elapsedTime; /**Width and Height are set in one place. * Using 320,240 instead of 640,480 will make all your programming and transers faster * When you want to get fancy bump it up */ int kWidth = 320; int kHeight = 240; /**BufferedImage is now the the basic image format within java. Learn it, love it*/ BufferedImage liveImage = new BufferedImage(kWidth,kHeight,BufferedImage.TYPE_INT_ARGB); BufferedImage freezeFrame = new BufferedImage(kWidth,kHeight,BufferedImage.TYPE_INT_ARGB); /** For frame differencing we will need an array to store the pixels from some previous frame. * This may be a frame from the very start of the program when the cameras view was clear (background removal) * or it may be from the previous froma (movement detection). */ int[] backgroundReference = new int[kWidth * kHeight]; /** This is the constructor */ VideoWindow() { initVideo(); //set the window stuff setSize(kWidth*2, kHeight); setTitle("VideoWindow"); //setUndecorated(true); setVisible(true); //arrange to get callbacks for events from these Listeners. //I had to previously promise to implement and then implement the methods that these listeners call addWindowListener(this); addMouseListener(this); addKeyListener(this); } /** This cranks up the video by creating a pixelSource object. * It also subscribes to the video listener, of course I would have to have previously promised to implement a VideoListener and then implement "newFrame" * You might consider overriding this if you want a different kind of video object * or don't want to subscribe to the notification service. */ public void initVideo(){ ps = new QTLivePixelSource(kWidth, kHeight, 300); kWidth = ps.vidWidth; //you asked for one width but, especially on the mac, an extra pixel or two might get aded on to what you actually get. } /** Separated this out from init video because you get a lot of null pointer exceptions * when you start hearing back from the video before all your buffers are set up right * You can't set up your buffers until you construct the video * in case they need to be a little bigger than you expected * as the case on the mac. */ public void startVideo(){ ps.addVideoListener(this); } /** The is the entry point for your program * You will definitely want to override this and then get out of it as * soon as possible */ public static void main(String[] Args) { VideoWindow myWorld = new VideoWindow(); myWorld.startVideo(); } /** You always need to clean up */ public void cleanUp() { ps.killSession(); System.out.println("Killed Video Source"); //this stuff kills the window System.out.println("Kill Application"); setVisible(false); dispose(); System.exit(2); } /** This is the method that pixel source uses to tell you that a * new frame is ready. You have to have this if you want to implement a VideoListener */ public void newFrame() { long startTime = System.currentTimeMillis(); ps.grabFrame(); liveImage = ps.getImage(); repaint(); elapsedTime = System.currentTimeMillis() - startTime; } /** This overrides the update method of JFrame which gets called on repaint. The * reason I don't like JFrames is because it clears the screen (which I don't need) * and creates flicker doing it. I redo the method with a paint but no clear */ public void update(Graphics g){ paint(g); } /**This gets called everytime you repaint the screen. You would * want to override this if you want anything but side by side pictures */ public void paint(Graphics g) { g.drawImage(liveImage ,0,0,null); g.drawImage(freezeFrame, kWidth, 0, null); } /**This is a convenience because hate typing "System.out.println" * In this way you can rewrite java to your tastes. */ public void put(String s) { System.out.println(s); } /**This is a method that you promised to have as a WindowListener. */ public void windowClosing(WindowEvent e) { cleanUp(); } /**Grabs a frame and then puts it into a bufferedImage. */ public void grabPicture(BufferedImage _ff){ ps.grabFrame(); ps.getImage(_ff); } /**This stores the current frame for future reference. */ public void grabReference() { // you have clone which makes a full copy of the old frame //otherwise you would just make a reference to the array that keeps changing with each new frame backgroundReference = (int[]) ps.getPixelArray().clone(); } /**This is a method that you promised to have as a KeyListener. * For homework you might try to replace the last part with different input than a keystroke */ public void keyReleased(KeyEvent e) { if (e.getKeyChar() == 's') { ps.videoSettings(); } else if (e.getKeyChar() == 't') { put("Timer" + elapsedTime); } else if (KeyEvent.getKeyText(e.getKeyCode()).equals("Escape")) { cleanUp() ; } } public void windowDeactivated(WindowEvent e) { } public void windowDeiconified(WindowEvent e) { } public void windowIconified(WindowEvent e) { } public void windowOpened(WindowEvent e) { } public void keyPressed(KeyEvent e) { } public void keyTyped(KeyEvent e) { } public void windowActivated(WindowEvent e) { } public void windowClosed(WindowEvent e) { } public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } }