Import from internal git

This commit is contained in:
Laurent
2026-06-23 20:27:12 +02:00
commit 2ddced7d41
72 changed files with 3308 additions and 0 deletions

28
src/main/java/Main.java Normal file
View File

@@ -0,0 +1,28 @@
import app.AppModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import presenters.MainPresenter;
import presenters.NavPresenter;
import ui.implementation.components.nav.NavBar;
import ui.implementation.views.MainView;
import ui.interfaces.IMainView;
import javax.swing.*;
/**
* @author Laurent Crema
*/
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AppModule());
SwingUtilities.invokeLater(() -> {
NavBar navBar = injector.getInstance(NavBar.class);
MainView view = (MainView) injector.getInstance(IMainView.class);
view.setNavBar(navBar);
view.setVisible(true);
});
}
}

View File

@@ -0,0 +1,49 @@
package app;
import app.state.AppState;
import app.state.DoubleMatrixState;
import com.google.common.eventbus.EventBus;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import presenters.DoubleMatrixPresenter;
import presenters.MainPresenter;
import presenters.NavPresenter;
import services.ImageService;
import ui.implementation.components.nav.NavBar;
import ui.implementation.views.DoubleMatrix;
import ui.implementation.views.MainView;
import ui.interfaces.IDoubleMatrix;
import ui.interfaces.IMainView;
import ui.interfaces.INavBar;
/**
* @author Laurent Crema
*/
public class AppModule extends AbstractModule {
@Override
protected void configure() {
//--- States ---
bind(AppState.class).in(Scopes.SINGLETON);
bind(DoubleMatrixState.class);
//--- Application layer ---
bind(EventBus.class).in(Scopes.SINGLETON);
bind(INavigator.class).to(SwingNavigator.class).in(Scopes.SINGLETON);
//--- UI layer ---
bind(INavBar.class).to(NavBar.class);
bind(IMainView.class).to(MainView.class);
bind(IDoubleMatrix.class).to(DoubleMatrix.class);
//--- Presentation layer ---
bind(MainPresenter.class);
bind(NavPresenter.class);
bind(DoubleMatrixPresenter.class);
//--- Service layer layer ---
bind(ImageService.class);
}
}

View File

@@ -0,0 +1,7 @@
package app;
public interface INavigator {
void showFourier();
}

View File

@@ -0,0 +1,23 @@
package app;
import com.google.inject.Inject;
import com.google.inject.Provider;
import ui.implementation.views.DoubleMatrix;
public class SwingNavigator implements INavigator {
private final Provider<DoubleMatrix> doubleMatrixProvider;
@Inject
public SwingNavigator(
Provider<DoubleMatrix> doubleMatrixProvider
) {
this.doubleMatrixProvider = doubleMatrixProvider;
}
@Override
public void showFourier() {
DoubleMatrix doubleMatrix = doubleMatrixProvider.get();
doubleMatrix.setVisible(true);
}
}

View File

@@ -0,0 +1,37 @@
package app.state;
import com.google.common.eventbus.EventBus;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import domain.common.Mode;
import domain.events.ImageChangedEvent;
import domain.events.ModeChangedEvent;
import domain.image.Image;
@Singleton
public class AppState extends State {
private Mode mode;
private Image rgbImage;
@Inject
public AppState(EventBus eventBus) {
super(eventBus);
}
public void setMode(Mode mode) {
this.mode = mode;
this.eventBus.post(new ModeChangedEvent(mode));
}
public void setImage(Image image) {
this.rgbImage = image;
this.eventBus.post(new ImageChangedEvent(image));
}
public Image getImage(){
return this.rgbImage;
}
public Mode getMode() { return this.mode; }
}

View File

@@ -0,0 +1,49 @@
package app.state;
import com.google.common.eventbus.EventBus;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import domain.events.fourier.*;
import domain.image.GrayScaleMatrix;
import domain.image.processing.complex.ComplexMatrix;
public class DoubleMatrixState extends State {
private ComplexMatrix fourier;
private GrayScaleMatrix module;
private GrayScaleMatrix phase;
private GrayScaleMatrix real;
private GrayScaleMatrix imaginary;
@Inject
public DoubleMatrixState() { super(new EventBus()); }
public ComplexMatrix getFourier() {
return fourier;
}
public void setFourier(ComplexMatrix fourier) {
this.fourier = fourier;
this.eventBus.post(new ComplexMatrixChanged(fourier));
}
public void setModule(GrayScaleMatrix matrix) {
this.module = matrix;
this.eventBus.post(new ModuleChangedEvent(matrix));
}
public void setPhase(GrayScaleMatrix matrix) {
this.phase = matrix;
this.eventBus.post(new PhaseChangedEvent(matrix));
}
public void setReal(GrayScaleMatrix matrix) {
this.real = matrix;
this.eventBus.post(new RealChangedEvent(matrix));
}
public void setImaginary(GrayScaleMatrix matrix) {
this.imaginary = matrix;
this.eventBus.post(new ImaginaryChangedEvent(matrix));
}
}

View File

@@ -0,0 +1,16 @@
package app.state;
import com.google.common.eventbus.EventBus;
public abstract class State {
protected EventBus eventBus;
public State(EventBus eventBus) {
this.eventBus = eventBus;
}
public void register(Object obj) {
eventBus.register(obj);
}
}

View File

@@ -0,0 +1,9 @@
package domain.common;
public enum Mode {
DISABLED,
DRAW_PIXEL,
DRAW_LINE,
DRAW_RECTANGLE,
DRAW_CIRCLE,
}

View File

@@ -0,0 +1,5 @@
package domain.events;
import domain.image.Image;
public record ImageChangedEvent(Image image) { }

View File

@@ -0,0 +1,6 @@
package domain.events;
import domain.image.GrayScaleMatrix;
public record MatrixChangedEvent(GrayScaleMatrix matrix) {
}

View File

@@ -0,0 +1,5 @@
package domain.events;
import domain.common.Mode;
public record ModeChangedEvent(Mode mode) { }

View File

@@ -0,0 +1,6 @@
package domain.events.fourier;
import domain.image.processing.complex.ComplexMatrix;
public record ComplexMatrixChanged(ComplexMatrix matrix) {
}

View File

@@ -0,0 +1,6 @@
package domain.events.fourier;
import domain.image.GrayScaleMatrix;
public record ImaginaryChangedEvent(GrayScaleMatrix matrix) {
}

View File

@@ -0,0 +1,6 @@
package domain.events.fourier;
import domain.image.GrayScaleMatrix;
public record ModuleChangedEvent(GrayScaleMatrix matrix) {
}

View File

@@ -0,0 +1,6 @@
package domain.events.fourier;
import domain.image.GrayScaleMatrix;
public record PhaseChangedEvent(GrayScaleMatrix matrix) {
}

View File

@@ -0,0 +1,6 @@
package domain.events.fourier;
import domain.image.GrayScaleMatrix;
public record RealChangedEvent(GrayScaleMatrix matrix) {
}

View File

@@ -0,0 +1,130 @@
package domain.image;
import infrastructure.image.io.ImageSaver;
import java.util.Arrays;
/**
* @author Jean-Marc Wagner, Laurent Crema
*/
public class GrayScaleMatrix {
private final double[][] matrix;
private final double maxValue;
private final double minValue;
public GrayScaleMatrix(double[][] matrix) {
this.matrix = matrix;
this.maxValue = computeMax();
this.minValue = computeMin();
}
/**
* Returns a copy of the actual content of this matrix.
* Since a copy is returned, no change that will be applied on it is going to affect the original matrix
* @return a copy of the actual content
*/
public double[][] getRawData() {
return Arrays.copyOf(matrix, matrix.length);
}
public int getWidth(){
return matrix[0].length;
}
public int getHeight(){
return matrix.length;
}
public double getMaxValue() {
return maxValue;
}
public double getMinValue() {
return minValue;
}
public double getValueAt(double normalized) {
if(normalized <= 0) { return minValue; }
if(normalized >= 1) { return maxValue; }
return minValue + (maxValue - minValue) * normalized;
}
private double computeMax(){
double res = matrix[0][0];
for(int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
double value = matrix[y][x];
if (value > res) res = matrix[y][x];
}
}
return res;
}
private double computeMin(){
double res = matrix[0][0];
for(int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
double value = matrix[y][x];
if (value < res) res = matrix[y][x];
}
}
return res;
}
public GrayScaleMatrix clip() {
return clip(minValue, maxValue);
}
public GrayScaleMatrix clip(double lowerBound, double upperBound) {
int height = getHeight();
int width = getWidth();
double[][] res = new double[height][width];
double range = upperBound - lowerBound;
if (range == 0) range = 1;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
double v = matrix[y][x];
double out;
if (v >= upperBound) {
out = 255;
} else if (v <= lowerBound) {
out = 0;
} else {
out = (v - lowerBound) / range * 255.0;
}
res[y][x] = Math.clamp(out, 0, 255);
}
}
return new GrayScaleMatrix(res);
}
public Image toImage() {
Pixel[][] res = new Pixel[getHeight()][getWidth()];
double range = maxValue - minValue;
if (range == 0) range = 1;
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
double normalized = (matrix[y][x] - minValue) / range;
int gray = (int) (normalized * 255);
res[y][x] = new Pixel(gray, gray, gray);
}
}
return new Image(res);
}
}

View File

@@ -0,0 +1,126 @@
package domain.image;
/**
* @author Laurent Crema
*/
public class Image {
private final Pixel[][] pixels;
private GrayScaleMatrix grayScaleEquivalent;
public Image(Pixel[][] pixels) {
if(pixels == null || pixels.length == 0 || pixels[0].length == 0)
throw new IllegalArgumentException("Invalid dimensions");
this.pixels = pixels;
}
public Image(int red, int green, int blue, int height, int width) {
pixels = new Pixel[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[y][x] = new Pixel(red, green, blue);
}
}
}
public int getWidth(){
return pixels[0].length;
}
public int getHeight(){
return pixels.length;
}
public Pixel getPixel(int x, int y){
if(x < 0 || y < 0 || x >= getWidth() || y >= getHeight())
throw new IllegalArgumentException("Invalid coordinates");
return pixels[y][x];
}
public void setPixelColor(int x, int y, int red, int green, int blue){
if(x < 0 || y < 0 || x >= getWidth() || y >= getHeight())
throw new IllegalArgumentException("Invalid coordinates");
Pixel p = new Pixel(red, green, blue);
pixels[y][x] = p;
grayScaleEquivalent = toGrayScale();
}
public void setRectangleColor(int x1, int x2, int y1, int y2,
int red, int green, int blue) {
int minX = Math.max(0, Math.min(x1, x2));
int maxX = Math.min(pixels[0].length - 1, Math.max(x1, x2));
int minY = Math.max(0, Math.min(y1, y2));
int maxY = Math.min(pixels.length - 1, Math.max(y1, y2));
Pixel p = new Pixel(red, green, blue);
for (int y = minY; y <= maxY; y++) {
for (int x = minX; x <= maxX; x++) {
pixels[y][x] = p;
}
}
grayScaleEquivalent = toGrayScale();
}
public void setLineColor(int x1, int x2, int y1, int y2,
int red, int green, int blue) {
int dx = Math.abs(x2 - x1);
int dy = Math.abs(y2 - y1);
int sx = x1 < x2 ? 1 : -1;
int sy = y1 < y2 ? 1 : -1;
int err = dx - dy;
Pixel p = new Pixel(red, green, blue);
while (true) {
if (x1 >= 0 && y1 >= 0 && x1 < getWidth() && y1 < getHeight()) {
pixels[y1][x1] = p;
}
if (x1 == x2 && y1 == y2) break;
int e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x1 += sx;
}
if (e2 < dx) {
err += dx;
y1 += sy;
}
}
grayScaleEquivalent = toGrayScale();
}
/**
* Return the corresponding gray scale matrix. Since this operation is destructive, the original image is not modified.
* Instead, a new one is returned.
* @return A newly converted image
*/
public GrayScaleMatrix toGrayScale() {
if(grayScaleEquivalent != null) return this.grayScaleEquivalent;
double[][] res = new double[getHeight()][getWidth()];
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
Pixel p = pixels[y][x];
res[y][x] = p.grayValue();
}
}
this.grayScaleEquivalent = new GrayScaleMatrix(res);
return this.grayScaleEquivalent;
}
}

View File

@@ -0,0 +1,62 @@
package domain.image;
/**
* @author Laurent Crema
*/
public class Pixel {
private int red, green, blue;
public Pixel(int red, int green, int blue) {
if(checkColorValidity(red))
throw new IllegalArgumentException("Invalid red value"); // <-- here
if(checkColorValidity(green)) throw new IllegalArgumentException("Invalid green value");
if(checkColorValidity(blue)) throw new IllegalArgumentException("Invalid blue value");
this.red = red;
this.green = green;
this.blue = blue;
}
public int getRed() {
return red;
}
public void setRed(int value) {
if(checkColorValidity(value)) throw new IllegalArgumentException("Invalid value");
this.red = value;
}
public int getGreen() {
return green;
}
public void setGreen(int value) {
if(checkColorValidity(value)) throw new IllegalArgumentException("Invalid value");
this.green = value;
}
public int getBlue() {
return blue;
}
public void setBlue(int value) {
if(checkColorValidity(value)) throw new IllegalArgumentException("Invalid value");
this.blue = value;
}
public boolean checkColorValidity(int color) {
return !(color >= 0 && color <= 255);
}
/**
* Convert the current RGB combination into a gray value according to UIT-R BT 709 standard.
* The current RGB values are not modified.
* @return the corresponding gray scale value
*/
public int grayValue(){
return (int) (0.2126 * red + 0.7152 * green + 0.0722 * blue);
}
}

View File

@@ -0,0 +1,80 @@
package domain.image.processing.complex;
public class ComplexMatrix
{
private Complexe m[][];
private int lignes;
private int colonnes;
/** Creates a new instance of MatriceComplexe */
public ComplexMatrix(int l, int c)
{
lignes = l;
colonnes = c;
m = new Complexe[l][c];
for(int i=0 ; i<lignes ; i++)
for(int j=0 ; j<colonnes ; j++)
m[i][j] = new Complexe(0.0,0.0);
}
public void set(int ligne,int colonne,Complexe complexe)
{
m[ligne][colonne] = complexe;
}
public void set(int ligne,int colonne,double partieReelle,double partieImaginaire)
{
Complexe c = new Complexe(partieReelle,partieImaginaire);
set(ligne,colonne,c);
}
public Complexe get(int ligne,int colonne)
{
return m[ligne][colonne];
}
public double[][] getPartieReelle()
{
double d[][] = new double[lignes][colonnes];
for(int i=0 ; i<lignes ; i++)
for(int j=0 ; j<colonnes ; j++)
d[i][j] = m[i][j].getPartieReelle();
return d;
}
public double[][] getPartieImaginaire()
{
double d[][] = new double[lignes][colonnes];
for(int i=0 ; i<lignes ; i++)
for(int j=0 ; j<colonnes ; j++)
d[i][j] = m[i][j].getPartieImaginaire();
return d;
}
public double[][] getModule()
{
double d[][] = new double[lignes][colonnes];
for(int i=0 ; i<lignes ; i++)
for(int j=0 ; j<colonnes ; j++)
d[i][j] = m[i][j].getModule();
return d;
}
public double[][] getPhase()
{
double d[][] = new double[lignes][colonnes];
for(int i=0 ; i<lignes ; i++)
for(int j=0 ; j<colonnes ; j++)
d[i][j] = m[i][j].getPhase();
return d;
}
public int getLignes() {
return lignes;
}
public int getColonnes() {
return colonnes;
}
}

View File

@@ -0,0 +1,61 @@
package domain.image.processing.complex;
public class Complexe
{
private double partieReelle;
private double partieImaginaire;
/** Creates a new instance of Complexe */
public Complexe(double pr,double pi)
{
partieReelle = pr;
partieImaginaire = pi;
}
public double getModule()
{
return Math.sqrt(partieReelle*partieReelle + partieImaginaire*partieImaginaire);
}
public double getPhase()
{
return Math.atan2(partieImaginaire,partieReelle);
}
public void additionne(Complexe c)
{
partieReelle += c.getPartieReelle();
partieImaginaire += c.getPartieImaginaire();
}
public void multiplie(Complexe c)
{
double r,i;
r = partieReelle*c.getPartieReelle() - partieImaginaire*c.getPartieImaginaire();
i = partieReelle*c.getPartieImaginaire() + partieImaginaire*c.getPartieReelle();
partieReelle = r;
partieImaginaire = i;
}
public Complexe conjugue()
{
return new Complexe(partieReelle,-partieImaginaire);
}
public double getPartieReelle() {
return partieReelle;
}
public void setPartieReelle(double partieReelle) {
this.partieReelle = partieReelle;
}
public double getPartieImaginaire() {
return partieImaginaire;
}
public void setPartieImaginaire(double partieImaginaire) {
this.partieImaginaire = partieImaginaire;
}
}

View File

@@ -0,0 +1,173 @@
package domain.image.processing.fourier;
import domain.image.processing.complex.ComplexMatrix;
public class Fourier
{
public static ComplexMatrix Fourier2D(double f[][])
{
int M = f.length;
int N = f[0].length;
ComplexMatrix F = new ComplexMatrix(M,N);
//********** n --> v **********
double pr1[][] = new double[M][N];
double pi1[][] = new double[M][N];
for(int m=0 ; m<M ; m++)
{
for(int v=0 ; v<=N/2 ; v++)
{
pr1[m][v] = 0.0;
pi1[m][v] = 0.0;
double cosTheta = 1.0, newCosTheta;
double sinTheta = 0.0, newSinTheta;
double cosDTheta = Math.cos(-2.0*Math.PI*(double)v/(double)N);
double sinDTheta = Math.sin(-2.0*Math.PI*(double)v/(double)N);
for (int n=0 ; n<N ; n++)
{
pr1[m][v] += f[m][n] * cosTheta;
pi1[m][v] += f[m][n] * sinTheta;
newCosTheta = cosTheta*cosDTheta - sinTheta*sinDTheta;
newSinTheta = sinTheta*cosDTheta + cosTheta*sinDTheta;
cosTheta = newCosTheta;
sinTheta = newSinTheta;
}
pr1[m][v] /= (double)N;
pi1[m][v] /= (double)N;
if (v > 0)
{
pr1[m][N-v] = pr1[m][v];
pi1[m][N-v] = -pi1[m][v];
}
}
}
//********** m --> u **********
double pr2[][] = new double[M][N];
double pi2[][] = new double[M][N];
for(int v=0 ; v<N ; v++)
{
for(int u=0 ; u<M ; u++)
{
pr2[u][v] = 0.0;
pi2[u][v] = 0.0;
double cosTheta = 1.0, newCosTheta;
double sinTheta = 0.0, newSinTheta;
double cosDTheta = Math.cos(-2.0*Math.PI*(double)u/(double)M);
double sinDTheta = Math.sin(-2.0*Math.PI*(double)u/(double)M);
for (int m=0 ; m<M ; m++)
{
pr2[u][v] += pr1[m][v] * cosTheta - pi1[m][v] * sinTheta;
pi2[u][v] += pr1[m][v] * sinTheta + pi1[m][v] * cosTheta;
newCosTheta = cosTheta*cosDTheta - sinTheta*sinDTheta;
newSinTheta = sinTheta*cosDTheta + cosTheta*sinDTheta;
cosTheta = newCosTheta;
sinTheta = newSinTheta;
}
pr2[u][v] /= (double)M;
pi2[u][v] /= (double)M;
}
}
//********** Remplissage de F **********
for(int u=0 ; u<M ; u++)
for(int v=0 ; v<N ; v++)
F.set(u,v,pr2[u][v],pi2[u][v]);
return F;
}
public static ComplexMatrix InverseFourier2D(ComplexMatrix F)
{
int M = F.getLignes();
int N = F.getColonnes();
ComplexMatrix f = new ComplexMatrix(M,N);
double pr0[][] = F.getPartieReelle();
double pi0[][] = F.getPartieImaginaire();
//********** v --> n **********
double pr1[][] = new double[M][N];
double pi1[][] = new double[M][N];
for(int u=0 ; u<M ; u++)
{
for(int n=0 ; n<N ; n++)
{
pr1[u][n] = 0.0;
pi1[u][n] = 0.0;
double cosTheta = 1.0, newCosTheta;
double sinTheta = 0.0, newSinTheta;
double cosDTheta = Math.cos(2.0*Math.PI*(double)n/(double)N);
double sinDTheta = Math.sin(2.0*Math.PI*(double)n/(double)N);
for (int v=0 ; v<N ; v++)
{
pr1[u][n] += pr0[u][v] * cosTheta - pi0[u][v] * sinTheta;
pi1[u][n] += pr0[u][v] * sinTheta + pi0[u][v] * cosTheta;
newCosTheta = cosTheta*cosDTheta - sinTheta*sinDTheta;
newSinTheta = sinTheta*cosDTheta + cosTheta*sinDTheta;
cosTheta = newCosTheta;
sinTheta = newSinTheta;
}
}
}
//********** u --> m **********
double pr2[][] = new double[M][N];
double pi2[][] = new double[M][N];
for(int n=0 ; n<N ; n++)
{
for(int m=0 ; m<M ; m++)
{
pr2[m][n] = 0.0;
pi2[m][n] = 0.0;
double cosTheta = 1.0, newCosTheta;
double sinTheta = 0.0, newSinTheta;
double cosDTheta = Math.cos(2.0*Math.PI*(double)m/(double)M);
double sinDTheta = Math.sin(2.0*Math.PI*(double)m/(double)M);
for (int u=0 ; u<M ; u++)
{
pr2[m][n] += pr1[u][n] * cosTheta - pi1[u][n] * sinTheta;
pi2[m][n] += pr1[u][n] * sinTheta + pi1[u][n] * cosTheta;
newCosTheta = cosTheta*cosDTheta - sinTheta*sinDTheta;
newSinTheta = sinTheta*cosDTheta + cosTheta*sinDTheta;
cosTheta = newCosTheta;
sinTheta = newSinTheta;
}
}
}
//********** Remplissage de f **********
for(int m=0 ; m<M ; m++)
for(int n=0 ; n<N ; n++)
f.set(m,n,pr2[m][n],pi2[m][n]);
return f;
}
public static ComplexMatrix decroise(ComplexMatrix F)
{
int M = F.getLignes();
int N = F.getColonnes();
ComplexMatrix mat = new ComplexMatrix(M,N);
int m,n;
for(m=0 ; m<M/2 ; m++)
for(n=0 ; n<N/2 ; n++) mat.set(m,n,F.get(M/2+m,N/2+n));
for(m=M/2 ; m<M ; m++)
for(n=0 ; n<N/2 ; n++) mat.set(m,n,F.get(m-M/2,n+N/2));
for(m=0 ; m<M/2 ; m++)
for(n=N/2 ; n<N ; n++) mat.set(m,n,F.get(m+M/2,n-N/2));
for(m=M/2 ; m<M ; m++)
for(n=N/2 ; n<N ; n++) mat.set(m,n,F.get(m-M/2,n-N/2));
return mat;
}
}

View File

@@ -0,0 +1,27 @@
package domain.image.processing.histogram;
import domain.image.GrayScaleMatrix;
import domain.image.Image;
public class Histogramme {
public static int[] Histogramme256(GrayScaleMatrix mat) {
int M = mat.getHeight();
int N = mat.getWidth();
int histo[] = new int[256];
for (int i = 0; i < 256; i++) histo[i] = 0;
Image grayScaleImage = mat.toImage();
int pixelGrayValue = 0;
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
pixelGrayValue = grayScaleImage.getPixel(i, j).grayValue();
if ((pixelGrayValue >= 0) && (pixelGrayValue <= 255)) {
histo[pixelGrayValue]++;
}
}
}
return histo;
}
}

View File

@@ -0,0 +1,20 @@
package domain.image.processing.lineaire;
import jdk.jshell.spi.ExecutionControl;
public class FiltrageLinaireGlobal {
public static int[][] filtrePasseBasIdeal(int[][] image,int frequenceCoupure){
return null;
}
public static int[][] filtrePasseHautIdeal(int[][] image,int frequenceCoupure){
return null;
}
public static int[][] filtrePasseBasButterworth(int[][] image,int frequenceCoupure,int ordre){
return null;
}
public static int[][] filtrePasseHautButterworth(int[][] image,int frequenceCoupure, int ordre) {
return null;
}
}

View File

@@ -0,0 +1,39 @@
package infrastructure.image.io;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import domain.image.Image;
import domain.image.Pixel;
public class ImageLoader {
public static Image loadImage(File f) throws IOException {
BufferedImage buffered = ImageIO.read(f);
if (buffered == null) throw new IOException("Unsupported or invalid image file: " + f);
int width = buffered.getWidth();
int height = buffered.getHeight();
Pixel[][] pixels = new Pixel[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = buffered.getRGB(x, y);
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
pixels[y][x] = new Pixel(r, g, b);
}
}
return new Image(pixels);
}
}

View File

@@ -0,0 +1,12 @@
package infrastructure.image.io;
import domain.image.Image;
import java.io.IOException;
public class ImageSaver {
public static void saveImage(Image image) throws IOException {
}
}

View File

@@ -0,0 +1,55 @@
package infrastructure.ui;
import domain.image.Image;
import domain.image.Pixel;
import java.awt.image.BufferedImage;
public final class ImageMapper {
public static BufferedImage toBufferedImage(Image image) {
int width = image.getWidth();
int height = image.getHeight();
BufferedImage out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Pixel p = image.getPixel(x, y);
int rgb = (p.getRed() << 16)
| (p.getGreen() << 8)
| p.getBlue();
out.setRGB(x, y, rgb);
}
}
return out;
}
public static Image fromBufferedImage(BufferedImage img) {
int width = img.getWidth();
int height = img.getHeight();
Pixel[][] pixels = new Pixel[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = img.getRGB(x, y);
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
pixels[y][x] = new Pixel(r, g, b);
}
}
return new Image(pixels);
}
}

View File

@@ -0,0 +1,126 @@
package presenters;
import app.state.DoubleMatrixState;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Inject;
import domain.events.fourier.ImaginaryChangedEvent;
import domain.events.fourier.ModuleChangedEvent;
import domain.events.fourier.PhaseChangedEvent;
import domain.events.fourier.RealChangedEvent;
import domain.image.GrayScaleMatrix;
import domain.image.Image;
import domain.image.processing.complex.ComplexMatrix;
import services.ImageService;
import ui.interfaces.IDoubleMatrix;
import java.io.IOException;
/**
* @author Laurent Crema
*/
public class DoubleMatrixPresenter {
private IDoubleMatrix view;
private final DoubleMatrixState state;
private final ImageService imageService;
@Inject
public DoubleMatrixPresenter(ImageService imageService, DoubleMatrixState state) {
this.imageService = imageService;
this.state = state;
this.state.register(this);
}
public void setView(IDoubleMatrix view){
this.view = view;
}
public void saveImage(Image image) throws IOException {
this.imageService.saveImage(image);
}
public void loadModule(){
double[][] module = getFourier().getModule();
state.setModule(new GrayScaleMatrix(module));
}
public void loadPhase(){
double[][] phase = getFourier().getPhase();
state.setPhase(new GrayScaleMatrix(phase));
}
public void loadReal(){
double[][] real = getFourier().getPartieReelle();
state.setReal(new GrayScaleMatrix(real));
}
public void loadImaginary(){
double[][] imaginary = getFourier().getPartieImaginaire();
state.setImaginary(new GrayScaleMatrix(imaginary));
}
public double getValueAt(GrayScaleMatrix matrix, double normalized){
return matrix.getValueAt(normalized);
}
public void clipModule(double black, double white){
GrayScaleMatrix module = new GrayScaleMatrix(getFourier().getModule());
GrayScaleMatrix matrix = clip(module, black, white);
state.setModule(matrix);
}
public void clipPhase(double black, double white){
GrayScaleMatrix phase = new GrayScaleMatrix(getFourier().getPhase());
GrayScaleMatrix matrix = clip(phase, black, white);
state.setPhase(matrix);
}
public void clipReal(double black, double white){
GrayScaleMatrix real = new GrayScaleMatrix(getFourier().getPartieReelle());
GrayScaleMatrix matrix = clip(real, black, white);
state.setReal(matrix);
}
public void clipImaginary(double black, double white){
GrayScaleMatrix imaginary = new GrayScaleMatrix(getFourier().getPartieImaginaire());
GrayScaleMatrix matrix = clip(imaginary, black, white);
state.setImaginary(matrix);
}
@Subscribe
public void onModuleUpdate(ModuleChangedEvent event) {
GrayScaleMatrix module = new GrayScaleMatrix(getFourier().getModule());
view.updateModule(module, event.matrix());
}
@Subscribe
public void onPhaseUpdate(PhaseChangedEvent event) {
GrayScaleMatrix phase = new GrayScaleMatrix(getFourier().getPhase());
view.updatePhase(phase, event.matrix());
}
@Subscribe
public void onRealUpdate(RealChangedEvent event) {
GrayScaleMatrix real = new GrayScaleMatrix(getFourier().getPartieReelle());
view.updateReal(real, event.matrix());
}
@Subscribe
public void onImaginaryUpdate(ImaginaryChangedEvent event) {
GrayScaleMatrix imaginary = new GrayScaleMatrix(getFourier().getPartieImaginaire());
view.updateImaginary(imaginary, event.matrix());
}
private GrayScaleMatrix clip(GrayScaleMatrix matrix, double black, double white){
double lowerBound = matrix.getValueAt(black);
double upperBound = matrix.getValueAt(white);
return matrix.clip(lowerBound, upperBound);
}
private ComplexMatrix getFourier() {
if (state.getFourier() == null) {
state.setFourier(imageService.computeFourier());
}
return state.getFourier();
}
}

View File

@@ -0,0 +1,67 @@
package presenters;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Inject;
import domain.common.Mode;
import domain.events.ImageChangedEvent;
import domain.events.ModeChangedEvent;
import domain.image.Image;
import services.ImageService;
import services.ModeService;
import ui.interfaces.IMainView;
/**
* @author Laurent Crema
*/
public class MainPresenter {
private IMainView view;
private final ModeService modeService;
private final ImageService imageService;
@Inject
public MainPresenter(ModeService modeService, ImageService imageService, EventBus eventBus) {
this.modeService = modeService;
this.imageService = imageService;
eventBus.register(this);
}
public void setView(IMainView view) {
this.view = view;
}
@Subscribe
public void onImageChanged(ImageChangedEvent e){
view.displayImage(e.image());
}
@Subscribe
public void onModeChanged(ModeChangedEvent e){
view.changeMode(e.mode());
}
public void drawPixel(int x, int y, int red, int green, int blue){
if(modeService.getMode() != Mode.DRAW_PIXEL) return;
Image image = imageService.getImage();
image.setPixelColor(x, y, red, green, blue);
imageService.setImage(image);
}
public void drawShape(int x1, int x2, int y1, int y2, int red, int green, int blue){
Image image = imageService.getImage();
switch (modeService.getMode()) {
case DRAW_RECTANGLE:
image.setRectangleColor(x1, x2, y1, y2, red, green, blue);
break;
case DRAW_LINE:
image.setLineColor(x1, x2, y1, y2, red, green, blue);
break;
case DRAW_CIRCLE:
break;
}
imageService.setImage(image);
}
}

View File

@@ -0,0 +1,55 @@
package presenters;
import app.INavigator;
import com.google.inject.Inject;
import domain.common.Mode;
import domain.image.GrayScaleMatrix;
import services.ImageService;
import services.ModeService;
import ui.interfaces.INavBar;
import java.io.File;
import java.io.IOException;
/**
* @author Laurent Crema
*/
public class NavPresenter {
private INavBar navBar;
private INavigator navigator;
private final ImageService imageService;
private final ModeService modeService;
@Inject
public NavPresenter(INavigator navigator, ImageService imageService, ModeService modeService) {
this.navigator = navigator;
this.imageService = imageService;
this.modeService = modeService;
}
public void setView(INavBar navBar) {
this.navBar = navBar;
}
public void createImage(int red, int green, int blue, int height, int width) {
imageService.createImage(red, green, blue, height, width);
}
public void loadImage(File f) throws IOException {
imageService.loadImage(f);
}
public void goToFourier(){
navigator.showFourier();
}
public GrayScaleMatrix getImageGrayMatrix() {
//return ((CImageNG)appState.getImage()).getMatrice();
return imageService.getImage().toGrayScale();
}
public void setMode(Mode mode) {
modeService.setMode(mode);
}
}

View File

@@ -0,0 +1,55 @@
package services;
import app.state.AppState;
import com.google.inject.Inject;
import domain.image.Image;
import domain.image.GrayScaleMatrix;
import domain.image.processing.complex.ComplexMatrix;
import domain.image.processing.fourier.Fourier;
import infrastructure.image.io.ImageLoader;
import infrastructure.image.io.ImageSaver;
import java.io.File;
import java.io.IOException;
public class ImageService {
private final AppState appState;
@Inject
public ImageService(AppState appState) {
this.appState = appState;
}
public void createImage(int red, int green, int blue, int height, int width) {
Image image = new Image(red, green, blue, height, width);
appState.setImage(image);
}
public void loadImage(File f) throws IOException {
Image image = ImageLoader.loadImage(f);
appState.setImage(image);
}
public void saveImage(Image image) throws IOException {
ImageSaver.saveImage(image);
}
public ComplexMatrix computeFourier(){
GrayScaleMatrix matrix = appState.getImage().toGrayScale();
ComplexMatrix fourier = Fourier.Fourier2D(matrix.getRawData());
return Fourier.decroise(fourier);
}
public Image getImage(){
return appState.getImage();
}
public void setImage(Image img){
appState.setImage(img);
}
public GrayScaleMatrix getGrayScale(){
return appState.getImage().toGrayScale();
}
}

View File

@@ -0,0 +1,22 @@
package services;
import app.state.AppState;
import com.google.inject.Inject;
import domain.common.Mode;
public class ModeService {
private final AppState appState;
@Inject
public ModeService(AppState appState) {
this.appState = appState;
}
public void setMode(Mode m){
appState.setMode(m);
}
public Mode getMode() { return this.appState.getMode(); }
}

View File

@@ -0,0 +1,79 @@
package ui.implementation.components.image;
import domain.image.GrayScaleMatrix;
import domain.image.Image;
import infrastructure.ui.ImageMapper;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ImagePanel extends JPanel {
private BufferedImage image;
private double scale;
private int drawW;
private int drawH;
private int offsetX;
private int offsetY;
public ImagePanel() { }
public ImagePanel(BufferedImage image) {
loadImage(image);
}
public void loadImage(BufferedImage image){
this.image = image;
setPreferredSize(new Dimension(image.getWidth(null), image.getHeight(null)));
repaint();
}
public void loadImage(GrayScaleMatrix matrix){
this.image = ImageMapper.toBufferedImage(matrix.toImage());
setPreferredSize(new Dimension(this.image.getWidth(null), this.image.getHeight(null)));
repaint();
}
public Point toImageCoordinates(int x, int y) {
if (image == null) return null;
if (x < offsetX || x >= offsetX + drawW ||
y < offsetY || y >= offsetY + drawH) {
return null;
}
int imgX = (int) ((x - offsetX) / scale);
int imgY = (int) ((y - offsetY) / scale);
return new Point(imgX, imgY);
}
private void computeViewport() {
if (image == null) return;
int imgW = image.getWidth();
int imgH = image.getHeight();
scale = Math.min(
(double) getWidth() / imgW,
(double) getHeight() / imgH
);
drawW = (int) (imgW * scale);
drawH = (int) (imgH * scale);
offsetX = (getWidth() - drawW) / 2;
offsetY = (getHeight() - drawH) / 2;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) return;
computeViewport();
g.drawImage(image, offsetX, offsetY, drawW, drawH, null);
}
}

View File

@@ -0,0 +1,9 @@
package ui.implementation.components.intent;
import javax.swing.*;
public class FileChooser extends JFileChooser {
public FileChooser(String initialLocation) {
super(initialLocation);
}
}

View File

@@ -0,0 +1,32 @@
package ui.implementation.components.nav;
import javax.swing.*;
import java.net.URL;
public class Menu extends JMenu {
public Menu(String title, JMenuItem... items)
{
this(title,null, items);
}
public Menu(String title, String iconPath, JMenuItem... items)
{
super(title);
if (iconPath != null) {
URL url = getClass().getResource(iconPath);
if (url != null) {
setIcon(new ImageIcon(url));
}
}
if (items != null) {
for (JMenuItem item : items) {
if (item != null) {
this.add(item);
}
}
}
}
}

View File

@@ -0,0 +1,25 @@
package ui.implementation.components.nav;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.net.URL;
public class MenuItem extends JMenuItem {
public MenuItem(String title, ActionListener listener) {
this(title, null, listener);
}
public MenuItem(String title, String iconPath, ActionListener listener) {
super(title);
if(iconPath != null) {
URL url = getClass().getResource(iconPath);
if (url != null) {
super.setIcon(new ImageIcon(url));
}
}
if (listener != null) {
addActionListener(listener);
}
}
}

View File

@@ -0,0 +1,301 @@
package ui.implementation.components.nav;
import domain.image.GrayScaleMatrix;
import domain.image.processing.histogram.Histogramme;
import domain.common.Mode;
import jakarta.inject.Inject;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import presenters.NavPresenter;
import ui.implementation.components.intent.FileChooser;
import ui.implementation.dialogs.ImageCreatorDialog;
import ui.implementation.dialogs.GreyScaleImageCreatorDialog;
import ui.implementation.dialogs.RGBImageCreatorDialog;
import ui.interfaces.INavBar;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
/**
* @author Jean-Marc Wagner, Laurent Crema
*/
public class NavBar extends JMenuBar implements INavBar {
private JMenu imageMenu;
private JMenu drawingMenu;
private JMenu fourierMenu;
private JMenu linearMenu;
private JMenu histogramMenu;
private NavPresenter presenter;
@Inject
public NavBar(NavPresenter presenter) {
this.presenter = presenter;
this.presenter.setView(this);
initComponents();
}
private void initComponents(){
imageMenu = new Menu("Image","/net_13_p1.jpg",
new Menu("Nouvelle", "/file_65_p3.jpg",
new MenuItem("RGB", e -> this.createImage(e, new RGBImageCreatorDialog(new JFrame(),true))),
new MenuItem("NG", e -> this.createImage(e, new GreyScaleImageCreatorDialog(new JFrame(),true)))
),
new MenuItem("Ouvrir...", "/folder_036_p3.jpg", this::loadImage),
new MenuItem("Enregistrer sous...","/dd_27_p3.jpg", e -> {}),
new MenuItem("Quitter","/cp_59_p3.jpg", this::quit)
);
drawingMenu = new Menu("Editer","/dd_28_p1.jpg",
new Menu("Dessiner", "/display_14_p3.jpg",
new MenuItem("Couleur", this::chooseColor),
new Menu("Formes",
new MenuItem("Pixel", e -> this.setMode(e, Mode.DRAW_PIXEL)),
new MenuItem("Ligne", e -> this.setMode(e, Mode.DRAW_LINE)),
new MenuItem("Rectangle",e -> this.setMode(e, Mode.DRAW_RECTANGLE)),
new MenuItem("Cercle", e -> this.setMode(e, Mode.DRAW_CIRCLE))
)
),
new Menu("Convertir",
new MenuItem("RGB", e -> {}),
new MenuItem("NG", e -> {})
)
);
fourierMenu = new Menu("Fourier","/cp_51_p1.jpg",
new MenuItem("Afficher", "/cp_51_p3.jpg", this::displayFourier)
);
linearMenu = new Menu("Linéaire","/cp_51_p1.jpg",
new Menu("Global",
new Menu("Formes",
new MenuItem("PasseBasIdeal", e -> this.setMode(e, Mode.DRAW_PIXEL)),
new MenuItem("PasseHautIdeal", e -> this.setMode(e, Mode.DRAW_LINE)),
new MenuItem("PasseBasButterworth",e -> this.setMode(e, Mode.DRAW_RECTANGLE)),
new MenuItem("PasseHautButterworth", e -> this.setMode(e, Mode.DRAW_CIRCLE))
)
)
);
histogramMenu = new Menu("Histogramme","/report_48_hot.jpg",
new MenuItem("Afficher", "/report_32_hot.jpg",this::displayHistogram)
);
this.add(imageMenu);
this.add(drawingMenu);
this.add(fourierMenu);
this.add(linearMenu);
this.add(histogramMenu);
drawingMenu.setEnabled(false);
fourierMenu.setEnabled(false);
linearMenu.setEnabled(false);
histogramMenu.setEnabled(false);
}
//####################################################
private File chooseFile(){
FileChooser chooser = new FileChooser("./");
int dialogResult = chooser.showOpenDialog(this);
if (dialogResult != JFileChooser.APPROVE_OPTION) return null;
return chooser.getSelectedFile();
}
private void loadImage(ActionEvent e) {
try
{
File file = chooseFile();
if(file == null) return;
presenter.loadImage(file);
activeMenusRGB();
activeMenusNG();
}
catch (IOException ex)
{
System.err.println("Erreur I/O : " + ex.getMessage());
}
}
private void quit(ActionEvent e) {
System.exit(0);
}
private void createImage(ActionEvent e, ImageCreatorDialog dialog) {
dialog.setVisible(true);
presenter.createImage(
dialog.getRed(), dialog.getGreen(), dialog.getBlue(),
dialog.getImageHeight(), dialog.getImageWidth());
activeMenusRGB();
activeMenusNG();
}
private void setMode(ActionEvent e, Mode mode) {
presenter.setMode(mode);
}
private void chooseColor(ActionEvent e) {
/*if (imageRGB != null)
{
Color newC = JColorChooser.showDialog(this,"Couleur du pinceau", couleurPinceauRGB);
if (newC != null) couleurPinceauRGB = newC;
observer.setCouleurPinceau(couleurPinceauRGB);
}
if (imageNG != null)
{
GreyScalePicker dialog = new GreyScalePicker(new JFrame(),true, couleurPinceauNG);
dialog.setVisible(true);
couleurPinceauNG = dialog.getCouleur();
}*/
}
private void activeMenusNG()
{
drawingMenu.setEnabled(true);
fourierMenu.setEnabled(true);
linearMenu.setEnabled(true);
histogramMenu.setEnabled(true);
}
private void activeMenusRGB()
{
drawingMenu.setEnabled(true);
fourierMenu.setEnabled(false);
linearMenu.setEnabled(false);
histogramMenu.setEnabled(false);
}
//####################################################
private void displayHistogram(ActionEvent e) {
GrayScaleMatrix i_graymatrix = presenter.getImageGrayMatrix();
int[] histo = Histogramme.Histogramme256(i_graymatrix);
//Création du dataset
XYSeries serie = new XYSeries("Histo");
for(int i=0 ; i<256 ; i++) serie.add(i,histo[i]);
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(serie);
// Creation du chart
JFreeChart chart = ChartFactory.createHistogram("Histogramme","Niveaux de gris",
"Nombre de pixels", dataset, PlotOrientation.VERTICAL,false,false,false);
XYPlot plot = chart.getXYPlot();
ValueAxis axeX = plot.getDomainAxis();
axeX.setRange(0,255);
plot.setDomainAxis(axeX);
// creation d'une frame
ChartFrame frame = new ChartFrame("Histogramme de l'image",chart);
frame.pack();
frame.setVisible(true);
}
private void jMenuItemFourierAfficherPartieImaginaireActionPerformed(ActionEvent e) {
// try
// {
// int f_int[][] = imageNG.getMatrice();
// double f[][] = new double[imageNG.getLargeur()][imageNG.getHauteur()];
// for(int i=0 ; i<imageNG.getLargeur() ; i++)
// for(int j=0 ; j<imageNG.getHauteur() ; j++) f[i][j] = (double)(f_int[i][j]);
//
// System.out.println("Debut Fourier");
// MatriceComplexe fourier = Fourier.Fourier2D(f);
// System.out.println("Fin Fourier");
// fourier = Fourier.decroise(fourier);
// double partieImaginaire[][] = fourier.getPartieImaginaire();
//
// DoubleMatrix dialog = new DoubleMatrix(this,true,partieImaginaire,"Fourier : Affichage de la partie imaginaire");
// dialog.setVisible(true);
// }
// catch (CImageNGException ex)
// {
// System.out.println("Erreur CImageNG : " + ex.getMessage());
// }
}
private void jMenuItemFourierAfficherPartieReelleActionPerformed(ActionEvent e) {
// try
// {
// int f_int[][] = imageNG.getMatrice();
// double f[][] = new double[imageNG.getLargeur()][imageNG.getHauteur()];
// for(int i=0 ; i<imageNG.getLargeur() ; i++)
// for(int j=0 ; j<imageNG.getHauteur() ; j++) f[i][j] = (double)(f_int[i][j]);
//
// System.out.println("Debut Fourier");
// MatriceComplexe fourier = Fourier.Fourier2D(f);
// System.out.println("Fin Fourier");
// fourier = Fourier.decroise(fourier);
// double partieReelle[][] = fourier.getPartieReelle();
//
// DoubleMatrix dialog = new DoubleMatrix(this,true,partieReelle,"Fourier : Affichage de la partie reelle");
// dialog.setVisible(true);
// }
// catch (CImageNGException ex)
// {
// System.out.println("Erreur CImageNG : " + ex.getMessage());
// }
}
private void jMenuItemFourierAfficherPhaseActionPerformed(ActionEvent e) {
// try
// {
// int f_int[][] = imageNG.getMatrice();
// double f[][] = new double[imageNG.getLargeur()][imageNG.getHauteur()];
// for(int i=0 ; i<imageNG.getLargeur() ; i++)
// for(int j=0 ; j<imageNG.getHauteur() ; j++) f[i][j] = (double)(f_int[i][j]);
//
// System.out.println("Debut Fourier");
// MatriceComplexe fourier = Fourier.Fourier2D(f);
// System.out.println("Fin Fourier");
// fourier = Fourier.decroise(fourier);
// double phase[][] = fourier.getPhase();
//
// DoubleMatrix dialog = new DoubleMatrix(this,true,phase,"Fourier : Affichage de la phase");
// dialog.setVisible(true);
// }
// catch (CImageNGException ex)
// {
// System.out.println("Erreur CImageNG : " + ex.getMessage());
// }
}
private void displayFourier(ActionEvent e) {
try
{
presenter.goToFourier();
// int f_int[][] = imageNG.getMatrice();
// double f[][] = new double[imageNG.getLargeur()][imageNG.getHauteur()];
// for(int i=0 ; i<imageNG.getLargeur() ; i++)
// for(int j=0 ; j<imageNG.getHauteur() ; j++) f[i][j] = (double)(f_int[i][j]);
//
// System.out.println("Debut Fourier");
// MatriceComplexe fourier = Fourier.Fourier2D(f);
// System.out.println("Fin Fourier");
// fourier = Fourier.decroise(fourier);
// double module[][] = fourier.getModule();
//
// DoubleMatrix dialog = new DoubleMatrix(this,true,module,"Fourier : Affichage du module");
// dialog.setVisible(true);
}
catch (Exception ex)
{
System.out.println("Erreur CImageNG : " + ex.getMessage());
}
}
}

View File

@@ -0,0 +1,38 @@
package ui.implementation.dialogs;
import java.awt.Color;
import javax.swing.*;
public class GreyScaleImageCreatorDialog extends ImageCreatorDialog
{
private JSlider slider;
public GreyScaleImageCreatorDialog(java.awt.Frame parent, boolean modal)
{
super(parent, modal);
createColorPicker();
}
@Override
protected void createColorPicker() {
slider = new JSlider();
slider.setValue(getValue());
slider.setMajorTickSpacing(255);
slider.setMaximum(255);
slider.setMinorTickSpacing(15);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.addChangeListener(this::jSliderStateChanged);
colorPickerContainer.add(slider);
}
private int getValue(){
return color.getRed();
}
private void jSliderStateChanged(javax.swing.event.ChangeEvent evt) {
int value = slider.getValue();
color = new Color(value, value, value);
colorVisualizer.setBackground(color);
}
}

View File

@@ -0,0 +1,122 @@
package ui.implementation.dialogs;
import java.awt.Color;
public class GreyScalePicker extends javax.swing.JDialog
{
private int couleur;
/** Creates new form JDialogChoixCouleurNG */
public GreyScalePicker(java.awt.Frame parent, boolean modal, int c)
{
super(parent, modal);
couleur = c;
initComponents();
couleur = c;
jSlider.setValue(couleur);
jPanel.setBackground(new Color(couleur,couleur,couleur));
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
jSlider = new javax.swing.JSlider();
jPanel = new javax.swing.JPanel();
jButtonOk = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Choix du niveau de gris");
setResizable(false);
jSlider.setMajorTickSpacing(255);
jSlider.setMaximum(255);
jSlider.setMinorTickSpacing(15);
jSlider.setPaintLabels(true);
jSlider.setPaintTicks(true);
jSlider.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
jSliderStateChanged(evt);
}
});
jPanel.setBorder(javax.swing.BorderFactory.createCompoundBorder(null, javax.swing.BorderFactory.createLineBorder(new Color(255, 0, 0))));
javax.swing.GroupLayout jPanelLayout = new javax.swing.GroupLayout(jPanel);
jPanel.setLayout(jPanelLayout);
jPanelLayout.setHorizontalGroup(
jPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 62, Short.MAX_VALUE)
);
jPanelLayout.setVerticalGroup(
jPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 45, Short.MAX_VALUE)
);
jButtonOk.setText("Ok");
jButtonOk.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonOkActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(19, 19, 19)
.addComponent(jPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
.addComponent(jButtonOk, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jButtonOk, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE)
.addComponent(jPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSlider, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jButtonOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonOkActionPerformed
couleur = jSlider.getValue();
setVisible(false);
dispose();
}//GEN-LAST:event_jButtonOkActionPerformed
private void jSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSliderStateChanged
int valeur = jSlider.getValue();
Color c = new Color(valeur,valeur,valeur);
jPanel.setBackground(c);
}//GEN-LAST:event_jSliderStateChanged
public int getCouleur() { return couleur; }
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new GreyScalePicker(new javax.swing.JFrame(), true, 128).setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButtonOk;
private javax.swing.JPanel jPanel;
private javax.swing.JSlider jSlider;
// End of variables declaration//GEN-END:variables
}

View File

@@ -0,0 +1,167 @@
package ui.implementation.dialogs;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public abstract class ImageCreatorDialog extends JDialog
{
protected Color color;
protected int height;
protected int width;
protected JButton confirmButton;
protected JPanel colorVisualizer;
protected JComponent colorPickerContainer;
protected JTextField heightInput;
protected JTextField widthInput;
public ImageCreatorDialog(Frame parent, boolean modal)
{
super(parent, modal);
initComponents();
color = new Color(255,255,255);
width = 256;
height = 256;
}
private void initComponents() {
colorVisualizer = new JPanel();
confirmButton = new JButton();
widthInput = new JTextField();
heightInput = new JTextField();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Choix de la couleur");
setResizable(false);
GroupLayout jPanelLayout = new GroupLayout(colorVisualizer);
colorVisualizer.setBorder(
BorderFactory.createCompoundBorder(null,
BorderFactory.createLineBorder(new Color(255, 0, 0)))
);
colorVisualizer.setLayout(jPanelLayout);
jPanelLayout.setHorizontalGroup(
jPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGap(0, 62, Short.MAX_VALUE)
);
jPanelLayout.setVerticalGroup(
jPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGap(0, 55, Short.MAX_VALUE)
);
confirmButton.setText("Ok");
confirmButton.addActionListener(this::onConfirmClicked);
widthInput.setHorizontalAlignment(JTextField.CENTER);
heightInput.setHorizontalAlignment(JTextField.CENTER);
JLabel widthLabel = new JLabel("Largeur");
JLabel heightLabel = new JLabel("Hauteur");
colorPickerContainer = new JPanel(new BorderLayout());
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(27, 27, 27)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(widthLabel)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(widthInput, GroupLayout.PREFERRED_SIZE, 97, GroupLayout.PREFERRED_SIZE)
.addGap(37, 37, 37)
.addComponent(heightLabel)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(heightInput, GroupLayout.PREFERRED_SIZE, 96, GroupLayout.PREFERRED_SIZE)
.addContainerGap(51, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(colorVisualizer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGap(25, 25, 25)
.addComponent(colorPickerContainer)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 135, Short.MAX_VALUE)
.addComponent(confirmButton, GroupLayout.PREFERRED_SIZE, 65, GroupLayout.PREFERRED_SIZE)
.addGap(26, 26, 26))))
);
layout.linkSize(SwingConstants.HORIZONTAL, heightInput, widthInput);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(24, 24, 24)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(heightInput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(heightLabel)
.addComponent(widthInput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(widthLabel)
)
.addGap(37, 37, 37)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(confirmButton, GroupLayout.DEFAULT_SIZE, 57, Short.MAX_VALUE)
.addComponent(colorPickerContainer, GroupLayout.DEFAULT_SIZE, 57, Short.MAX_VALUE))
.addComponent(colorVisualizer, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
pack();
colorVisualizer.setBackground(color);
widthInput.setText("256");
heightInput.setText("256");
}
protected void onColorChosen(ActionEvent e) {
Color color = JColorChooser.showDialog(this,"Couleur de fond", this.color);
if (color == null) return;
this.color = color;
colorVisualizer.setBackground(this.color);
}
protected void onConfirmClicked(ActionEvent e) {
try
{
height = Integer.parseInt(widthInput.getText());
width = Integer.parseInt(heightInput.getText());
setVisible(false);
dispose();
} catch(NumberFormatException nfe)
{
JOptionPane.showMessageDialog(this,
"Hauteur et Largeur doivent etre entiers !","Erreur",
JOptionPane.ERROR_MESSAGE);
}
}
public Color getImageColor() {
return color;
}
public int getRed() {
return color.getRed();
}
public int getGreen() {
return color.getGreen();
}
public int getBlue() {
return color.getBlue();
}
public int getImageWidth(){
return width;
}
public int getImageHeight(){
return height;
}
protected abstract void createColorPicker();
}

View File

@@ -0,0 +1,24 @@
package ui.implementation.dialogs;
import javax.swing.*;
import java.awt.*;
public class RGBImageCreatorDialog extends ImageCreatorDialog
{
private JButton colorPickerButton;
public RGBImageCreatorDialog(Frame parent, boolean modal)
{
super(parent, modal);
createColorPicker();
}
@Override
protected void createColorPicker() {
colorPickerButton = new JButton();
colorPickerButton.setText("Choisir");
colorPickerButton.addActionListener(this::onColorChosen);
colorPickerContainer.add(colorPickerButton);
}
}

View File

@@ -0,0 +1,374 @@
package ui.implementation.views;
import domain.image.GrayScaleMatrix;
import domain.image.Image;
import jakarta.inject.Inject;
import presenters.DoubleMatrixPresenter;
import ui.implementation.components.image.ImagePanel;
import ui.implementation.components.intent.FileChooser;
import ui.interfaces.IDoubleMatrix;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;
import java.util.Objects;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
/**
* @author Jean-Marc Wagner, Laurent Crema
*/
public class DoubleMatrix extends JFrame implements IDoubleMatrix
{
private double normalizedWhite;
private double normalizedBlack;
private boolean isUpdating = false;
private JTabbedPane modeTab;
private ImagePanel modulePreviewContainer;
private ImagePanel phasePreviewContainer;
private ImagePanel realPreviewContainer;
private ImagePanel imaginaryPreviewContainer;
private JSlider whiteSlider;
private JTextField whiteTextField;
private JLabel maxLabel;
private JSlider blackSlider;
private JTextField blackTextField;
private JLabel minLabel;
private final DoubleMatrixPresenter presenter;
@Inject
public DoubleMatrix(DoubleMatrixPresenter presenter)
{
this.presenter = presenter;
initComponents();
presenter.setView(this);
initValues();
}
private void initComponents() {
modulePreviewContainer = new ImagePanel();
phasePreviewContainer = new ImagePanel();
realPreviewContainer = new ImagePanel();
imaginaryPreviewContainer = new ImagePanel();
blackSlider = buildSlider();
whiteSlider = buildSlider();
blackTextField = buildTextField(Color.BLACK);
whiteTextField = buildTextField(null);
minLabel = buildValueLabel();
maxLabel = buildValueLabel();
JLabel minValueText = new JLabel("Valeur MIN :");
JLabel maxValueText = new JLabel("Valeur MAX :");
JButton saveButton = new JButton(new ImageIcon(Objects.requireNonNull(getClass().getResource("/dd_27_p3.jpg"))));
saveButton.addActionListener(this::saveImage);
blackSlider.addChangeListener(this::onValueUpdate);
whiteSlider.addChangeListener(this::onValueUpdate);
blackTextField.addActionListener(this::jTextFieldNoirActionPerformed);
whiteTextField.addActionListener(this::jTextFieldBlancActionPerformed);
modeTab = buildModeTab();
buildLayout(modeTab, maxValueText, minValueText, minLabel, maxLabel, saveButton);
setTitle("Fourier");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
pack();
}
private void initValues(){
modeTab.setSelectedIndex(1);
blackSlider.setValue(0);
whiteSlider.setValue(1000);
}
private JSlider buildSlider() {
return new JSlider(JSlider.VERTICAL);
}
private JTextField buildTextField(Color background) {
JTextField field = new JTextField();
field.setFont(new Font("Tahoma", Font.BOLD, 11));
field.setForeground(Color.RED);
field.setHorizontalAlignment(JTextField.CENTER);
if (background != null) field.setBackground(background);
return field;
}
private JLabel buildValueLabel() {
JLabel label = new JLabel("0.0");
label.setFont(new Font("Tahoma", Font.BOLD, 11));
label.setForeground(Color.BLUE);
return label;
}
private JTabbedPane buildModeTab(){
JTabbedPane modeTabs = new JTabbedPane();
modeTabs.addTab("Module", modulePreviewContainer);
modeTabs.addTab("Phase", phasePreviewContainer);
modeTabs.addTab("Partie réelle", realPreviewContainer);
modeTabs.addTab("Partie imaginaire", imaginaryPreviewContainer);
modeTabs.addChangeListener(e -> {
switch (modeTabs.getSelectedIndex()) {
case 0 -> presenter.loadModule();
case 1 -> presenter.loadPhase();
case 2 -> presenter.loadReal();
case 3 -> presenter.loadImaginary();
}
});
return modeTabs;
}
private void buildLayout(JTabbedPane modeTab,
JLabel labelMax, JLabel labelMin,
JLabel valeurMin, JLabel valeurMax,
JButton saveButton) {
JPanel rightPanel = new JPanel();
GroupLayout rightLayout = new GroupLayout(rightPanel);
rightPanel.setLayout(rightLayout);
rightLayout.setHorizontalGroup(
rightLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(whiteTextField, GroupLayout.PREFERRED_SIZE, 90, GroupLayout.PREFERRED_SIZE)
.addGroup(rightLayout.createSequentialGroup()
.addComponent(blackSlider)
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(whiteSlider)
)
.addComponent(blackTextField, GroupLayout.PREFERRED_SIZE, 90, GroupLayout.PREFERRED_SIZE)
);
rightLayout.setVerticalGroup(
rightLayout.createSequentialGroup()
.addComponent(whiteTextField, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addGroup(rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(blackSlider)
.addComponent(whiteSlider)
)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(blackTextField, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
);
// -------------------------
// MAIN LAYOUT
// -------------------------
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
// TOP BAR
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(labelMin)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(valeurMin)
.addGap(50)
.addComponent(labelMax)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(valeurMax)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED,
GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(saveButton)
.addContainerGap()
)
// MAIN ROW
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(modeTab, 400, 400, Short.MAX_VALUE)
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(rightPanel, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap()
)
);
layout.setVerticalGroup(
layout.createSequentialGroup()
// TOP BAR
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(labelMin)
.addComponent(valeurMin)
.addComponent(labelMax)
.addComponent(valeurMax)
.addComponent(saveButton)
)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
// MAIN CONTENT
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(modeTab)
.addComponent(rightPanel)
)
);
}
private File chooseFile(){
FileChooser chooser = new FileChooser("./");
int dialogResult = chooser.showOpenDialog(this);
if (dialogResult != JFileChooser.APPROVE_OPTION) return null;
return chooser.getSelectedFile();
}
private void onValueUpdate(ChangeEvent e) {
if (isUpdating) return;
isUpdating = true;
try {
int black = blackSlider.getValue();
int white = whiteSlider.getValue();
int minGap = 1;
if (white - black < minGap) {
if (blackSlider.getValueIsAdjusting()) {
black = white - minGap;
blackSlider.setValue(black);
} else {
white = black + minGap;
whiteSlider.setValue(white);
}
}
normalizedBlack = (double) black / blackSlider.getMaximum();
normalizedWhite = (double) white / whiteSlider.getMaximum();
switch (modeTab.getSelectedIndex()) {
case 0 -> presenter.clipModule(normalizedBlack, normalizedWhite);
case 1 -> presenter.clipPhase(normalizedBlack, normalizedWhite);
case 2 -> presenter.clipReal(normalizedBlack, normalizedWhite);
case 3 -> presenter.clipImaginary(normalizedBlack, normalizedWhite);
}
} finally {
isUpdating = false;
}
}
@Override
public void updateModule(GrayScaleMatrix source, GrayScaleMatrix clipped) {
updatePreview(modulePreviewContainer, source, clipped);
}
@Override
public void updatePhase(GrayScaleMatrix source, GrayScaleMatrix clipped) {
updatePreview(phasePreviewContainer, source, clipped);
}
@Override
public void updateReal(GrayScaleMatrix source, GrayScaleMatrix clipped) {
updatePreview(realPreviewContainer, source, clipped);
}
@Override
public void updateImaginary(GrayScaleMatrix source, GrayScaleMatrix clipped) {
updatePreview(imaginaryPreviewContainer, source, clipped);
}
private void updatePreview(ImagePanel imagePanel, GrayScaleMatrix source, GrayScaleMatrix matrix) {
try {
imagePanel.loadImage(matrix);
updateLabels(source.getMinValue(), source.getMaxValue());
updateTextFields(
presenter.getValueAt(source, normalizedBlack),
presenter.getValueAt(source, normalizedWhite)
);
} catch (Exception e){
displayErrorMessage("Oups !", e.getMessage());
}
}
private void updateTextFields(double black, double white) {
blackTextField.setText(String.format("%.5f", black));
whiteTextField.setText(String.format("%.5f", white));
}
private void updateLabels(double black, double white) {
minLabel.setText(String.format("%.5f", black));
maxLabel.setText(String.format("%.5f", white));
}
private void saveImage(ActionEvent evt) {
File file = chooseFile();
if (file != null) {
try {
presenter.saveImage(null);
//image.enregistreFormatPNG(fichier);
} catch (IOException ex) {
System.err.println("Erreur I/O : " + ex.getMessage());
}
}
}
private void displayErrorMessage(String title, String message) {
JOptionPane.showMessageDialog(
this,
message,
title,
JOptionPane.ERROR_MESSAGE
);
}
private void jTextFieldNoirActionPerformed(ActionEvent evt) {
// double val = Double.parseDouble(jTextFieldNoir.getText());
//
// double black = presenter.getBlackLevel();
// double white = presenter.getWhiteLevel();
//
// if (val < black)
// {
// jSliderNoir.setValue(0);
// return;
// }
// if (val >= normalizedWhite)
// {
// jSliderNoir.setValue(jSliderBlanc.getValue()-1);
// return;
// }
// int s = (int)((double)D*(val-black)/(white-black)+0.5);
// jSliderNoir.setValue(s);
}
private void jTextFieldBlancActionPerformed(ActionEvent evt) {
// double val = Double.parseDouble(jTextFieldBlanc.getText());
// double black = presenter.getBlackLevel();
// double white = presenter.getWhiteLevel();
//
// if (val > white)
// {
// jSliderBlanc.setValue(D);
// return;
// }
// if (val <= normalizedBlack)
// {
// jSliderBlanc.setValue(jSliderNoir.getValue()+1);
// return;
// }
// int s = (int)((double)D*(val-black)/(white-black)+0.5);
// jSliderBlanc.setValue(s);
}
}

View File

@@ -0,0 +1,201 @@
package ui.implementation.views;
import com.google.inject.Inject;
import domain.common.Mode;
import domain.image.Image;
import infrastructure.ui.ImageMapper;
import presenters.MainPresenter;
import ui.implementation.components.image.ImagePanel;
import ui.implementation.components.nav.NavBar;
import ui.interfaces.IMainView;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
/**
* @author Jean-Marc Wagner, Laurent Crema
*/
public class MainView extends JFrame implements IMainView
{
private Mode currentMode;
private ImagePanel imagePreviewContainer;
private final MainPresenter presenter;
@Inject
public MainView(MainPresenter presenter){
this.presenter = presenter;
this.presenter.setView(this);
initComponents();
}
public void setNavBar(NavBar navBar) {
setJMenuBar(navBar);
}
private void initComponents() {
imagePreviewContainer = new ImagePanel();
imagePreviewContainer.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
drawPixel(e.getX(), e.getY(), 255, 0, 0);
}
});
imagePreviewContainer.addMouseListener(new MouseAdapter() {
private Point startPoint;
@Override
public void mousePressed(MouseEvent e) {
startPoint = new Point(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
Point endPoint = new Point(e.getX(), e.getY());
if (startPoint == null) return;
drawShape(
startPoint.x,
endPoint.x,
startPoint.y,
endPoint.y,
255, 0, 0
);
startPoint = null;
}
});
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(imagePreviewContainer)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(imagePreviewContainer)
.addContainerGap())
);
setSize(new Dimension(500, 400));
setLocationRelativeTo(null);
}
public void drawPixel(int x, int y, int red, int green, int blue){
try {
Point p = imagePreviewContainer.toImageCoordinates(x, y);
if(p == null) return;
presenter.drawPixel((int)p.getX(), (int)p.getY(), red, green, blue);
} catch (Exception e) {
displayErrorMessage("Oups !",
"Impossible de dessiner sur l'image pour le moment : " + e.getMessage());
}
}
public void drawShape(int x1, int x2, int y1, int y2, int red, int green, int blue){
try {
Point p1 = imagePreviewContainer.toImageCoordinates(x1, y1);
Point p2 = imagePreviewContainer.toImageCoordinates(x2, y2);
if(p1 == null || p2 == null) return;
presenter.drawShape(
(int)p1.getX(), (int)p2.getX(), (int) p1.getY(), (int) p2.getY(),
red, green, blue);
} catch (Exception e) {
displayErrorMessage("Oups !",
"Impossible de dessiner sur l'image pour le moment : " + e.getMessage());
}
}
// public void SelectCercleDetected(DeuxClicsEvent e)
// {
// if (presenter.isCircleModeActive())
// {
// try
// {
// if (imageRGB != null)
// imageRGB.DessineCercle(e.getX1(),e.getY1(),e.getX2(),e.getY2(),couleurPinceauRGB);
// if (imageNG != null)
// imageNG.DessineCercle(e.getX1(),e.getY1(),e.getX2(),e.getY2(),couleurPinceauNG);
// }
// catch (CImageRGBException ex)
// { System.out.println("Erreur RGB : " + ex.getMessage()); }
// catch (CImageNGException ex)
// { System.out.println("Erreur NG : " + ex.getMessage()); }
// }
// }
//
// public void SelectCercleFillDetected(DeuxClicsEvent e)
// {
// if (presenter.isPlainCircleModeActive())
// {
// try
// {
// if (imageRGB != null)
// imageRGB.RemplitCercle(e.getX1(),e.getY1(),e.getX2(),e.getY2(),couleurPinceauRGB);
// if (imageNG != null)
// imageNG.RemplitCercle(e.getX1(),e.getY1(),e.getX2(),e.getY2(),couleurPinceauNG);
// }
// catch (CImageRGBException ex)
// { System.out.println("Erreur RGB : " + ex.getMessage()); }
// catch (CImageNGException ex)
// { System.out.println("Erreur NG : " + ex.getMessage()); }
// }
// }
//
// public void SelectRectFillDetected(DeuxClicsEvent e)
// {
// if (presenter.isPlainRectangleActive())
// {
// try
// {
// if (imageRGB != null)
// imageRGB.RemplitRect(e.getX1(),e.getY1(),e.getX2(),e.getY2(),couleurPinceauRGB);
// if (imageNG != null)
// imageNG.RemplitRect(e.getX1(),e.getY1(),e.getX2(),e.getY2(),couleurPinceauNG);
// }
// catch (CImageRGBException ex)
// { System.out.println("Erreur RGB : " + ex.getMessage()); }
// catch (CImageNGException ex)
// { System.out.println("Erreur NG : " + ex.getMessage()); }
// }
// }
@Override
public void displayImage(Image image) {
try {
BufferedImage bufferedImage = ImageMapper.toBufferedImage(image);
imagePreviewContainer.loadImage(bufferedImage);
} catch (Exception ex) {
displayErrorMessage("Oups !", ex.getMessage());
}
}
@Override
public void changeMode(Mode m) {
}
private void displayErrorMessage(String title, String message) {
JOptionPane.showMessageDialog(
this,
message,
title,
JOptionPane.ERROR_MESSAGE
);
}
}

View File

@@ -0,0 +1,11 @@
package ui.interfaces;
import domain.image.GrayScaleMatrix;
public interface IDoubleMatrix {
void updateModule(GrayScaleMatrix source, GrayScaleMatrix clipped);
void updatePhase(GrayScaleMatrix source, GrayScaleMatrix clipped);
void updateReal(GrayScaleMatrix source, GrayScaleMatrix clipped);
void updateImaginary(GrayScaleMatrix source, GrayScaleMatrix clipped);
}

View File

@@ -0,0 +1,15 @@
package ui.interfaces;
import domain.common.Mode;
import domain.image.Image;
import presenters.DoubleMatrixPresenter;
import presenters.MainPresenter;
import java.awt.image.BufferedImage;
public interface IMainView {
void changeMode(Mode m);
void displayImage(Image image);
}

View File

@@ -0,0 +1,8 @@
package ui.interfaces;
import presenters.NavPresenter;
public interface INavBar {
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB