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..e61cd1639e0e43c1147a81f2a40564739ff73cb3
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,92 @@
+<?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>scale-bar</artifactId>
+    <version>3.1.6</version>
+
+    <packaging>jar</packaging>
+
+    <name>Scale Bar</name>
+    <description>
+        Displays a scale bar overlay on the sequence.
+        Warning: this plugin needs correct sequence metadata to be effective. Otherwise it will display wrong values.
+    </description>
+    <url>http://icy.bioimageanalysis.org/plugin/scale-bar/</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>
+
+        <!-- The EzPlug library, simplifies writing UI for Icy plugins. -->
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>ezplug</artifactId>
+        </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/tprovoost/scale/Scale.java b/src/main/java/plugins/tprovoost/scale/Scale.java
new file mode 100644
index 0000000000000000000000000000000000000000..af5f315e38bb02b0c8311a2d50de3a06eea6d881
--- /dev/null
+++ b/src/main/java/plugins/tprovoost/scale/Scale.java
@@ -0,0 +1,56 @@
+package plugins.tprovoost.scale;
+
+import icy.gui.main.GlobalSequenceListener;
+import icy.main.Icy;
+import icy.plugin.abstract_.Plugin;
+import icy.plugin.interface_.PluginDaemon;
+import icy.sequence.Sequence;
+
+public class Scale extends Plugin implements PluginDaemon
+{
+    ScalePainter sp;
+    GlobalSequenceListener globalSequenceListener;
+
+    @Override
+    public void run()
+    {
+        // nothing to do here
+    }
+
+    @Override
+    public void stop()
+    {
+        for (Sequence sequence : Icy.getMainInterface().getSequences())
+            sequence.removeOverlay(sp);
+
+        Icy.getMainInterface().removeGlobalSequenceListener(globalSequenceListener);
+    }
+
+    @Override
+    public void init()
+    {
+        // create painter
+        sp = new ScalePainter();
+        globalSequenceListener = new GlobalSequenceListener()
+        {
+            @Override
+            public void sequenceOpened(Sequence sequence)
+            {
+                sequence.addOverlay(sp);
+            }
+
+            @Override
+            public void sequenceClosed(Sequence sequence)
+            {
+                sequence.removeOverlay(sp);
+            }
+        };
+
+        // add the Scale Bar overlay on opened sequences
+        for (Sequence sequence : Icy.getMainInterface().getSequences())
+            sequence.addOverlay(sp);
+
+        // listen new opened sequence
+        Icy.getMainInterface().addGlobalSequenceListener(globalSequenceListener);
+    }
+}
diff --git a/src/main/java/plugins/tprovoost/scale/ScalePainter.java b/src/main/java/plugins/tprovoost/scale/ScalePainter.java
new file mode 100644
index 0000000000000000000000000000000000000000..af4f9ce1b0e19fd317131b0a09148e3a9d765b2e
--- /dev/null
+++ b/src/main/java/plugins/tprovoost/scale/ScalePainter.java
@@ -0,0 +1,159 @@
+package plugins.tprovoost.scale;
+
+import icy.canvas.IcyCanvas;
+import icy.canvas.IcyCanvas2D;
+import icy.math.MathUtil;
+import icy.math.UnitUtil;
+import icy.math.UnitUtil.UnitPrefix;
+import icy.painter.Overlay;
+import icy.sequence.Sequence;
+import icy.util.GraphicsUtil;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.Stroke;
+
+public class ScalePainter extends Overlay
+{
+    /**
+     * Possible rounded scale factors : 1 --> 900
+     */
+    final static double[] scaleRoundedFactors = new double[] {1d, 2d, 3d, 4d, 5d, 6d, 7d, 8d, 9d, 10d, 20d, 30d, 40d,
+            50d, 60d, 70d, 80d, 90d, 100d, 200d, 300d, 400d, 500d, 600d, 700d, 800d, 900d};
+
+    public ScalePainter()
+    {
+        super("Scale Bar");
+    }
+
+    @Override
+    public void paint(Graphics2D g2, Sequence sequence, IcyCanvas canvas)
+    {
+        if (g2 == null)
+            return;
+        if (!(canvas instanceof IcyCanvas2D))
+            return;
+
+        final IcyCanvas2D c2d = (IcyCanvas2D) canvas;
+        final Graphics2D g = (Graphics2D) g2.create();
+
+        double scaleFactor = c2d.getScaleX();
+        g.transform(c2d.getInverseTransform());
+
+        BasicStroke[] stroke = new BasicStroke[4];
+        stroke[0] = new BasicStroke(2f);
+        stroke[1] = new BasicStroke(3f);
+        stroke[2] = new BasicStroke(4f);
+        stroke[3] = new BasicStroke(5f);
+        int w = canvas.getCanvasSizeX();
+        int h = canvas.getCanvasSizeY();
+        double pxSize = sequence.getPixelSizeX();
+        int space = 20; // spacing from borders
+
+        int sizeW = w / 8;
+        // get the value with the best display possible
+        double valueReal = sizeW * pxSize / scaleFactor / 10;
+        UnitPrefix bestUnit = UnitUtil.getBestUnit(valueReal, UnitPrefix.MICRO, 1);
+        double valueRealBestUnit = UnitUtil.getValueInUnit(valueReal * 10, UnitPrefix.MICRO, bestUnit);
+
+        double closestScale = MathUtil.closest(valueRealBestUnit, scaleRoundedFactors);
+
+        // closest scale in px
+        int closestScPx = (int) (UnitUtil.getValueInUnit(closestScale, bestUnit, UnitPrefix.MICRO) / pxSize * scaleFactor);
+        // int closestScPx = closestScale;
+
+        g.setColor(Color.BLACK);
+        g.setStroke(stroke[3]);
+        // g.drawLine(w - space - closestScPx, h - space, w - space, h - space);
+        g.drawLine(space, h - space, space + closestScPx, h - space);
+
+        g.setColor(Color.WHITE);
+        g.setStroke(stroke[2]);
+        g.drawLine(space, h - space, space + closestScPx, h - space);
+
+        int fontSize = 14;
+        Font font = new Font("Arial", Font.PLAIN, fontSize);
+        g.setFont(font);
+        String pixelString = "" + closestScale + " " + bestUnit + "m";
+        int txW = g.getFontMetrics().charsWidth(pixelString.toCharArray(), 0, pixelString.length());
+        int txH = g.getFontMetrics().getHeight();
+
+        g.setColor(Color.black);
+        // GraphicsUtil.drawString(g, pixelString, w - space - closestScPx / 2 -
+        // txW / 2, h - space - txH, true);
+        GraphicsUtil.drawString(g, pixelString, space + closestScPx / 2 - txW / 2, h - space - txH, true);
+
+        g.dispose();
+    }
+
+    double convertScale(IcyCanvas canvas, double value)
+    {
+        return canvas.canvasToImageLogDeltaX((int) value);
+    }
+
+    public class CompositeStroke implements Stroke
+    {
+        private Stroke stroke1, stroke2;
+
+        public CompositeStroke(Stroke stroke1, Stroke stroke2)
+        {
+            this.stroke1 = stroke1;
+            this.stroke2 = stroke2;
+        }
+
+        @Override
+        public Shape createStrokedShape(Shape shape)
+        {
+            return stroke2.createStrokedShape(stroke1.createStrokedShape(shape));
+        }
+    }
+
+//    private int findBestScale(IcyCanvas2D canvas, Sequence s)
+//    {
+//        int w = s.getWidth();
+//        int minSize = w / 8;
+//        int maxSize = w / 4;
+//        double pxSize = s.getPixelSizeX();
+//        double tab[] = new double[maxSize - minSize];
+//        double scaleFactor = canvas.getScaleX();
+//
+//        // generate all values
+//        for (int i = minSize; i < maxSize; ++i)
+//        {
+//
+//            // get the value with the best display possible
+//            double valueReal = i * pxSize / scaleFactor;
+//            UnitPrefix bestUnit = UnitUtil.getBestUnit(valueReal, UnitPrefix.MICRO, 1);
+//            double bestValue = UnitUtil.getValueInUnit(valueReal, UnitPrefix.MICRO, bestUnit);
+//            bestValue = ((int) (bestValue * 100)) / 100d;
+//
+//            tab[i - minSize] = bestValue;
+//        }
+//
+//        // return the first value with a round value
+//        for (int i = 0; i < maxSize - minSize; ++i)
+//        {
+//            double bestValue = tab[i];
+//            if (bestValue == (int) bestValue)
+//            {
+//                return i + minSize;
+//            }
+//        }
+//
+//        // otherwise, return first value with only one decimal
+//        for (int i = 0; i < maxSize - minSize; ++i)
+//        {
+//            double bestValue = tab[i];
+//            if (bestValue == ((int) (bestValue * 10)) / 10d)
+//            {
+//                return i + minSize;
+//            }
+//        }
+//
+//        // otherwise, return w / 4
+//        return w / 4;
+//    }
+}
diff --git a/src/main/java/plugins/tprovoost/scale/ScalePainterOld.java b/src/main/java/plugins/tprovoost/scale/ScalePainterOld.java
new file mode 100644
index 0000000000000000000000000000000000000000..caf0c37945f25f8037de04c34b7d146ec29fdd2a
--- /dev/null
+++ b/src/main/java/plugins/tprovoost/scale/ScalePainterOld.java
@@ -0,0 +1,105 @@
+package plugins.tprovoost.scale;
+
+import icy.canvas.IcyCanvas;
+import icy.canvas.IcyCanvas2D;
+import icy.math.UnitUtil;
+import icy.math.UnitUtil.UnitPrefix;
+import icy.painter.Overlay;
+import icy.roi.ROI2D;
+import icy.sequence.Sequence;
+import icy.util.GraphicsUtil;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.Stroke;
+
+public class ScalePainterOld extends Overlay
+{
+	public ScalePainterOld()
+	{
+		super("Scale Bar");
+	}
+
+	@Override
+	public void paint(Graphics2D g2, Sequence sequence, IcyCanvas canvas)
+	{
+		if (g2 == null)
+			return;
+		Graphics2D g = (Graphics2D) g2.create();
+		// g.transform(((IcyCanvas2D) canvas).getInverseTransform());
+		int w = sequence.getWidth();
+		int h = sequence.getHeight();
+		int sizeW = w / 10;
+		double pxSize = sequence.getPixelSizeX();
+		int spaceFBords = 20; // spacing from borders
+
+		BasicStroke[] stroke = new BasicStroke[4];
+		stroke[0] = new BasicStroke((float) canvas.canvasToImageLogDeltaX(2));
+		stroke[1] = new BasicStroke((float) canvas.canvasToImageLogDeltaX(3));
+		stroke[2] = new BasicStroke((float) canvas.canvasToImageLogDeltaX(4));
+		stroke[3] = new BasicStroke((float) canvas.canvasToImageLogDeltaX(5));
+
+		// get the value with the best display possible
+		double valueReal = sizeW * pxSize / 10;
+		UnitPrefix bestUnit = UnitUtil.getBestUnit(valueReal, UnitPrefix.MICRO, 1);
+		double bestValue = UnitUtil.getValueInUnit(valueReal * 10, UnitPrefix.MICRO, bestUnit);
+
+		// get the best scale possible
+		int closestScale = 0;
+		if (bestValue < 10)
+		{
+			closestScale = (int) bestValue;
+		} else
+			closestScale = (int) (bestValue / 10) * 10;
+
+		// closest scale in px
+		int closestScPx = (int) (UnitUtil.getValueInUnit(closestScale, bestUnit, UnitPrefix.MICRO) / pxSize);
+
+		g.setColor(Color.BLACK);
+		g.setStroke(stroke[3]);
+		g.drawLine(w - spaceFBords - closestScPx, h - spaceFBords, w - spaceFBords, h - spaceFBords);
+
+		g.setColor(Color.WHITE);
+		g.setStroke(stroke[2]);
+		g.drawLine(w - spaceFBords - closestScPx, h - spaceFBords, w - spaceFBords, h - spaceFBords);
+
+		int fontSize = (int) canvas.canvasToImageLogDeltaX(14);
+		Font font = new Font("Arial", Font.PLAIN, fontSize);
+		g.setFont(font);
+		String pixelString = "" + closestScale + " " + bestUnit + "m";
+		int txW = g.getFontMetrics().charsWidth(pixelString.toCharArray(), 0, pixelString.length());
+		int txH = g.getFontMetrics().getHeight();
+
+		// g.fillRect(w - spaceFBords - closestScPx / 2 - txW / 2, h -
+		// spaceFBords - txH, txW, txH);
+
+		g.setColor(Color.black);
+		GraphicsUtil.drawString(g, pixelString, w - spaceFBords - closestScPx / 2 - txW / 2, h - spaceFBords - txH, true);
+
+		g.dispose();
+	}
+
+	double convertScale(IcyCanvas canvas, double value)
+	{
+		return canvas.canvasToImageLogDeltaX((int) value);
+	}
+
+	public class CompositeStroke implements Stroke
+	{
+		private Stroke stroke1, stroke2;
+
+		public CompositeStroke(Stroke stroke1, Stroke stroke2)
+		{
+			this.stroke1 = stroke1;
+			this.stroke2 = stroke2;
+		}
+
+		public Shape createStrokedShape(Shape shape)
+		{
+			return stroke2.createStrokedShape(stroke1.createStrokedShape(shape));
+		}
+	}
+}
diff --git a/src/main/resources/Scale.png b/src/main/resources/Scale.png
new file mode 100644
index 0000000000000000000000000000000000000000..2227c16fad9f21113d628a11d5b912a4f42f1431
Binary files /dev/null and b/src/main/resources/Scale.png differ
diff --git a/src/main/resources/Scale.xml b/src/main/resources/Scale.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9a16e0be213bfede02c8022c11ac819abd1d518d
--- /dev/null
+++ b/src/main/resources/Scale.xml
@@ -0,0 +1,78 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<root>
+<url><![CDATA[http://icy.bioimageanalysis.org/repository/getXMLPluginFile.php?pluginId=179&beta=0]]></url><name>Scale Bar</name><version>2.0.0.0</version><required_kernel_version>1.3.6.0</required_kernel_version><kernel_ver>1.3.6.0</kernel_ver><jar_url><![CDATA[http://icy.bioimageanalysis.org/repository/getJarFile.php?pluginId=179&beta=0]]></jar_url><icon_url><![CDATA[http://bioimageanalysis.org/icy/image.php?idAttach=1229]]></icon_url><image_url><![CDATA[http://bioimageanalysis.org/icy/image.php?idAttach=2020]]></image_url><description><![CDATA[Displays a scale bar overlay on the sequence. Be advised, this plugin needs correct Metadata on the sequence to be effective or it will display wrong values.]]></description><classname><![CDATA[plugins.tprovoost.scale.Scale]]></classname><author><![CDATA[tprovoost - Thomas Provoost]]></author><changelog><![CDATA[-
+Version 2.0.0.0
+Date 2013-07-03 12:15:38
+
+* Bottom left now. This will make it avoid being invisible because of the zoom factor is displayed at the same time
+* the scale bar now fully works
+
+-
+Version 1.6.0.0
+Date 2013-07-03 12:02:48
+
+* Uses orders of magnitude instead of precise values.
+* size of scale bar never changes now: will always be : size of the canvas / 8.
+
+-
+Version 1.5.0.0
+Date 2013-06-26 16:52:26
+
+* Now only updates text while zooming, and change the size and value after the zoom
+
+-
+Version 1.4.0.0
+Date 2013-06-26 11:20:13
+
+* fixed bar location issue
+
+-
+Version 1.3.1.0
+Date 2013-06-17 15:18:23
+
+* removed debug information
+
+-
+Version 1.3.0.0
+Date 2013-06-17 15:17:46
+
+* now scales with images zoom
+
+-
+Version 1.2.0.0
+Date 2013-06-17 14:15:50
+
+* removed white rectangle
+* now shadow on text
+
+-
+Version 1.1.0.0
+Date 2013-01-11 16:30:30
+
+Updated to 1.3.0.0
+
+-
+Version 1.0.0.2
+Date 2012-10-22 17:10:43
+
+* corrected 3D issue.
+
+-
+Version 1.0.0.1
+Date 2012-07-03 09:23:11
+
+Corrected issue with compilation.
+
+-
+Version 1.0.0.0
+Date 2012-07-02 21:17:10
+
+Updated to Icy last version.
+
+-
+Version 0.0.1.0
+Date 2012-06-20 14:33:49
+
+
+
+]]></changelog><web><![CDATA[http://icy.bioimageanalysis.org/plugin/Scale_Bar]]></web><dependencies></dependencies></root>
\ No newline at end of file
diff --git a/src/main/resources/Scale_icon.png b/src/main/resources/Scale_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..46567ed34a2c5de77c00a72963814c1866260f07
Binary files /dev/null and b/src/main/resources/Scale_icon.png differ