diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3d47f986c41db29ec6dc0d5036bf760b3a1cf366
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.idea/
+target/
+.settings/
+*.iml
+.project
+.classpath
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b8ffa4f9cc71d9646a8e0ed9a2e1ce07cbc9c756
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!-- Inherited Icy Parent POM -->
+    <parent>
+        <groupId>org.bioimageanalysis.icy</groupId>
+        <artifactId>parent-pom-plugin</artifactId>
+        <version>1.0.3</version>
+    </parent>
+
+    <!-- Project Information -->
+    <artifactId>image-to-workbook</artifactId>
+    <version>2.5.3</version>
+
+    <packaging>jar</packaging>
+
+    <name>Image to Workbook</name>
+    <description>Convert a 2D Image to workbook</description>
+    <url>http://icy.bioimageanalysis.org/plugin/image-to-workbook/</url>
+    <inceptionYear>2020</inceptionYear>
+
+    <organization>
+        <name>Institut Pasteur</name>
+        <url>https://pasteur.fr</url>
+    </organization>
+
+    <licenses>
+        <license>
+            <name>GNU GPLv3</name>
+            <url>https://www.gnu.org/licenses/gpl-3.0.en.html</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <developers>
+        <developer>
+            <id>sdallongeville</id>
+            <name>Stéphane Dallongeville</name>
+            <url>https://research.pasteur.fr/fr/member/stephane-dallongeville/</url>
+            <roles>
+                <role>founder</role>
+                <role>lead</role>
+                <role>architect</role>
+                <role>developer</role>
+                <role>debugger</role>
+                <role>tester</role>
+                <role>maintainer</role>
+                <role>support</role>
+            </roles>
+        </developer>
+    </developers>
+
+    <!-- Project properties -->
+    <properties>
+
+    </properties>
+
+    <!-- Project build configuration -->
+    <build>
+
+    </build>
+
+    <!-- List of project's dependencies -->
+    <dependencies>
+        <!-- The core of Icy -->
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>icy-kernel</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>workbooks</artifactId>
+            <version>3.4.10</version>
+        </dependency>
+    </dependencies>
+
+    <!-- Icy Maven repository (to find parent POM) -->
+    <repositories>
+        <repository>
+            <id>icy</id>
+            <name>Icy's Nexus</name>
+            <url>https://icy-nexus.pasteur.fr/repository/Icy/</url>
+        </repository>
+    </repositories>
+</project>
\ No newline at end of file
diff --git a/src/main/java/plugins/worm/image2workbook/Image2Workbook.java b/src/main/java/plugins/worm/image2workbook/Image2Workbook.java
new file mode 100644
index 0000000000000000000000000000000000000000..0585b378844070f3b0d6b2f5ef7f107e9e0960d9
--- /dev/null
+++ b/src/main/java/plugins/worm/image2workbook/Image2Workbook.java
@@ -0,0 +1,464 @@
+package plugins.worm.image2workbook;
+
+import java.awt.BasicStroke;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.BufferedWriter;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.swing.JComponent;
+import javax.swing.JLayeredPane;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.jdesktop.swingx.JXButton;
+
+import icy.canvas.IcyCanvas;
+import icy.file.FileUtil;
+import icy.gui.dialog.MessageDialog;
+import icy.gui.dialog.SaveDialog;
+import icy.gui.frame.IcyFrame;
+import icy.gui.frame.progress.ToolTipFrame;
+import icy.gui.viewer.Viewer;
+import icy.gui.viewer.ViewerEvent;
+import icy.gui.viewer.ViewerEvent.ViewerEventType;
+import icy.gui.viewer.ViewerListener;
+import icy.image.IcyBufferedImage;
+import icy.painter.Overlay;
+import icy.plugin.abstract_.PluginActionable;
+import icy.sequence.Sequence;
+import icy.sequence.SequenceEvent;
+import icy.sequence.SequenceListener;
+import icy.system.IcyHandledException;
+import icy.type.point.Point5D;
+import plugins.adufour.vars.gui.swing.WorkbookEditor;
+import plugins.adufour.vars.lang.VarWorkbook;
+
+public class Image2Workbook extends PluginActionable
+{
+    public static final HashMap<Viewer, MagnifierOverlay> magnifiers = new HashMap<Viewer, Image2Workbook.MagnifierOverlay>();
+    // squence chooser define
+    // SequenceChooser sq = new SequenceChooser( true, "Input Sequence");
+    Sequence sequence;
+    // workbook define
+    VarWorkbook wb = new VarWorkbook("workbook", "Result");
+    WorkbookEditor ed = new WorkbookEditor(wb);
+    // save button define
+    JXButton buttonSave = new JXButton("Save workbook as...");
+    IcyFrame mainFrame = new IcyFrame("Image2Workbook Result");
+
+    @Override
+    public void run()
+    {
+        Viewer viewer = getActiveViewer();
+
+        if (viewer == null)
+            throw new IcyHandledException("Open an image before using the magnifier");
+
+        if (magnifiers.containsKey(viewer))
+            return;
+
+        if (viewer.getSequence() == null)
+            throw new IcyHandledException("The active viewer contains no sequence");
+
+        magnifiers.put(viewer, new MagnifierOverlay(viewer, viewer.getSequence().getSizeC() - 1, 4, wb, mainFrame));
+
+        ed.setEnabled(true);
+        // sq.setActiveSequenceSelected();
+        // main editor
+
+        mainFrame.setResizable(true);
+        mainFrame.setLayout(new BorderLayout());
+        // north panel
+        // JXPanel NorthPanel = new JXPanel();
+        // //sq.addActionListener(new ActionListener()
+        // {
+        //
+        // @Override
+        // public void actionPerformed(ActionEvent e) {
+        // sequence = sq.getSelectedSequence();
+        // //ImageToWorkbook(sequence,wb);
+        // }
+        // });
+
+        // NorthPanel.add(sq);
+        // South panel
+        // JXPanel SouthPanel = new JXPanel();
+        // buttonSave.addActionListener(new ActionListener()
+        // {
+        // @Override
+        // public void actionPerformed(ActionEvent e)
+        // {
+        // String path = SaveDialog.chooseFile("Save workbook as...", null, "Workbook", ".xls");
+        // if (path == null) return;
+        //
+        // try
+        // {
+        // FileOutputStream fos = new FileOutputStream(path);
+        // wb.getValue().write(fos);
+        // fos.close();
+        // }
+        // catch (IOException e1)
+        // {
+        // MessageDialog.showDialog(e1.getMessage(), MessageDialog.ERROR_MESSAGE);
+        // }
+        // }
+        //
+        //
+        // });
+        // SouthPanel.add(buttonSave);
+        // show the workbook
+        JComponent cp = ed.getEditorComponent();
+        cp.setPreferredSize(new Dimension(600, 600));
+        mainFrame.add(cp, BorderLayout.CENTER);
+        // show the button and squencechooser
+        // mainFrame.add(NorthPanel, BorderLayout.NORTH);
+        // mainFrame.add(SouthPanel,BorderLayout.NORTH);
+        // Pack and show the window
+        mainFrame.pack();
+        mainFrame.addToDesktopPane(JLayeredPane.DEFAULT_LAYER);
+        mainFrame.setVisible(true);
+
+        // }
+    }
+
+    private static final class MagnifierOverlay extends Overlay implements SequenceListener, ViewerListener
+    {
+        private final Sequence sequence;
+        private final ToolTipFrame frame = new ToolTipFrame(
+                "<b>Image2Workbook instructions:</b><br/><ul><li>Press 'c' to toggle between channels</li>"
+                        + "<li>Press 'a' to save  the sequence data</li>"
+                        + "<li>Press 's' to save current image data</li>" + "<li>Press 'q' to close</li>"
+                        + "<li>Press 'space' to toggle the workbook refresh mode</li></ul>");
+
+        float currentPosX, currentPosY;
+        int currentChannel = 0;
+
+        private int scale;
+        AffineTransform xForm = new AffineTransform();
+
+        int radius = 50;
+        int diameter = radius * 2;
+        GradientPaint paintBlack = new GradientPaint(0, 0, Color.black, radius, radius, Color.darkGray.darker(), true);
+        GradientPaint paintGreen = new GradientPaint(0, 0, Color.green, radius, radius, Color.lightGray.darker(), true);
+
+        Rectangle2D.Float lens = new Rectangle2D.Float();
+        final Viewer viewer;
+        Boolean RefreshWorkbookMode = true;
+        VarWorkbook wb;
+        IcyFrame mainFrame;
+
+        public MagnifierOverlay(Viewer viewer, int initialChannel, int magnifierScale, VarWorkbook w, IcyFrame frame)
+        {
+            super("Magnifier");
+            wb = w;
+            mainFrame = frame;
+            this.viewer = viewer;
+            this.sequence = viewer.getSequence();
+            this.currentChannel = initialChannel;
+            sequence.addOverlay(this);
+            radius = Math.min(Math.min(sequence.getSizeX() / 2, sequence.getSizeY()) / 2, 50);
+            diameter = radius * 2;
+            paintBlack = new GradientPaint(0, 0, Color.black, radius, radius, Color.darkGray.darker(), true);
+            paintGreen = new GradientPaint(0, 0, Color.green, radius, radius, Color.lightGray.darker(), true);
+
+            sequence.addListener(this);
+            viewer.addListener(this);
+            setScale(magnifierScale);
+        }
+
+        private void setScale(int scale)
+        {
+            this.scale = scale;
+            new Font("Tahoma", Font.PLAIN, scale).deriveFont(scale * 0.1f);
+        }
+
+        private void updateImageCache()
+        {
+
+            currentChannel = Math.min(currentChannel, sequence.getSizeC());
+
+        }
+
+        @Override
+        public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas)
+        {
+            // don't paint on other viewers
+            if (viewer.getCanvas() != canvas)
+                return;
+            boolean displayValues = RefreshWorkbookMode;// currentZoom >= 2f;
+
+            float xo = currentPosX - radius;
+            float yo = currentPosY - radius;
+
+            // canvas.getScaleX();
+
+            // draw the lens
+            Graphics2D graphics = (Graphics2D) g.create();
+            graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
+
+            if (displayValues)
+                graphics.setPaint(paintGreen);
+            else
+                graphics.setPaint(paintBlack);
+
+            if (radius >= 5)
+                graphics.setStroke(new BasicStroke((float) 1));
+            else
+                graphics.setStroke(new BasicStroke((float) 0.1));
+
+            graphics.draw(lens);
+
+            // draw the "zoomed" image inside the lens
+            graphics.clip(lens);
+            // graphics.translate(xForm.getTranslateX(), xForm.getTranslateY());
+            // graphics.scale(scale, scale);
+            // canvas.getImageLayer().getOverlay().paint(graphics, sequence, canvas);
+
+            graphics.dispose();
+            // draw pixel values
+
+            if (displayValues)
+            {
+                IcyBufferedImage im = canvas.getCurrentImage();
+                Sheet sheet = wb.getValue().getSheetAt(0);
+
+                // int k=0;c
+                for (int j = (int) yo; j < yo + diameter; j++)
+                {
+                    Row row = sheet.createRow((int) (j - yo));
+
+                    // int m=0;
+                    for (int i = (int) xo; i < xo + diameter; i++)
+                    {
+                        Cell cell = row.createCell((int) (i - xo));
+
+                        if (im.getBounds().contains(i, j))
+                            cell.setCellValue(im.getData(i, j, currentChannel));
+                        else
+                            cell.setCellValue(0);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void mouseMove(MouseEvent e, Point5D.Double imagePoint, IcyCanvas canvas)
+        {
+            boolean displayValues = RefreshWorkbookMode;
+            if (!displayValues)
+                return;
+            currentPosX = (float) imagePoint.getX();
+            currentPosY = (float) imagePoint.getY();
+
+            if (currentPosX < radius)
+                currentPosX = radius;
+            if (currentPosY < radius)
+                currentPosY = radius;
+            if (currentPosX > (viewer.getSequence().getSizeX() + radius))
+                currentPosX = viewer.getSequence().getSizeX() + radius;
+            if (currentPosY > (viewer.getSequence().getSizeY() + radius))
+                currentPosY = viewer.getSequence().getSizeY() + radius;
+            radius = Math.min(Math.min(sequence.getSizeX() / 2, sequence.getSizeY() / 2), 50);
+            diameter = radius * 2;
+            paintBlack = new GradientPaint(0, 0, Color.black, radius, radius, Color.darkGray.darker(), true);
+            paintGreen = new GradientPaint(0, 0, Color.green, radius, radius, Color.lightGray.darker(), true);
+
+            xForm.setToTranslation(-currentPosX * scale + currentPosX, -currentPosY * scale + currentPosY);
+            lens.setFrame(currentPosX - radius, currentPosY - radius, diameter, diameter);
+
+            mainFrame.setTitle(sequence.getName() + " @Channel  " + new Integer(currentChannel).toString()
+                    + "  Location @ " + '(' + new Double(Math.round((double) (currentPosX - radius))).toString() + " "
+                    + ',' + " " + new Double(Math.round((double) (currentPosY - radius))).toString() + ')');
+            canvas.repaint();
+            mainFrame.repaint();
+
+            super.mouseMove(e, imagePoint, canvas);
+        }
+
+        @Override
+        public void keyPressed(KeyEvent e, Point2D imagePoint, IcyCanvas canvas)
+        {
+            if (canvas.getViewer() != viewer)
+                return;
+
+            if ((e.getKeyChar() == 'c') || (e.getKeyChar() == 'C'))
+            {
+                currentChannel = (currentChannel + 1) % (canvas.getCurrentImage().getSizeC());
+                mainFrame.setTitle(sequence.getName() + " @Channel  " + new Integer(currentChannel).toString()
+                        + "  Location @ " + '(' + new Double(Math.round((double) (currentPosX - radius))).toString()
+                        + " " + ',' + " " + new Double(Math.round((double) (currentPosY - radius))).toString() + ')');
+                canvas.repaint();
+                mainFrame.repaint();
+            }
+            else if ((e.getKeyChar() == 's') || (e.getKeyChar() == 'S'))
+            {
+                saveWorkbook();
+            }
+            else if ((e.getKeyChar() == 'a') || (e.getKeyChar() == 'A'))
+            {
+                saveAllData(sequence);
+            }
+            else if ((e.getKeyChar() == 'q') || (e.getKeyChar() == 'Q'))
+            {
+                mainFrame.close();
+                remove();
+            }
+            else if (e.getKeyCode() == KeyEvent.VK_SPACE)
+            {
+                RefreshWorkbookMode = !RefreshWorkbookMode;
+            }
+        }
+
+        @Override
+        public void remove()
+        {
+            frame.close();
+            super.remove();
+            if (sequence != null)
+                sequence.removeListener(this);
+            if (viewer != null)
+                viewer.removeListener(this);
+            magnifiers.remove(viewer);
+        }
+
+        @Override
+        public void sequenceChanged(SequenceEvent sequenceEvent)
+        {
+            switch (sequenceEvent.getSourceType())
+            {
+                case SEQUENCE_DATA:
+                case SEQUENCE_COLORMAP:
+
+                    updateImageCache();
+
+                default:
+                    break;
+            }
+        }
+
+        @Override
+        public void sequenceClosed(Sequence sequence)
+        {
+            remove();
+        }
+
+        @Override
+        public void viewerChanged(ViewerEvent event)
+        {
+            if (event.getType() == ViewerEventType.CANVAS_CHANGED)
+                remove();
+        }
+
+        @Override
+        public void viewerClosed(Viewer viewer)
+        {
+            remove();
+        }
+
+        public void saveWorkbook()
+        {
+            String path = SaveDialog.chooseFile("Save workbook as...", null, "Workbook", ".xls");
+            if (path == null)
+                return;
+
+            try
+            {
+                FileOutputStream fos = new FileOutputStream(path);
+                wb.getValue().write(fos);
+                fos.close();
+            }
+            catch (IOException e1)
+            {
+                MessageDialog.showDialog(e1.getMessage(), MessageDialog.ERROR_MESSAGE);
+            }
+        }
+
+        public void saveImageData(String path, Sequence sequence, int t, int z)
+        {
+
+            if (path == null)
+                return;
+            if (!(path.contains(".csv")))
+            {
+                path = path.concat(".csv");
+            }
+            for (int channel = 0; channel < sequence.getSizeC(); channel++)
+            {
+                IcyBufferedImage im = sequence.getImage(t, z, channel);
+
+                try
+                {
+                    FileWriter fw = new FileWriter(
+                            path.replace(".csv", '_' + "channel" + new Integer(channel).toString() + ".csv"), false);
+
+                    BufferedWriter bw = new BufferedWriter(fw);
+                    for (int y = 0; y < im.getSizeY(); y++)
+                    {
+
+                        for (int x = 0; x < im.getSizeX() - 1; x++)
+                        {
+                            bw.write(new Double(im.getData(x, y, 0)).toString());
+                            bw.write(',');
+                        }
+                        bw.write(new Double(im.getData(im.getSizeX() - 1, y, 0)).toString());
+                        bw.write('\n');
+                        bw.flush();
+                    }
+                    bw.close();
+                    fw.close();
+                }
+                catch (IOException e1)
+                {
+                    MessageDialog.showDialog(e1.getMessage(), MessageDialog.ERROR_MESSAGE);
+                }
+            }
+
+        }
+
+        public void saveAllData(Sequence sequence)
+        {
+            String pathchanged;
+
+            String path = SaveDialog.chooseFile("Save current image as...", null,
+                    sequence.getName().toString() + ".csv");
+            if (path == null)
+                return;
+            path = path.replace(".csv", "").replace(".CSV", "");
+
+            FileUtil.createDir(path);
+            path = path + '/' + sequence.getName().toString();
+            for (int T = 0; T < sequence.getSizeT(); T++)
+            {
+                for (int Z = 0; Z < sequence.getSizeZ(); Z++)
+                {
+
+                    if (!(path.contains(".csv")))
+                    {
+                        path = path.concat(".csv");
+                    }
+
+                    pathchanged = path.replace(".csv",
+                            '_' + "t" + new Integer(T).toString() + '_' + "z" + new Integer(Z).toString() + ".csv");
+                    saveImageData(pathchanged, sequence, T, Z);
+
+                }
+            }
+        }
+
+    }
+}