package fr.unistra.pelican.algorithms.io; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import javax.media.Buffer; import javax.media.CannotRealizeException; import javax.media.Duration; import javax.media.Manager; import javax.media.NoPlayerException; import javax.media.Player; import javax.media.Time; import javax.media.control.FrameGrabbingControl; import javax.media.control.FramePositioningControl; import javax.media.format.VideoFormat; import javax.media.util.BufferToImage; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.ByteImage; /** * Experimental Frame loader (works only the AVI format, for further detail * please contact the author). * It loads only the frames given in the ArrayList selectedFrames * @author Erhan Aptoula, Jonathan Weber,Vincent Danner */ public class FrameLoader extends Algorithm { /** * Input parameter. */ public String filename; /** * List of the frames to be loaded */ public ArrayList<Integer> selectedFrames=new ArrayList<Integer>(); /** * Output parameter. */ public ByteImage outputImage; /** * Constructor * */ public FrameLoader() { super(); super.inputs = "filename,selectedFrames"; super.outputs = "outputImage"; } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { // create a movie player, in a 'realized' state Player p = null; int totalFrames = 0; int bands = 1; try{ URL url = new URL("file:" + filename); try { p = Manager.createRealizedPlayer(url); // create a frame positioner FramePositioningControl fpc = (FramePositioningControl) p .getControl("javax.media.control.FramePositioningControl"); // create a frame grabber FrameGrabbingControl fg = (FrameGrabbingControl) p .getControl("javax.media.control.FrameGrabbingControl"); // request that the player changes to a 'prefetched' state p.prefetch(); // wait until the player is in that state... Time duration = p.getDuration(); if (duration != Duration.DURATION_UNKNOWN) totalFrames = fpc.mapTimeToFrame(duration); else throw new AlgorithmException("Duration unknown"); Integer framesUsed=selectedFrames.size(); for (int i = 0; i <framesUsed; i++) { Integer currentFrame = selectedFrames.get(i); if(currentFrame>=totalFrames||currentFrame<0) throw new AlgorithmException("there is no frame n° "+currentFrame+ " in this video" ); // move to a particular frame fpc.seek(currentFrame+1); // take a snap of the current frame Buffer buf = fg.grabFrame(); // get its video format details VideoFormat vf = (VideoFormat) buf.getFormat(); // initialize BufferToImage with video format BufferToImage bufferToImage = new BufferToImage(vf); // convert the buffer to an image BufferedImage bim = (BufferedImage) bufferToImage.createImage(buf); int width = bim.getWidth(null); int height = bim.getHeight(null); if (outputImage == null) { switch (bim.getType()) { case BufferedImage.TYPE_BYTE_GRAY: case BufferedImage.TYPE_USHORT_GRAY: bands = 1; break; case BufferedImage.TYPE_INT_RGB: case BufferedImage.TYPE_INT_BGR: bands = 3; break; default: throw new AlgorithmException( "Unsupported pixel organization"); } outputImage = new ByteImage(width,height,1,framesUsed,bands); } WritableRaster r = bim.getRaster(); int loc=(i)*outputImage.getBDim()*outputImage.getXDim()*outputImage.getYDim(); for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) for (int b = 0; b < bands; b++) { outputImage.setPixelByte(loc,(byte)r.getSample(x, y, b)); loc++; //outputImage.setPixelXYZTBByte(x,y,0,i,b,(byte)r.getSample(x, y, b)); } if(outputImage.getBDim()==3) outputImage.setColor(true); } }finally{ p.close(); } } catch (NoPlayerException e) { throw new AlgorithmException("Unable to read file "+this.filename); } catch (CannotRealizeException e){ throw new AlgorithmException("Unable to read file "+this.filename); } catch (IOException e) { throw new AlgorithmException("Unable to read file "+this.filename); } } /** * Experimental frame loader. * * @param filename * Directory of the video * @param selectedFrames * ArrayList of the frames that must be loaded * @return the loaded frames as a video */ public static ByteImage exec(String filename,ArrayList<Integer> selectedFrames) { return (ByteImage) new FrameLoader().process(filename, selectedFrames); } }