|
ICY Version 1.0.1.0
|
*public class SwimmingPoolListenerTutorial extends Plugin implements PluginImageAnalysis , SwimmingPoolListener { @Override public void compute() { // We register this class as a listener of the swimmingPool Icy.getMainInterface().getSwimmingPool().addListener( this ); new AnnounceFrame( "Swimming pool listener example: I am listening/watching the swimmingpool." ); // watch if objects are already in the swimming pool: for ( SwimmingObject swimmingObject : Icy.getMainInterface().getSwimmingPool().getObjects() ) { if ( swimmingObject.getObject() instanceof Point2D ) { Point2D point = (Point2D) swimmingObject.getObject(); new AnnounceFrame("Swimming pool listener example: There is already an object in the swimming pool ! Its coordinates are "+ point.getX() + "," + point.getY() ); } } } @Override public void swimmingPoolChangeEvent(SwimmingPoolEvent event) { // an object has been added in the swimming pool ! if ( event.getType() == SwimmingPoolEventType.ELEMENT_ADDED ) { // Can we manage this type ? if ( event.getResult().getObject() instanceof Point2D ) { // yes, we know it, let's process it. Point2D point = (Point2D) event.getResult().getObject(); new AnnounceFrame("Swimming pool listener example: A point has been dropped ! Its coordinates are "+ point.getX() + "," + point.getY() ); }else { // no, we don't know what we should do with it. new AnnounceFrame( "Swimming pool listener example: Something has been dropped, but I don't know how to handle it." ); } } } } *
This is a swimming pool listener tutorial. Use it with SwimmingPoolEmitterTutorial.
The swimming pool is a place where any plugin can access, listen, create, delete or transform objects. This is the ultimate flexibility to create communication between plugins.
This tutorial explain how to register a listener, and listen to a certain type of object.
*public class ProcessingFromROI extends Plugin implements PluginImageAnalysis, SequenceListener, ViewerListener { private Viewer viewer; private Sequence sequence; private AbstractPainter painter; BufferedImage img; private int[] imgData; @Override public void compute() { viewer = getFocusedViewer(); // no viewer has been found ? if (viewer == null) { // display an information message as we need an opened sequence MessageDialog.showDialog("This example needs a sequence to start. Please load an image file.", MessageDialog.INFORMATION_MESSAGE); return; } // we should avoid direct sequence reference but it really help there sequence = viewer.getSequence(); // display an announcement with Plugin description new AnnounceFrame("This example show how do localized operation on image from ROI"); // no ROI2D in sequence if (!sequence.hasROI(ROI2D.class)) new AnnounceFrame("Add a ROI to the sequence to see plugin action"); // define a painter to just draw the image over the sequence painter = new AbstractPainter() { @Override public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas) { // just draw the image over the sequence g.drawImage(img, null, 0, 0); } }; // add the painter to the sequence sequence.addPainter(painter); // build an ARGB image with same dimension than sequence img = new BufferedImage(sequence.getSizeX(), sequence.getSizeY(), BufferedImage.TYPE_INT_ARGB); // get internal image data reference imgData = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); // listen viewer changes so we know when current displayed image change viewer.addListener(this); // listen sequence changes so we know when sequence rois are modified sequence.addListener(this); refresh(); } // we call this method when we want to terminate plugin execution private void close() { // remove viewer listener viewer.removeListener(this); // remove sequence listener sequence.removeListener(this); // remove the painter from the sequence (same as painter.detachFromAll()) sequence.removePainter(painter); // free sequence reference viewer = null; sequence = null; } private void refresh() { // clear image Arrays.fill(imgData, 0); final IcyBufferedImage currentImage = getFocusedImage(); if (currentImage != null) { // get image bounds (rectangle defining height and width of image) final Rectangle imageBounds = currentImage.getBounds(); BooleanMask2D globalMask = null; // compute global boolean mask of all ROI2D contained in the sequence for (ROI2D roi : sequence.getROI2Ds()) { // get intersection between image and roi bounds final Rectangle intersect = roi.getBounds().intersection(imageBounds); // get the boolean mask of roi (optimized from intersection bounds) final boolean[] mask = roi.getAsBooleanMask(intersect); // update global mask if (globalMask == null) globalMask = new BooleanMask2D(intersect, mask); else globalMask.union(intersect, mask); } // process only if global mask is not empty if ((globalMask != null) && (!globalMask.bounds.isEmpty())) { final Rectangle bounds = globalMask.bounds; final boolean[] mask = globalMask.mask; // calculate offset int offMsk = 0; int offImg = (bounds.y * imageBounds.width) + bounds.x; // do process only on data contained in ROI for (int y = 0; y < bounds.height; y++) { // override all contained pixels with half transparent green for (int x = 0; x < bounds.width; x++) if (mask[offMsk + x]) imgData[offImg + x] = 0x8000FF00; offMsk += bounds.width; offImg += imageBounds.width; } } } // notify that our painter has changed (image data modified) // this method is a facility of AbstractPainter // this is equivalent to sequence.painterChanged(painter); painter.changed(); } // called when sequence has changed @Override public void sequenceChanged(SequenceEvent sequenceEvent) { // we want to know about sequence roi changes switch (sequenceEvent.getSourceType()) { case SEQUENCE_ROI: // roi change --> refresh refresh(); break; } } // called when sequence is closed (last viewer containing sequence has changed @Override public void sequenceClosed(Sequence sequence) { } @Override public void viewerChanged(Viewer viewer, ViewerChangedEventType eventType) { // we want to know about navigation change (current displayed image change) switch (eventType) { case POSITION_T_CHANGED: case POSITION_Z_CHANGED: // refresh refresh(); break; } } @Override public void viewerClosed(Viewer viewer) { // end plugin execution close(); } } *
This class show how we can use ROI to do localized operation on image
1.7.3