From 65ab9dcca790ca39e4d256214a2c74013f4847a6 Mon Sep 17 00:00:00 2001 From: Simon Ebner Date: Fri, 5 Apr 2013 11:08:44 +0200 Subject: [PATCH] Initial commit of the ImageJ ZeroMQ Viewer --- ch.psi.imagej.zeromq/.classpath | 32 ++++ ch.psi.imagej.zeromq/.gitignore | 1 + ch.psi.imagej.zeromq/.project | 23 +++ .../.settings/org.eclipse.jdt.core.prefs | 12 ++ .../.settings/org.eclipse.m2e.core.prefs | 4 + ch.psi.imagej.zeromq/pom.xml | 20 +++ .../ch/psi/imagej/zeromq/ZeroMQViewer.java | 168 ++++++++++++++++++ .../src/main/resources/.gitignore | 0 ch.psi.imagej.zeromq/src/test/java/.gitignore | 0 .../src/test/resources/.gitignore | 0 10 files changed, 260 insertions(+) create mode 100644 ch.psi.imagej.zeromq/.classpath create mode 100644 ch.psi.imagej.zeromq/.gitignore create mode 100644 ch.psi.imagej.zeromq/.project create mode 100644 ch.psi.imagej.zeromq/.settings/org.eclipse.jdt.core.prefs create mode 100644 ch.psi.imagej.zeromq/.settings/org.eclipse.m2e.core.prefs create mode 100644 ch.psi.imagej.zeromq/pom.xml create mode 100644 ch.psi.imagej.zeromq/src/main/java/ch/psi/imagej/zeromq/ZeroMQViewer.java create mode 100644 ch.psi.imagej.zeromq/src/main/resources/.gitignore create mode 100644 ch.psi.imagej.zeromq/src/test/java/.gitignore create mode 100644 ch.psi.imagej.zeromq/src/test/resources/.gitignore diff --git a/ch.psi.imagej.zeromq/.classpath b/ch.psi.imagej.zeromq/.classpath new file mode 100644 index 0000000..8dee4f3 --- /dev/null +++ b/ch.psi.imagej.zeromq/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch.psi.imagej.zeromq/.gitignore b/ch.psi.imagej.zeromq/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/ch.psi.imagej.zeromq/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ch.psi.imagej.zeromq/.project b/ch.psi.imagej.zeromq/.project new file mode 100644 index 0000000..09b1d63 --- /dev/null +++ b/ch.psi.imagej.zeromq/.project @@ -0,0 +1,23 @@ + + + ch.psi.imagej.zeromq + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/ch.psi.imagej.zeromq/.settings/org.eclipse.jdt.core.prefs b/ch.psi.imagej.zeromq/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..8e4055a --- /dev/null +++ b/ch.psi.imagej.zeromq/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/ch.psi.imagej.zeromq/.settings/org.eclipse.m2e.core.prefs b/ch.psi.imagej.zeromq/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/ch.psi.imagej.zeromq/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/ch.psi.imagej.zeromq/pom.xml b/ch.psi.imagej.zeromq/pom.xml new file mode 100644 index 0000000..04ef489 --- /dev/null +++ b/ch.psi.imagej.zeromq/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + ch.psi + ch.psi.imagej.zeromq + 0.0.1-SNAPSHOT + + + + org.jeromq + jeromq + 0.2.0 + + + gov.nih.imagej + imagej + 1.46 + provided + + + \ No newline at end of file diff --git a/ch.psi.imagej.zeromq/src/main/java/ch/psi/imagej/zeromq/ZeroMQViewer.java b/ch.psi.imagej.zeromq/src/main/java/ch/psi/imagej/zeromq/ZeroMQViewer.java new file mode 100644 index 0000000..e069bb1 --- /dev/null +++ b/ch.psi.imagej.zeromq/src/main/java/ch/psi/imagej/zeromq/ZeroMQViewer.java @@ -0,0 +1,168 @@ +package ch.psi.imagej.zeromq; +// EPICS_AD_Viewer.java +// Original authors +// Tim Madden, APS +// Mark Rivers, University of Chicago +import ij.*; +import ij.process.*; +import java.awt.*; +import ij.plugin.*; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.awt.event.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.*; +import javax.swing.Timer; +import javax.swing.border.*; + +import org.jeromq.ZMQ; + +public class ZeroMQViewer implements PlugIn { + + private static final Logger logger = Logger.getLogger(ZeroMQViewer.class.getName()); + + private ImagePlus img; + + private int imageSizeX = 2560; + private int imageSizeY = 2160; + + // These are used for the frames/second calculation + private long prevTime; + private int numImageUpdates; + + private JFrame frame; + private JTextField fpsText; + + private boolean isPluginRunning; + + private Timer timer; + + private ZMQ.Context context; + private ZMQ.Socket socket; + + public void run(String arg) { + IJ.showStatus("Running ZeroMQ Viewer"); + try { + isPluginRunning = true; + + prevTime = System.currentTimeMillis(); + numImageUpdates = 0; + + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + context = ZMQ.context(1); + socket = context.socket(ZMQ.PULL); + socket.bind("tcp://*:8080"); + + while (isPluginRunning) { + byte[] message = socket.recv(); + byte[] content = null; + if (socket.hasReceiveMore()) { + content = socket.recv(); + } + logger.info(new String(message)); + updateImage(content); + } + + timer.stop(); + + socket.close(); + context.term(); + + img.close(); + frame.setVisible(false); + + IJ.showStatus("Exiting ZeroMQ Viewer"); + + } catch (Exception e) { + logger.log(Level.SEVERE, "", e); + IJ.showStatus(e.toString()); + } + } + + public void updateImage(byte[] content) { + try { + if(img==null){ + // TODO eventually use ByteProcessor or BinaryProcessor + // BinaryProcessor p = new ij.process.BinaryProcessor(new + // ByteProcessor(imageSizeX, imageSizeY)); + img = new ImagePlus("", new ShortProcessor(imageSizeX, imageSizeY)); + img.show(); + } + + // TODO Check whether this is needed + short[] shorts = new short[content.length / 2]; + ByteBuffer.wrap(content).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts); + img.getProcessor().setPixels(shorts); + + img.updateAndDraw(); + numImageUpdates++; + } catch (Exception ex) { + logger.log(Level.SEVERE, "UpdateImage got exception", ex); + } + } + + /** + * Create the GUI and show it. For thread safety, this method should be + * invoked from the event-dispatching thread. + */ + public void createAndShowGUI() { + fpsText = new JTextField(6); + fpsText.setEditable(false); + fpsText.setHorizontalAlignment(JTextField.CENTER); + + frame = new JFrame("ZeroMQ_Viewer Plugin"); + JPanel panel = new JPanel(new BorderLayout()); + panel.setLayout(new GridBagLayout()); + panel.setBorder(new EmptyBorder(new Insets(5, 5, 5, 5))); + frame.getContentPane().add(BorderLayout.CENTER, panel); + GridBagConstraints c = new GridBagConstraints(); + // Add extra space around each component to avoid clutter + c.insets = new Insets(2, 2, 2, 2); + + // Top row + // Anchor all components CENTER + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 0; + panel.add(new JLabel("Frames/s"), c); + + // Middle row + // These widgets should be centered + c.anchor = GridBagConstraints.CENTER; + c.gridy = 1; + c.gridx = 0; + panel.add(fpsText, c); + + // Display the window. + frame.pack(); + frame.addWindowListener(new FrameExitListener()); + frame.setVisible(true); + + int timerDelay = 2000; // 2 seconds + timer = new Timer(timerDelay, new ActionListener() { + public void actionPerformed(ActionEvent event) { + long time = System.currentTimeMillis(); + double fps = 1000. * numImageUpdates / (double) (time - prevTime); + fpsText.setText(String.format("%.1f", fps)); + prevTime = time; + numImageUpdates = 0; + } + }); + timer.start(); + + } + + public class FrameExitListener extends WindowAdapter { + public void windowClosing(WindowEvent event) { + isPluginRunning = false; + } + } +} diff --git a/ch.psi.imagej.zeromq/src/main/resources/.gitignore b/ch.psi.imagej.zeromq/src/main/resources/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/ch.psi.imagej.zeromq/src/test/java/.gitignore b/ch.psi.imagej.zeromq/src/test/java/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/ch.psi.imagej.zeromq/src/test/resources/.gitignore b/ch.psi.imagej.zeromq/src/test/resources/.gitignore new file mode 100644 index 0000000..e69de29