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