diff --git a/src/data/coords/circleCoords.ts b/src/data/coords/circleCoords.ts
index 6209cd4293cf5784972a0f692ff7dc88da76921d..98e08477ddc56334a677f7acc6f03a28e98acd6b 100644
--- a/src/data/coords/circleCoords.ts
+++ b/src/data/coords/circleCoords.ts
@@ -14,7 +14,7 @@ export class CircleCoords implements Coords {
         return new paper.Rectangle(this.center.x - this.radius, this.center.y - this.radius, this.radius * 2, this.radius * 2);
     }
 
-    toPath(): paper.Path {
+    toRemovedPath(): paper.Path {
         return new paper.Path.Circle(this.center, this.radius);
     }
 
diff --git a/src/data/coords/coords.tsx b/src/data/coords/coords.tsx
index d198ca939c44e62e68d52472cd98b4a216b8900d..4169b90a954d68cc45d5d11d2138f4600c841b03 100644
--- a/src/data/coords/coords.tsx
+++ b/src/data/coords/coords.tsx
@@ -1,4 +1,5 @@
 import * as paper from "paper";
+import {PathCoords} from "./pathCoords";
 
 
 /**
@@ -15,5 +16,6 @@ export interface Coords {
     /**
      * Un paper.Path representatif des coodonnées
      */
-    toPath() : paper.Path;
+    toRemovedPath() : paper.Path;
+
 }
\ No newline at end of file
diff --git a/src/data/coords/ellipseCoords.ts b/src/data/coords/ellipseCoords.ts
index 0408a0528de8c745efbe87434db9a59bcbb99152..d2598f504bd2d36548beb8f91e7a71d31cf6701c 100644
--- a/src/data/coords/ellipseCoords.ts
+++ b/src/data/coords/ellipseCoords.ts
@@ -10,10 +10,10 @@ export class EllipseCoords implements Coords {
     }
 
     bounds(): paper.Rectangle {
-        return this.toPath().bounds;
+        return this.toRemovedPath().bounds;
     }
 
-    toPath(): paper.Path {
+    toRemovedPath(): paper.Path {
         let path = new paper.Path.Ellipse(new paper.Rectangle(
                 new paper.Point(this.center.x - this.radiusX, this.center.y - this.radiusY),
                 new paper.Size(2 * this.radiusX, 2 * this.radiusY)
diff --git a/src/data/coords/pathCoords.ts b/src/data/coords/pathCoords.ts
new file mode 100644
index 0000000000000000000000000000000000000000..60498098cd9ea4f5a82d72fffa57472bf89318fe
--- /dev/null
+++ b/src/data/coords/pathCoords.ts
@@ -0,0 +1,40 @@
+import * as paper from "paper";
+import {Coords} from "./coords";
+
+/**
+ * Distance en dessous de la quelle on considère que le path est fermé
+ */
+const CLOSING_DISTANCE = 10;
+
+/**
+ * Etend les types de paper avec un cercle (centre + rayon)
+ */
+export class PathCoords implements Coords {
+
+    public constructor(public points : paper.Point[] = []) {
+    }
+
+    bounds(): paper.Rectangle {
+        return this.toRemovedPath().bounds;
+    }
+
+    toRemovedPath(): paper.Path {
+        let path = new paper.Path();
+        path.remove();
+        this.points.forEach((point) => {
+            path.add(point)
+        })
+        return path;
+    }
+
+    /**
+     * Indique si le masque est fermé (le dernier point est proche du premier)
+     */
+    public isClosed() : boolean {
+        let path = this.toRemovedPath();
+        return !path.isEmpty()
+            && (path.bounds.width > CLOSING_DISTANCE || path.bounds.height > CLOSING_DISTANCE)
+            && path.firstSegment.point.getDistance(path.lastSegment.point) < CLOSING_DISTANCE;
+    }
+
+}
\ No newline at end of file
diff --git a/src/data/coords/pathCoords.tsx b/src/data/coords/pathCoords.tsx
deleted file mode 100644
index 78c0074d3c0a91862b67c0d6a1545793f22525ec..0000000000000000000000000000000000000000
--- a/src/data/coords/pathCoords.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import * as paper from "paper";
-import {Coords} from "./coords";
-
-/**
- * Distance en dessous de la quelle on considère que le path est fermé
- */
-const CLOSING_DISTANCE = 10;
-
-/**
- * Etend les types de paper avec un cercle (centre + rayon)
- */
-export class PathCoords implements Coords {
-
-    public constructor(public path : paper.Path) {
-    }
-
-    bounds(): paper.Rectangle {
-        return this.path.bounds;
-    }
-
-    toPath(): paper.Path {
-        const result = this.path.clone();
-        result.remove();
-        return result;
-    }
-
-    /**
-     * Indique si le masque est fermé (le dernier point est proche du premier)
-     */
-    public isClosed() : boolean {
-        return !this.path.isEmpty()
-            && (this.path.bounds.width > CLOSING_DISTANCE || this.path.bounds.height > CLOSING_DISTANCE)
-            && this.path.firstSegment.point.getDistance(this.path.lastSegment.point) < CLOSING_DISTANCE;
-    }
-
-}
\ No newline at end of file
diff --git a/src/data/coords/transform/toConvexHull.ts b/src/data/coords/transform/toConvexHull.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a3fc45a92449ffb07393a3501b6210c4c13f7203
--- /dev/null
+++ b/src/data/coords/transform/toConvexHull.ts
@@ -0,0 +1,90 @@
+import {PathCoords} from "../pathCoords";
+import {Transformation} from "./transformation";
+
+enum Orientation {
+    Collinear = 0,
+    Clockwise = 1,
+    Counterclockwise= 2
+}
+
+/**
+ * Génère une coque convexe
+ * Jarvis’s Algorithm or Wrapping
+ * @see https://www.geeksforgeeks.org/convex-hull-set-1-jarviss-algorithm-or-wrapping/
+ */
+export class ToConvexHull implements Transformation<PathCoords, PathCoords> {
+
+    transform(pathCoords: PathCoords): PathCoords {
+        return new PathCoords(this.convexHull(pathCoords.points));
+    }
+
+    /**
+     *
+     * Prints convex hull of a set of n points.
+     */
+    private convexHull(points : paper.Point[]) : paper.Point[] {
+        if (points.length < 3) {
+            return points;
+        }
+
+        // Initialize Result
+        let hull = [];
+
+        // Find the leftmost point
+        let startIndex = 0;
+        for (let i = 1; i < points.length; i++) {
+            if (points[i].x < points[startIndex].x) {
+                startIndex = i;
+            }
+        }
+
+        // Start from leftmost point, keep moving
+        // counterclockwise until reach the start point
+        // again. This loop runs O(h) times where h is
+        // number of points in result or output.
+        let p = startIndex;
+        do {
+
+            // Add current point to result
+            hull.push(points[p]);
+
+            // Search for a point 'q' such that
+            // orientation(p, q, x) is counterclockwise
+            // for all points 'x'. The idea is to keep
+            // track of last visited most counterclock-
+            // wise point in q. If any point 'i' is more
+            // counterclock-wise than q, then update q.
+            let q = (p + 1) % points.length;
+
+            for (let i = 0; i < points.length; i++) {
+                // If i is more counterclockwise than
+                // current q, then update q
+                if (this.orientation(points[p], points[i], points[q]) == Orientation.Counterclockwise) {
+                    q = i;
+                }
+            }
+
+            // Now q is the most counterclockwise with
+            // respect to p. Set p as q for next iteration,
+            // so that q is added to result 'hull'
+            p = q;
+
+        } while (p != startIndex); // While we don't come to first point
+
+        return hull;
+    }
+
+    /**
+     * To find orientation of ordered triplet (p, q, r)
+     */
+    private orientation(p : paper.Point, q : paper.Point, r : paper.Point) : Orientation {
+        let val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
+        if (val == 0) {
+            return Orientation.Collinear;
+        } else if (val > 0) {
+            return Orientation.Clockwise;
+        } else {
+            return Orientation.Counterclockwise;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/data/coords/transform/ellipseFitter.ts b/src/data/coords/transform/toEllipseFitter.ts
similarity index 97%
rename from src/data/coords/transform/ellipseFitter.ts
rename to src/data/coords/transform/toEllipseFitter.ts
index 7ce261be247ace7a43e00f3b115826e7c31d9ea3..d3a683b315375c717d860e597a456157c17d6683 100644
--- a/src/data/coords/transform/ellipseFitter.ts
+++ b/src/data/coords/transform/toEllipseFitter.ts
@@ -13,7 +13,7 @@ const  HALFPI  : number= 1.5707963267949;
 /**
  * Adaptation de EllipseFitter.java de ImageJ
  */
-export class EllipseFitter implements Transformation<PathCoords, Coords>{
+export class ToEllipseFitter implements Transformation<PathCoords, Coords>{
 
     private bitCount : number = 0;
     private xsum : number = 0;
@@ -54,7 +54,7 @@ export class EllipseFitter implements Transformation<PathCoords, Coords>{
         let  theta : number;
 
 
-        const path = from.toPath();
+        const path = from.toRemovedPath();
         let  bounds = path.bounds;
         this.left = Math.round(bounds.x);
         this.top = Math.round(bounds.y);
@@ -113,7 +113,7 @@ export class EllipseFitter implements Transformation<PathCoords, Coords>{
         xCenter = this.left + xoffset + 0.5;
         yCenter = this.top + yoffset + 0.5;
 
-        return new EllipseCoords(new paper.Point(xCenter, yCenter),  major / 2,  minor / 2, -angle);
+        return new EllipseCoords(new paper.Point(xCenter, yCenter),  major / 2,  minor / 2, angle);
     }
 
     private  computeSums (path : paper.Path)  : void {
diff --git a/src/data/coords/vectorCoords.ts b/src/data/coords/vectorCoords.ts
index fa8c45da406337863ad406db07ecf51f7f8f8431..40025b1fe177ccbd57a741d45000850f6884a862 100644
--- a/src/data/coords/vectorCoords.ts
+++ b/src/data/coords/vectorCoords.ts
@@ -22,7 +22,7 @@ export class VectorCoords implements Coords {
         return this.end.subtract(this.start);
     }
 
-    toPath(): paper.Path {
+    toRemovedPath(): paper.Path {
         return new paper.Path.Line(this.start, this.end);
     }
 
diff --git a/src/data/dataExporter.ts b/src/data/dataExporter.ts
index 705d8a18bfe500a7fbf122a60fb6e57710d15f57..e9fd78e3e53f8b0712f4c9563274e72e337de524 100644
--- a/src/data/dataExporter.ts
+++ b/src/data/dataExporter.ts
@@ -2,9 +2,11 @@
  * Utilitaire d'export des données
  */
 import {LabData} from "../lab";
-import {EllipseFitter} from "./coords/transform/ellipseFitter";
+import {ToEllipseFitter} from "./coords/transform/toEllipseFitter";
 import {Coords} from "./coords/coords";
 import {MathUtils} from "../utils/mathUtils";
+import {ToConvexHull} from "./coords/transform/toConvexHull";
+import {PathCoords} from "./coords/pathCoords";
 
 const ROUNDING_DECIMALS = 3;
 
@@ -14,14 +16,11 @@ export class DataExporter {
      * Transforme un Path en CSV
      */
     public exportPathAsXYCsv(coords : Coords, close : boolean) : string {
-        const path = coords.toPath();
-        if(close) {
-            path.closePath();
-        }
+        const path = coords.toRemovedPath();
         let data = "";
-        for (let i = 0; i < path.length; i++) {
-            let point = path.getPointAt(i);
-            data += Math.round(point.x) + "\t" + Math.round(point.y) + "\n";
+        for (let i = 0; i < path.segments.length; i++) {
+            let segment = path.segments[i];
+            data += Math.round(segment.point.x) + "\t" + Math.round(segment.point.y) + "\n";
         }
         return data;
     }
@@ -29,13 +28,14 @@ export class DataExporter {
     /**
      * Transforme un Path en CSV
      */
-    public exportPathDescriptorsAsCsv(labData : LabData, coords : Coords) : string {
-        let path = coords.toPath();
+    public exportPathDescriptorsAsCsv(labData : LabData, coords : PathCoords) : string {
+        let path = coords.toRemovedPath();
         path.closePath();
 
         let linearScale = labData.rulerCoords.distance() / labData.rulerTickCount; // pixels/cm
         let areaScale = Math.pow(linearScale, 2);
-        let fittingEllipse = new EllipseFitter().transform(coords);
+        let fittingEllipse = new ToEllipseFitter().transform(coords);
+        let convexHull = new ToConvexHull().transform(coords);
 
         let line = 1;
         let label = labData.filename;
@@ -44,7 +44,7 @@ export class DataExporter {
         let circularity = 4 * Math.PI * area / Math.pow(perimeter, 2);
         let ar = fittingEllipse.getMajorAxis() / fittingEllipse.getMinorAxis();
         let round = 4 * area / (Math.PI * fittingEllipse.getMajorAxis());
-        let solid = "todo";
+        let solid = area / (convexHull.toRemovedPath().area / areaScale);
 
         let headers : string[] = [ " ", "Label", "Area", "Perim.", "Circ.","AR","Round","Solidity"];
         let data = [ line,
@@ -54,7 +54,7 @@ export class DataExporter {
             MathUtils.round(circularity, ROUNDING_DECIMALS),
             MathUtils.round(ar, ROUNDING_DECIMALS),
             MathUtils.round(round, ROUNDING_DECIMALS),
-            solid,
+            MathUtils.round(solid, ROUNDING_DECIMALS),
         ]
 
         return headers.join(",") + "\n" + data.join(",");
diff --git a/src/instruments/blobMask.ts b/src/instruments/blobMask.ts
index 53d95742559a7d14e11c1da5b07f4b5a276c095b..f89847a77474d4afb96d96bb064b1b031a29cc59 100644
--- a/src/instruments/blobMask.ts
+++ b/src/instruments/blobMask.ts
@@ -2,22 +2,29 @@ import * as paper from "paper";
 import {AbstractInstrument, Handle, Instrument} from "./instrument";
 import {PathCoords} from "../data/coords/pathCoords";
 import {DEBUG_MODE, Lab} from "../lab";
-import {EllipseFitter} from "../data/coords/transform/ellipseFitter";
+import {ToEllipseFitter} from "../data/coords/transform/toEllipseFitter";
+import {PaperUtils} from "../utils/paperUtils";
+import {ToConvexHull} from "../data/coords/transform/toConvexHull";
 
 /**
  * Représente la boîte de Petri
  */
 export class BlobMask extends AbstractInstrument<PathCoords> implements Instrument {
 
+    /**
+     * Garde l'état fermé ou pas
+     */
+    private wasClosed: boolean = false;
+
     /**
      * Appelé lorsque le tracé est fermé
      */
-    public onClosed : () => void = () => {};
+    public onClose : () => void = () => {};
 
     /**
      * Appelé lorsque le tracé s'ouvre
      */
-    public onOpened : () => void = () => {};
+    public onOpen : () => void = () => {};
 
     public constructor(protected lab : Lab, coords : PathCoords) {
         super(lab, coords, [
@@ -26,14 +33,38 @@ export class BlobMask extends AbstractInstrument<PathCoords> implements Instrume
     }
 
     drawIn(coords: PathCoords, group: paper.Group) {
-        let line = coords.path.clone();
+        let line = coords.toRemovedPath();
         group.addChild(line);
+    }
+
+    /**
+     * Surcharge pour gérer l'état fermé ouvert du tracé
+     */
+    refresh() {
+        super.refresh();
+        let isClosed = this.coords.isClosed();
+        if(!this.wasClosed && isClosed) {
+            this.onClose();
+
+        } else if(this.wasClosed && !isClosed) {
+            this.onOpen();
+        }
+        this.wasClosed = isClosed;
 
         if(DEBUG_MODE) {
-            if(line.length > 10) {
-                const pathCoords = new PathCoords(line.clone());
-                group.addChild(new EllipseFitter().transform(pathCoords).toPath());
+            if(this.drawGroup.bounds.area > 10) {
+                let fittedEllipse = new ToEllipseFitter().transform(this.coords).toRemovedPath();
+                fittedEllipse.strokeColor = new paper.Color("red");
+                fittedEllipse.strokeWidth = PaperUtils.absoluteDimension(2);
+                fittedEllipse.dashArray = [10, 12];
+                this.drawGroup.addChild(fittedEllipse);
             }
+
+            let convexHull = new ToConvexHull().transform(this.coords).toRemovedPath();
+            convexHull.strokeColor = new paper.Color("red");
+            convexHull.strokeWidth = PaperUtils.absoluteDimension(2);
+            convexHull.dashArray = [10, 12];
+            this.drawGroup.addChild(convexHull);
         }
 
     }
@@ -44,10 +75,10 @@ export class BlobMask extends AbstractInstrument<PathCoords> implements Instrume
 
     locateHandle(coords: PathCoords, handle: Handle): paper.Point {
         if(handle.name == "startHandle") {
-            if(coords.path.isEmpty()) {
+            if(coords.points.length == 0) {
                 return null;
             } else {
-                return coords.path.firstSegment.point;
+                return coords.points[0];
             }
         }
         throw new Error("Unknown handle");
@@ -71,12 +102,8 @@ export class BlobMask extends AbstractInstrument<PathCoords> implements Instrume
             return true;
         }
         if(!this.coords.isClosed()) { // Une fois la boucle fermée, on ne peut plus ajouter de
-            this.coords.path.add(event.point)
-            if(this.coords.isClosed()) {
-                this.onClosed();
-            }
+            this.coords.points.push(event.point)
         }
-
         this.refresh();
         return true;
     }
@@ -95,7 +122,7 @@ export class BlobMask extends AbstractInstrument<PathCoords> implements Instrume
      * Supprime quelques derniers points
      */
     public undo() {
-        this._undo(Math.max(this.coords.path.segments.length - 5, 0));
+        this._undo(Math.max(this.coords.points.length - 5, 0));
     }
 
     /**
@@ -109,11 +136,7 @@ export class BlobMask extends AbstractInstrument<PathCoords> implements Instrume
      * En charge de la suppression
      */
     private _undo(from : number) {
-        let wasClosed = this.coords.isClosed();
-        this.coords.path.removeSegments(from);
-        if(wasClosed) {
-            this.onOpened();
-        }
+        this.coords.points = this.coords.points.slice(0, from);
         this.refresh();
     }
 
diff --git a/src/instruments/instrument.ts b/src/instruments/instrument.ts
index a1e4871498d3bf08b5d5cfffeebe8bd90f22b01c..bc1d9f953fdb7bbb1962f01ebe69745766cccf9a 100644
--- a/src/instruments/instrument.ts
+++ b/src/instruments/instrument.ts
@@ -1,7 +1,8 @@
 import * as paper from "paper";
-import {Lab} from "../lab";
+import {DEBUG_MODE, Lab} from "../lab";
 import {Coords} from "../data/coords/coords";
 import {PaperUtils} from "../utils/paperUtils";
+import {ToEllipseFitter} from "../data/coords/transform/toEllipseFitter";
 
 /**
  * Un instrument d'analyse
@@ -59,7 +60,7 @@ export abstract class AbstractInstrument<C extends Coords> implements Instrument
     /**
      * Contient le dessin de l'instrument
      */
-    private drawGroup : paper.Group = new paper.Group();
+    protected drawGroup : paper.Group = new paper.Group();
 
     protected constructor(protected lab : Lab, protected coords : C,  protected handles : Handle[]) {
     }
diff --git a/src/instruments/petriDish.ts b/src/instruments/petriDish.ts
index 197e49b9d1ca2bd5f6f43b085790ecca9c7fc933..8095574dab34aa6d5d5add340fd70892a35ee285 100644
--- a/src/instruments/petriDish.ts
+++ b/src/instruments/petriDish.ts
@@ -18,7 +18,7 @@ export class PetriDish extends AbstractInstrument<EllipseCoords> implements Inst
     }
 
     drawIn(coords : EllipseCoords, group: paper.Group) {
-        group.addChild(coords.toPath());
+        group.addChild(coords.toRemovedPath());
     }
 
     onHandleMove(coords: EllipseCoords, handle: Handle, point: paper.Point, delta: paper.Point): void {
diff --git a/src/lab.tsx b/src/lab.tsx
index a24f7202f1e667ba8dbb740c880fcaad62e47a66..49c147881bc0f253cdedaf2534ad5b8c6a9ab667 100644
--- a/src/lab.tsx
+++ b/src/lab.tsx
@@ -18,10 +18,9 @@ import {EllipseCoords} from "./data/coords/ellipseCoords";
 /**
  * Debug mode (ou pas)
  */
-export const DEBUG_MODE = false;
+export const DEBUG_MODE = true;
 
 export interface LabData {
-
     pictureSize : paper.Size,
 
     filename : string,
@@ -144,7 +143,6 @@ export class Lab extends React.Component<{}> {
         let width = image.naturalWidth;
         let height = image.naturalHeight;
         this.data = {
-
             pictureSize: new paper.Size(width, height),
 
             filename: filename,
@@ -155,8 +153,7 @@ export class Lab extends React.Component<{}> {
 
             petriDishCoords: new EllipseCoords(new paper.Point(width / 2, height / 2), width * 0.75 / 2, width * 0.75 / 2, 0),
 
-            blobMaskCoords: new PathCoords(new paper.Path()),
-
+            blobMaskCoords: new PathCoords(),
         };
 
         // Le plus en dessous en premier
@@ -258,9 +255,9 @@ export class Lab extends React.Component<{}> {
      * Appelé lorsque le zoom a changé
      */
     private onZoomChanged() {
-        this.ruler.refresh();
-        this.petriDish.refresh();
-        this.blobMask.refresh();
+        this.ruler?.refresh();
+        this.petriDish?.refresh();
+        this.blobMask?.refresh();
     }
 
     render(): React.ReactNode {
diff --git a/src/steps/downloadStep.tsx b/src/steps/downloadStep.tsx
index 98fdc45c3385b02cdb59b009395314f911c26a62..4e76e0b11d7c25803a647b6e90ecf429829f732f 100644
--- a/src/steps/downloadStep.tsx
+++ b/src/steps/downloadStep.tsx
@@ -83,10 +83,8 @@ export class DownloadStep extends Step<DownloadStepState> {
      * Téléchargement des données du mask
      */
     private downloadBlobMaskData() : void {
-        let path = new paper.Path(this.props.lab.data.blobMaskCoords.path.segments);
-        path.closed = true; // ferme le contour
         let data = this.dataExporter.exportPathAsXYCsv(this.props.lab.data.blobMaskCoords, true);
-        IoUtils.downloadData(this.state.petriDishDataFilename, "text/plain;charset=UTF-8", data);
+        IoUtils.downloadData(this.state.blobMaskDataFilename, "text/plain;charset=UTF-8", data);
     }
 
     /**
@@ -100,7 +98,7 @@ export class DownloadStep extends Step<DownloadStepState> {
 
         renderingGroup.addChild(background)
 
-        let path = this.props.lab.data.blobMaskCoords.toPath();
+        let path = this.props.lab.data.blobMaskCoords.toRemovedPath();
         path.closed = true;
         path.fillColor = new paper.Color("white");
         path.strokeColor = null;
diff --git a/src/steps/drawBlobMaskStep.tsx b/src/steps/drawBlobMaskStep.tsx
index 420681fa34db1b190892ad0c79ecb547339aeffa..858a293aa0763775fa9dcf6237a384b956a9d52e 100644
--- a/src/steps/drawBlobMaskStep.tsx
+++ b/src/steps/drawBlobMaskStep.tsx
@@ -1,6 +1,10 @@
 import {Step, StepProps, StepState} from "./step";
 import * as React from "react";
+import * as paper from "paper";
 import {Alert, Button} from "react-bootstrap";
+import {IoUtils} from "../utils/ioUtils";
+import {DEBUG_MODE} from "../lab";
+import {StringUtils} from "../utils/stringUtils";
 
 
 interface DrawBlobMaskStepState extends StepState {
@@ -24,10 +28,10 @@ export class DrawBlobMaskStep extends Step<DrawBlobMaskStepState> {
 
     onActivation(): void {
         this.props.lab.blobMask.activate();
-        this.props.lab.blobMask.onClosed = () => {
+        this.props.lab.blobMask.onClose = () => {
             this.setState({closed: true });
         };
-        this.props.lab.blobMask.onOpened = () => {
+        this.props.lab.blobMask.onOpen = () => {
             this.setState({closed: false });
         };
         this.props.lab.zoomOn( this.props.lab.data.petriDishCoords.bounds(), 0.05);
@@ -37,6 +41,23 @@ export class DrawBlobMaskStep extends Step<DrawBlobMaskStepState> {
         this.props.lab.blobMask.deactivate();
     }
 
+    loadData(): void {
+        IoUtils.openTextFile(
+            (text : string) => {
+                console.info("text loaded")
+                this.props.lab.data.blobMaskCoords.points = [];
+                let lines = StringUtils.splitLines(text);
+                lines.filter(line => line.trim().length > 0).forEach(
+                    (line : string) => {
+                        let [x, y] = line.split("\t");
+                        this.props.lab.data.blobMaskCoords.points.push(new paper.Point(Number(x), Number(y)));
+                    }
+                );
+                // this.props.lab.data.blobMaskCoords.points.push(this.props.lab.data.blobMaskCoords.points[0]);
+                this.props.lab.blobMask.refresh();
+            });
+    }
+
     render() : React.ReactNode {
         return <div>
             <div>
@@ -49,6 +70,13 @@ export class DrawBlobMaskStep extends Step<DrawBlobMaskStepState> {
                 <Button className={"col-3"} variant={"success"} disabled={!this.state.active || !this.state.closed} onClick={this.terminate.bind(this)}>
                     <span hidden={!this.state.closed}><i className="fa-solid fa-hands-clapping fa-beat-fade me-2"></i></span>Fini !
                 </Button>
+                {DEBUG_MODE ?
+                    <Button className={"ms-2 col-4"} variant={"danger"} disabled={!this.state.active}
+                            onClick={this.loadData.bind(this)}>
+                        <i className="fa-solid fa-bug"></i> Charger XY
+                    </Button>
+                    : <></>
+                }
             </div>
         </div>
     }
diff --git a/src/utils/ioUtils.ts b/src/utils/ioUtils.ts
index 3266333ea588e0511b004e008f107e0c4eb58a8e..a955a0a6225eab1074f46a9b98358552e683d606 100644
--- a/src/utils/ioUtils.ts
+++ b/src/utils/ioUtils.ts
@@ -3,6 +3,29 @@
  */
 export class IoUtils {
 
+    /**
+     * Ouvre un chargement
+     */
+    public static openTextFile(onTextLoad : (text: string) => void) : void {
+        let input : HTMLInputElement = document.createElement('input');
+        input.type = 'file';
+        input.accept = '.txt';
+        input.onchange = (e: InputEvent)  => {
+            // getting a hold of the file reference
+            var file = (e.target as HTMLInputElement).files[0];
+
+            // setting up the reader
+            let reader = new FileReader();
+            reader.readAsText(file,'UTF-8');
+            // here we tell the reader what to do when it's done reading...
+            reader.onload = readerEvent => {
+                onTextLoad(readerEvent.target.result as string);
+            }
+
+        }
+        input.click();
+    }
+
     /**
      * Donne le nom de fichier sans extension
      */
diff --git a/src/utils/stringUtils.ts b/src/utils/stringUtils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a0ab7287d09f10da8adae1f93464bae5ea503466
--- /dev/null
+++ b/src/utils/stringUtils.ts
@@ -0,0 +1,14 @@
+/**
+ * Utilitaires
+ */
+export class StringUtils {
+
+    /**
+     * Découpe en multi-ligne
+     */
+    public static splitLines(text: string) : string[] {
+        return text.split(/\r?\n/);
+    }
+
+
+}
\ No newline at end of file