/* JMF_Movie_Analyzer.java Glen Cowan RHUL Physics Department 4 July, 2002 Based on JMF_MovieReader.java distributed with the ImageJ package This ImageJ plugin reads in an avi file and steps through frame by frame. The R, G and B pixel values are individually summed in a 4x4 box in the centre of the image. These values and the frame number are written to the output window and also to an output file. */ import ij.*; import ij.plugin.frame.*; import ij.process.*; import ij.io.*; import java.io.*; import java.awt.*; import java.awt.event.*; import java.net.*; import javax.media.*; import javax.media.control.FrameGrabbingControl; import javax.media.control.FramePositioningControl; import javax.media.format.VideoFormat; import javax.media.protocol.*; import javax.media.util.BufferToImage; public class JMF_Movie_Analyzer extends PlugInFrame implements ControllerListener, ActionListener { Player p; FramePositioningControl fpc; FrameGrabbingControl fgc; Object waitSync = new Object(); boolean stateTransitionOK = true; int totalFrames = FramePositioningControl.FRAME_UNKNOWN; BufferToImage frameConverter; String name; boolean grayscale = false; ImageStack stack; public JMF_Movie_Analyzer() { super("JMF Movie Reader"); } public void run(String arg) { IJ.showStatus(""); OpenDialog od = new OpenDialog("Open Movie...", ""); String dir = od.getDirectory(); name = od.getFileName(); if (name==null) return; String path = dir + name; String url = encodeURL("file://"+path); //IJ.write("path: "+path); //IJ.write("url: "+url); //url = "http://rsb.info.nih.gov/movie.avi"; //url = "file:///Macintosh HD/Desktop%20Folder/test.mov"; MediaLocator ml; if ((ml = new MediaLocator(url)) == null) { IJ.write("Cannot build media locator from: "); return; } DataSource ds = null; // Create a DataSource given the media locator. IJ.showStatus("creating JMF data source"); try { ds = Manager.createDataSource(ml); } catch (Exception e) { IJ.write("Cannot create DataSource from: " + ml); return; } openMovie(ds); } public String encodeURL(String url) { int index = 0; while (index>-1) { index = url.indexOf(' '); if (index>-1) url = url.substring(0,index)+"%20"+ url.substring(index+1,url.length()); } return url; } public boolean openMovie(DataSource ds) { IJ.showStatus("opening: "+ds.getContentType()); try { p = Manager.createPlayer(ds); } catch (Exception e) { error("Failed to create a player from the given DataSource:\n \n" + e.getMessage()); return false; } p.addControllerListener(this); p.realize(); if (!waitForState(p.Realized)) { error("Failed to realize the JMF player."); return false; } // Try to retrieve a FramePositioningControl from the player. fpc = (FramePositioningControl)p.getControl( "javax.media.control.FramePositioningControl"); if (fpc == null) { error("The player does not support FramePositioningControl."); return false; } // Try to retrieve a FrameGrabbingControl from the player. fgc = (FrameGrabbingControl)p.getControl( "javax.media.control.FrameGrabbingControl"); if (fgc == null) { error("The player does not support FrameGrabbingControl."); return false; } Time duration = p.getDuration(); double durationSeconds = duration.getSeconds(); System.out.println("durationSeconds = " + durationSeconds); if (duration != Duration.DURATION_UNKNOWN) { //IJ.write("Movie duration: " + duration.getSeconds()); totalFrames = fpc.mapTimeToFrame(duration)+1; if (totalFrames==FramePositioningControl.FRAME_UNKNOWN) IJ.write("The FramePositioningControl does not support mapTimeToFrame."); } else { IJ.write("Movie duration: unknown"); } // Prefetch the player. p.prefetch(); if (!waitForState(p.Prefetched)) { error("Failed to prefetch the player."); return false; } // Display the visual & control component if there's one. setLayout(new FlowLayout()); Component vc; if ((vc = p.getVisualComponent()) != null) { add(vc); } Buffer frame = fgc.grabFrame(); VideoFormat format = (VideoFormat)frame.getFormat(); frameConverter = new BufferToImage(format); setVisible(true); // get output file for analyzed pixel data IJ.showStatus("open output file"); boolean saveData = true; SaveDialog sd = new SaveDialog("Save data in file...", "", ".txt"); String dir = sd.getDirectory(); String outName = sd.getFileName(); if (outName==null) saveData = false; PrintWriter out = null; if ( saveData ) { String path = dir + outName; File outputFile = new File(path); try { out = new PrintWriter(new FileWriter(outputFile)); } catch (IOException e) { System.err.println("IOException: " + e.getMessage()); } } int scanRow = (int)IJ.getNumber("enter scan row (0 for top)", 60); System.out.println("scan row = " + scanRow); // loop over frames System.out.println("totalFrames = " + totalFrames); // KLUDGE -- For some reason it's not getting totalFrames or the duration // correct so change logic of program to loop as long as the frame number // is being incremented. GDC Nov 06. // for (int i=0;i>16; g += (c&0xff00)>>8; b += c&0xff; } } System.out.println(currentFrame + "\t" + r + "\t" + g + "\t" + b); if (saveData){ out.println(currentFrame + "\t" + r + "\t" + g + "\t" + b); } // save image in buffer and go to next frame int framesSkipped = fpc.skip(1); // System.out.println("framesSkipped = " + framesSkipped); int newFrame = fpc.mapTimeToFrame(p.getMediaTime()); // System.out.println("new, current frames = " + newFrame + " " + currentFrame); if ( newFrame > currentFrame ) { currentFrame = newFrame; keepGoing = true; frame = fgc.grabFrame(); // boolean status = saveImage(currentFrame, frame); // if (!status){ break; } } else { keepGoing = false; } } if (stack!=null) new ImagePlus(name, stack).show(); setVisible(false); dispose(); IJ.showStatus(""); if ( saveData ) { out.close(); } return true; } public void addNotify() { super.addNotify(); pack(); } /** Block until the player has transitioned to the given state. */ boolean waitForState(int state) { synchronized (waitSync) { try { while (p.getState() < state && stateTransitionOK) waitSync.wait(); } catch (Exception e) {} } return stateTransitionOK; } public void actionPerformed(ActionEvent ae) { int currentFrame = fpc.mapTimeToFrame(p.getMediaTime()); if (currentFrame != FramePositioningControl.FRAME_UNKNOWN) IJ.write("Current frame: " + currentFrame); } private void error(String msg) { IJ.showMessage("JMF Movie Reader", msg); IJ.showStatus(""); } private boolean saveImage(int count, Buffer frame) { Image img = frameConverter.createImage(frame); ImageProcessor ip = new ColorProcessor(img); if (count==1) { int width = ip.getWidth(); int height = ip.getHeight(); int size = (width*height*totalFrames*4)/(1024*1024); IJ.showStatus("Allocating "+width+"x"+height+"x"+totalFrames+ "stack ("+size+"MB)"); stack = allocateStack(width, height, totalFrames); if (stack==null) { IJ.outOfMemory("JMF Movie Opener"); return false; } grayscale = isGrayscale(ip); } if (grayscale) ip = ip.convertToByte(false); stack.setPixels(ip.getPixels(), count); return true; } /** Controller Listener */ public void controllerUpdate(ControllerEvent evt) { if (evt instanceof ConfigureCompleteEvent || evt instanceof RealizeCompleteEvent || evt instanceof PrefetchCompleteEvent) { synchronized (waitSync) { stateTransitionOK = true; waitSync.notifyAll(); } } else if (evt instanceof ResourceUnavailableEvent) { synchronized (waitSync) { stateTransitionOK = false; waitSync.notifyAll(); } } else if (evt instanceof EndOfMediaEvent) { p.setMediaTime(new Time(0)); //p.start(); //p.close(); //System.exit(0); } else if (evt instanceof SizeChangeEvent) { } } ImageStack allocateStack(int width, int height, int size) { ImageStack stack=null; byte[] temp; try { stack = new ImageStack(width, height); for (int i=0; i>16; g = (c&0xff00)>>8; b = c&0xff; if (r!=g || r!=b || g!=b) { grayscale = false; break; } } return grayscale; } }