From f6c7c853a52448c41c6b188b8ace2a4aa5bed64e Mon Sep 17 00:00:00 2001
From: arnaudlabourel <arnaud.labourel@univ-amu.fr>
Date: Fri, 17 Sep 2021 14:42:55 +0200
Subject: [PATCH] Correction version finale

---
 src/main/java/ByteGrayColor.java      | 37 ++++++++++---------
 src/main/java/CompositeTransform.java | 18 +++++++++
 src/main/java/CrissCross.java         | 26 +++++++++++++
 src/main/java/DecreaseGrayLevels.java | 28 ++++++++++++++
 src/main/java/Display.java            | 51 ++++++++++++++------------
 src/main/java/GrayColor.java          |  2 +
 src/main/java/GrayImage.java          |  3 +-
 src/main/java/Image.java              |  2 +-
 src/main/java/Invert.java             | 17 +++++++++
 src/main/java/Main.java               |  3 +-
 src/main/java/MatrixGrayImage.java    | 36 +++++++++---------
 src/main/java/Outline.java            | 48 ++++++++++++++++++++++++
 src/main/java/Pixelate.java           | 53 +++++++++++++++++++++++++++
 src/main/java/Transform.java          |  6 +++
 14 files changed, 268 insertions(+), 62 deletions(-)
 create mode 100755 src/main/java/CompositeTransform.java
 create mode 100755 src/main/java/CrissCross.java
 create mode 100755 src/main/java/DecreaseGrayLevels.java
 mode change 100644 => 100755 src/main/java/GrayColor.java
 mode change 100644 => 100755 src/main/java/GrayImage.java
 mode change 100644 => 100755 src/main/java/Image.java
 create mode 100755 src/main/java/Invert.java
 mode change 100644 => 100755 src/main/java/Main.java
 mode change 100644 => 100755 src/main/java/MatrixGrayImage.java
 create mode 100755 src/main/java/Outline.java
 create mode 100755 src/main/java/Pixelate.java
 create mode 100755 src/main/java/Transform.java

diff --git a/src/main/java/ByteGrayColor.java b/src/main/java/ByteGrayColor.java
index 63a28e9..bf54f4e 100644
--- a/src/main/java/ByteGrayColor.java
+++ b/src/main/java/ByteGrayColor.java
@@ -1,49 +1,44 @@
 import javafx.scene.paint.Color;
 
-/**
- * Created by Arnaud Labourel on 02/10/2018.
- */
-
 public class ByteGrayColor implements GrayColor {
 
     private static final int MINIMUM_GRAY_LEVEL = 0;
     private static final int MAXIMUM_GRAY_LEVEL = 255;
     private static final int OPACITY = 1;
 
-    private final int grayLevel;
+    public static final ByteGrayColor WHITE = new ByteGrayColor(MAXIMUM_GRAY_LEVEL);
+    public static final ByteGrayColor BLACK = new ByteGrayColor(MINIMUM_GRAY_LEVEL);
 
+    private static final double MAXIMUM_LUMINOSITY = 1.;
+
+    private final int grayLevel;
 
     public ByteGrayColor(){
-       this.grayLevel = MINIMUM_GRAY_LEVEL;
+        this.grayLevel = MINIMUM_GRAY_LEVEL;
     }
 
     public ByteGrayColor(int grayLevel) {
-        // TODO : Corriger l'initialisation de la propriété grayLevel de l'instance.
-        this.grayLevel = 0;
+        this.grayLevel = grayLevel;
     }
 
     public ByteGrayColor(double luminosity) {
-        // TODO : Corriger l'initialisation de la propriété grayLevel de l'instance.
-        this.grayLevel = 0;
+        this.grayLevel = (int) (luminosity * MAXIMUM_GRAY_LEVEL);
     }
 
     @Override
     public double getLuminosity() {
-        // TODO : Retourner la luminosité de la couleur (entre 0 noir et 1 blanc)
-        return 0;
+        return grayLevel/(double) MAXIMUM_GRAY_LEVEL;
     }
 
     @Override
     public Color getColor(){
-        double component = grayLevel / (double) MAXIMUM_GRAY_LEVEL;
+        double component = getLuminosity();
         return new Color(component, component, component, OPACITY);
     }
 
-
     @Override
     public int compareTo(GrayColor o) {
-        // TODO : Retourner la différence de niveau de gris.
-        return 0;
+        return Double.compare(this.getLuminosity(), o.getLuminosity());
     }
 
     @Override
@@ -54,4 +49,12 @@ public class ByteGrayColor implements GrayColor {
         return this.compareTo(color) == 0;
     }
 
-}
+    @Override
+    public GrayColor invert() {
+        return new ByteGrayColor(invertedLuminosity());
+    }
+
+    private double invertedLuminosity() {
+        return MAXIMUM_LUMINOSITY - getLuminosity();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/CompositeTransform.java b/src/main/java/CompositeTransform.java
new file mode 100755
index 0000000..bae7783
--- /dev/null
+++ b/src/main/java/CompositeTransform.java
@@ -0,0 +1,18 @@
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+
+public class CompositeTransform implements Transform {
+    private final Transform[] transforms;
+
+    public CompositeTransform(Transform[] transforms) {
+        this.transforms = transforms;
+    }
+
+    @Override
+    public void applyTo(GrayImage image) {
+        for(Transform transform : transforms){
+            transform.applyTo(image);
+        }
+    }
+}
diff --git a/src/main/java/CrissCross.java b/src/main/java/CrissCross.java
new file mode 100755
index 0000000..b6c3692
--- /dev/null
+++ b/src/main/java/CrissCross.java
@@ -0,0 +1,26 @@
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+public class CrissCross implements Transform{
+
+    private final int size;
+
+    public CrissCross(int size){
+        this.size = size;
+    }
+
+    @Override
+    public void applyTo(GrayImage image) {
+        for(int x = 0; x < image.getWidth(); x++) {
+            for(int y = 0; y < image.getHeight(); y++) {
+                modifyPixel(image, x, y);
+            }
+        }
+    }
+
+    private void modifyPixel(GrayImage image, int x, int y) {
+        if(x % size == 0 || y % size ==0){
+            image.setPixel(ByteGrayColor.BLACK, x, y);
+        }
+    }
+}
diff --git a/src/main/java/DecreaseGrayLevels.java b/src/main/java/DecreaseGrayLevels.java
new file mode 100755
index 0000000..cae2894
--- /dev/null
+++ b/src/main/java/DecreaseGrayLevels.java
@@ -0,0 +1,28 @@
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+public class DecreaseGrayLevels implements Transform {
+
+    private final int nbGrayLevels;
+
+    public DecreaseGrayLevels(int nbGrayLevels) {
+        this.nbGrayLevels = nbGrayLevels;
+    }
+
+    @Override
+    public void applyTo(GrayImage image) {
+        for(int x = 0; x < image.getWidth(); x++) {
+            for (int y = 0; y < image.getHeight(); y++) {
+                modifyPixel(image, x, y);
+            }
+        }
+    }
+
+    private void modifyPixel(GrayImage image, int x, int y) {
+        int numberOfIntervals = nbGrayLevels - 1;
+        double sizeOfIntervals = 1. / (double) numberOfIntervals;
+        double luminosity = image.getPixelGrayColor(x, y).getLuminosity();
+        double newLuminosity = Math.floor(luminosity * numberOfIntervals) * sizeOfIntervals;
+        image.setPixel(new ByteGrayColor(newLuminosity), x, y);
+    }
+}
diff --git a/src/main/java/Display.java b/src/main/java/Display.java
index 5332f89..cdf672f 100644
--- a/src/main/java/Display.java
+++ b/src/main/java/Display.java
@@ -11,41 +11,44 @@ import java.util.ResourceBundle;
  * Created by Arnaud Labourel on 04/10/2018.
  */
 public class Display implements Initializable {
-    @FXML
-    private Canvas canvas;
+  @FXML
+  private Canvas canvas;
 
-    MatrixGrayImage image;
+  MatrixGrayImage image;
 
-    @Override
-    public void initialize(URL location, ResourceBundle resources) {
+  @Override
+  public void initialize(URL location, ResourceBundle resources) {
 
-        this.image = MatrixGrayImage.createImageFromPGMFile("images/luminy.pgm");
+    this.image = MatrixGrayImage.createImageFromPGMFile("images/luminy.pgm");
 
-        // TODO : Ajouter les transformations d'image.
+    Transform transform = new CompositeTransform(new Transform[] {new DecreaseGrayLevels(8), new Outline(0.05), new Invert()});
 
-        render();
-    }
+    transform.applyTo(image);
+    image.writeIntoPGMFormat("/Users/arnaudlabourel/luminy.pgm");
+    render();
+  }
 
-    public void render() {
-        int pixelWidth = image.getWidth();
-        int pixelHeight = image.getHeight();
+  public void render() {
+    int pixelWidth = image.getWidth();
+    int pixelHeight = image.getHeight();
 
-        canvas.setWidth(pixelWidth);
-        canvas.setHeight(pixelHeight);
+    canvas.setWidth(pixelWidth);
+    canvas.setHeight(pixelHeight);
 
-        GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
+    GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
 
-        PixelWriter pixelWriter = graphicsContext.getPixelWriter();
+    PixelWriter pixelWriter = graphicsContext.getPixelWriter();
 
-        for (int i = 0; i < pixelWidth; i++) {
-            for (int j = 0; j < pixelHeight; j++) {
-                renderPixel(i,j, pixelWriter);
-            }
-        }
+    for (int i = 0; i < pixelWidth; i++) {
+      for (int j = 0; j < pixelHeight; j++) {
+        renderPixel(i,j, pixelWriter);
+      }
     }
+  }
 
-    private void renderPixel(int x, int y, PixelWriter pixelWriter) {
-        pixelWriter.setColor(x, y, image.getPixelColor(x, y));
-    }
+  private void renderPixel(int x, int y, PixelWriter pixelWriter) {
+    pixelWriter.setColor(x, y, image.getPixelColor(x, y));
+  }
 
 }
+
diff --git a/src/main/java/GrayColor.java b/src/main/java/GrayColor.java
old mode 100644
new mode 100755
index e871b5d..649bc2d
--- a/src/main/java/GrayColor.java
+++ b/src/main/java/GrayColor.java
@@ -4,7 +4,9 @@ import javafx.scene.paint.Color;
  * Created by Arnaud Labourel on 04/10/2018.
  * Interface correspondant à une couleur de gris.
  */
+
 public interface GrayColor extends Comparable<GrayColor> {
     double getLuminosity();
     Color getColor();
+    GrayColor invert();
 }
diff --git a/src/main/java/GrayImage.java b/src/main/java/GrayImage.java
old mode 100644
new mode 100755
index fdf4199..fa0472e
--- a/src/main/java/GrayImage.java
+++ b/src/main/java/GrayImage.java
@@ -1,5 +1,6 @@
+
 /**
- * Created by Arnaud Labourel on 04/10/2018.
+ * Interface pour une image avec des nuances de gris.
  */
 
 public interface GrayImage extends Image {
diff --git a/src/main/java/Image.java b/src/main/java/Image.java
old mode 100644
new mode 100755
index 282a645..9f8de10
--- a/src/main/java/Image.java
+++ b/src/main/java/Image.java
@@ -1,7 +1,7 @@
 import javafx.scene.paint.Color;
 
 /**
- * Created by Arnaud Labourel on 02/10/2018.
+ * Interface pour une image.
  */
 public interface Image {
     Color getPixelColor(int x, int y);
diff --git a/src/main/java/Invert.java b/src/main/java/Invert.java
new file mode 100755
index 0000000..639c49d
--- /dev/null
+++ b/src/main/java/Invert.java
@@ -0,0 +1,17 @@
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+public class Invert implements Transform{
+    @Override
+    public void applyTo(GrayImage image) {
+        for(int x = 0; x < image.getWidth(); x++) {
+            for (int y = 0; y < image.getHeight(); y++) {
+                modifyPixel(image, x, y);
+            }
+        }
+    }
+
+    private void modifyPixel(GrayImage image, int x, int y) {
+        image.setPixel(image.getPixelGrayColor(x, y).invert(), x, y);
+    }
+}
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
old mode 100644
new mode 100755
index 30f30b8..c18883d
--- a/src/main/java/Main.java
+++ b/src/main/java/Main.java
@@ -6,7 +6,6 @@ import javafx.stage.Stage;
 
 import java.io.IOException;
 
-
 public class Main extends Application
 {
 
@@ -18,8 +17,10 @@ public class Main extends Application
     public void start(Stage primaryStage) throws IOException {
         Parent root =FXMLLoader.load(getClass().getResource("fxml/Display.fxml"));
         primaryStage.setTitle("Image display");
+
         primaryStage.setScene(new Scene(root));
         primaryStage.show();
 
     }
+
 }
diff --git a/src/main/java/MatrixGrayImage.java b/src/main/java/MatrixGrayImage.java
old mode 100644
new mode 100755
index 401bfe7..ecfb91d
--- a/src/main/java/MatrixGrayImage.java
+++ b/src/main/java/MatrixGrayImage.java
@@ -14,45 +14,45 @@ public class MatrixGrayImage implements GrayImage {
     private final int width;
     private final int height;
 
-
     @Override
     public void setPixel(GrayColor gray, int x, int y) {
-        // TODO : Compléter la méthode pour modifier le pixel.
+        pixels[x][y] = gray;
     }
 
     @Override
     public GrayColor getPixelGrayColor(int x, int y) {
-        // TODO : Changer les instructions pour retourner le bon pixel.
-        return new ByteGrayColor();
+        return pixels[x][y];
     }
 
     @Override
     public Color getPixelColor(int x, int y) {
-        // TODO : Changer les instructions pour retourner la couleur du pixel.
-        return Color.WHITE;
+        return getPixelGrayColor(x, y).getColor();
     }
 
     @Override
     public int getWidth() {
-        // TODO : Changer les instructions pour retourner la largeur de l'image.
-        return 600;
+        return width;
     }
 
     @Override
     public int getHeight() {
-        // TODO : Changer les instructions pour retourner la hauteur de l'image.
-        return 400;
+        return height;
     }
 
     public MatrixGrayImage(int width, int height){
-        /* TODO : Modifier les instructions pour initialiser correctement
-            les propriétés de l'instance.
-         */
-        this.width = 0;
-        this.height = 0;
-        this.pixels = null;
+        this.width = width;
+        this.height = height;
+        this.pixels = new GrayColor[width][height];
+        setAllPixelsColorTo(ByteGrayColor.WHITE);
     }
 
+    private void setAllPixelsColorTo(GrayColor gray) {
+        for(int x = 0; x < this.width; x++){
+            for (int y = 0; y < this.height; y++){
+                pixels[x][y] = gray;
+            }
+        }
+    }
 
     public static MatrixGrayImage createImageFromPGMFile(String fileName) {
         // NE PAS MODIFIER !
@@ -87,7 +87,7 @@ public class MatrixGrayImage implements GrayImage {
             printWriter.println("# CREATOR: TP3 Version 1.0");
             printWriter.printf("%d %d\n",this.width, this.height);
 
-            printWriter.println(pgmCodeOfGrayColor(pixels[0][0]));
+            printWriter.println(PGM_MAXIMUM_CODE);
 
             for(int y = 0; y < height; y++){
                 for(int x = 0; x < width; x++) {
@@ -106,4 +106,4 @@ public class MatrixGrayImage implements GrayImage {
     private int pgmCodeOfGrayColor(GrayColor pixelGrayColor) {
         return (int) (pixelGrayColor.getLuminosity() * (double) PGM_MAXIMUM_CODE);
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/Outline.java b/src/main/java/Outline.java
new file mode 100755
index 0000000..5f7496e
--- /dev/null
+++ b/src/main/java/Outline.java
@@ -0,0 +1,48 @@
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+public class Outline implements Transform {
+    private final double threshold;
+
+    public Outline(double threshold) {
+        this.threshold = threshold;
+    }
+
+    private List<GrayColor> southEastNeighborPixels(GrayImage image, int x, int y){
+        List<GrayColor> neighborPixels = new ArrayList<>();
+        if (x != image.getWidth() - 1) {
+            neighborPixels.add(image.getPixelGrayColor(x + 1, y));
+        }
+        if (y != image.getHeight() - 1) {
+            neighborPixels.add(image.getPixelGrayColor(x, y + 1));
+        }
+        return neighborPixels;
+    }
+
+    @Override
+    public void applyTo(GrayImage image) {
+        for(int x = 0; x < image.getWidth(); x++) {
+            for(int y = 0; y < image.getHeight(); y++) {
+                modifyPixel(image, x, y);
+            }
+        }
+    }
+
+    private void modifyPixel(GrayImage image, int x, int y) {
+        List<GrayColor> neighborPixels = southEastNeighborPixels(image, x, y);
+        ByteGrayColor newColor = ByteGrayColor.WHITE;
+
+        for(GrayColor neighborPixel : neighborPixels){
+
+            if(Math.abs(neighborPixel.getLuminosity() - image.getPixelGrayColor(x,y).getLuminosity()) > threshold) {
+                newColor = ByteGrayColor.BLACK;
+            }
+        }
+
+        image.setPixel(newColor, x, y);
+    }
+
+}
diff --git a/src/main/java/Pixelate.java b/src/main/java/Pixelate.java
new file mode 100755
index 0000000..ae89578
--- /dev/null
+++ b/src/main/java/Pixelate.java
@@ -0,0 +1,53 @@
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+public class Pixelate implements Transform{
+
+    private class PixelSquare {
+        private final int xTopLeft;
+        private final int yTopLeft;
+
+        public PixelSquare(int xTopLeft, int yTopLeft) {
+            this.xTopLeft = xTopLeft;
+            this.yTopLeft = yTopLeft;
+        }
+
+        void setAllPixelsColor(GrayColor grayColor, GrayImage image){
+            for(int x = xTopLeft; x < Math.min(xTopLeft + newPixelSize, image.getWidth()); x++) {
+                for (int y = yTopLeft; y < Math.min(yTopLeft + newPixelSize, image.getHeight()); y++) {
+                    image.setPixel(grayColor, x, y);
+                }
+            }
+        }
+
+        ByteGrayColor averageColorOfPixels(GrayImage image){
+            double sumOfLuminosities = 0;
+            int nbPixels = 0;
+            for(int x = xTopLeft; x < Math.min(xTopLeft + newPixelSize, image.getWidth()); x++) {
+                for (int y = yTopLeft; y < Math.min(yTopLeft + newPixelSize, image.getHeight()); y++) {
+                    sumOfLuminosities += image.getPixelGrayColor(x, y).getLuminosity();
+                    nbPixels++;
+                }
+            }
+            return new ByteGrayColor(sumOfLuminosities/nbPixels);
+        }
+    }
+
+    private final int newPixelSize;
+
+    public Pixelate(int newPixelSize) {
+        this.newPixelSize = newPixelSize;
+    }
+
+    @Override
+    public void applyTo(GrayImage image){
+        int rowCount = (int) Math.ceil((double)image.getWidth()/newPixelSize);
+        int columnCount = (int) Math.ceil((double)image.getHeight()/newPixelSize);
+
+        for(int i = 0; i < rowCount; i++)
+            for(int j = 0; j < columnCount; j++){
+                PixelSquare pixelSquare = new PixelSquare(i*newPixelSize, j*newPixelSize);
+                pixelSquare.setAllPixelsColor(pixelSquare.averageColorOfPixels(image), image);
+            }
+    }
+}
diff --git a/src/main/java/Transform.java b/src/main/java/Transform.java
new file mode 100755
index 0000000..15d58d6
--- /dev/null
+++ b/src/main/java/Transform.java
@@ -0,0 +1,6 @@
+/**
+ * Created by Arnaud Labourel on 04/10/2018.
+ */
+public interface Transform {
+    void applyTo(GrayImage image);
+}
-- 
GitLab