From 114da44ff4a384f7131a187f7649d49732e7fc57 Mon Sep 17 00:00:00 2001 From: Laurent Date: Sun, 4 Oct 2026 11:57:35 +0200 Subject: [PATCH] Add use case view --- src/main/java/app/shared/INavigator.java | 1 + src/main/java/app/shared/SwingNavigator.java | 12 +- src/main/java/presenters/NavPresenter.java | 2 + .../java/presenters/UseCasePresenter.java | 98 +++++++++++ src/main/java/services/UseCaseService.java | 97 ++++++++++ .../java/ui/abstractions/IUseCaseView.java | 20 +++ .../implementation/components/nav/NavBar.java | 9 + .../ui/implementation/views/MainView.java | 2 +- .../views/useCase/UseCaseView.java | 166 ++++++++++++++++++ 9 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 src/main/java/presenters/UseCasePresenter.java create mode 100644 src/main/java/services/UseCaseService.java create mode 100644 src/main/java/ui/abstractions/IUseCaseView.java create mode 100644 src/main/java/ui/implementation/views/useCase/UseCaseView.java diff --git a/src/main/java/app/shared/INavigator.java b/src/main/java/app/shared/INavigator.java index 3ac818a..df86355 100644 --- a/src/main/java/app/shared/INavigator.java +++ b/src/main/java/app/shared/INavigator.java @@ -18,4 +18,5 @@ public interface INavigator { void showLinearOutline(); void showNonLinearOutline(); void showThresholding(); + void showUseCase(); } diff --git a/src/main/java/app/shared/SwingNavigator.java b/src/main/java/app/shared/SwingNavigator.java index ed60c20..62e7be5 100644 --- a/src/main/java/app/shared/SwingNavigator.java +++ b/src/main/java/app/shared/SwingNavigator.java @@ -13,6 +13,7 @@ import ui.implementation.views.morphology.ComplexMorphologyView; import ui.implementation.views.outline.LinearOutlineView; import ui.implementation.views.outline.NonLinearOutlineView; import ui.implementation.views.threshold.ThresholdingView; +import ui.implementation.views.useCase.UseCaseView; /** * Concrete implement of the INavigator interface. @@ -30,6 +31,7 @@ public class SwingNavigator implements INavigator { private final Provider linearOutlineProvider; private final Provider nonLinearOutlineProvider; private final Provider thresholdingProvider; + private final Provider useCaseProvider; @Inject public SwingNavigator( @@ -41,7 +43,8 @@ public class SwingNavigator implements INavigator { Provider complexMorphologyProvider, Provider linearOutlineProvider, Provider nonLinearOutlineProvider, - Provider thresholdingProvider + Provider thresholdingProvider, + Provider useCaseProvider ) { this.doubleMatrixProvider = doubleMatrixProvider; this.filteringProvider = filteringProvider; @@ -52,6 +55,7 @@ public class SwingNavigator implements INavigator { this.linearOutlineProvider = linearOutlineProvider; this.nonLinearOutlineProvider = nonLinearOutlineProvider; this.thresholdingProvider = thresholdingProvider; + this.useCaseProvider = useCaseProvider; } @Override @@ -108,6 +112,12 @@ public class SwingNavigator implements INavigator { runView(view); } + @Override + public void showUseCase() { + UseCaseView view = useCaseProvider.get(); + runView(view); + } + private void runView(AbstractView view) { ViewInitializer.Initialize(view); view.setVisible(true); diff --git a/src/main/java/presenters/NavPresenter.java b/src/main/java/presenters/NavPresenter.java index ea96b97..35f3f80 100644 --- a/src/main/java/presenters/NavPresenter.java +++ b/src/main/java/presenters/NavPresenter.java @@ -60,6 +60,8 @@ public class NavPresenter { public void goToThresholding() { navigator.showThresholding(); } + public void goToUseCase() { navigator.showUseCase(); } + public GrayScaleMatrix getImageGrayMatrix() { return appState.getImage().toGrayScale(); } public void setMode(Mode mode) { modeService.setMode(mode); } diff --git a/src/main/java/presenters/UseCasePresenter.java b/src/main/java/presenters/UseCasePresenter.java new file mode 100644 index 0000000..0ec06c7 --- /dev/null +++ b/src/main/java/presenters/UseCasePresenter.java @@ -0,0 +1,98 @@ +package presenters; + +import com.google.inject.Inject; +import domain.image.Image; +import infrastructure.image.io.ImageLoader; +import services.UseCaseService; +import ui.abstractions.IUseCaseView; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Objects; + +public class UseCasePresenter { + + private static final String NOISE_1_IMAGE = "/imageBruitee1.png"; + private static final String NOISE_2_IMAGE = "/imageBruitee2.png"; + private static final String HISTOGRAM_IMAGE = "/lenaAEgaliser.jpg"; + private static final String PEAS_IMAGE = "/petitsPois.png"; + private static final String BARNACLES_IMAGE = "/balanes.png"; + private static final String TOOLS_IMAGE = "/tools.png"; + private static final String SPACECRAFT_IMAGE = "/vaisseaux.jpg"; + private static final String PLANET_IMAGE = "/planete.jpg"; + private static final String TOAST_IMAGE = "/Tartines.jpg"; + + private final UseCaseService service; + private IUseCaseView view; + + @Inject + public UseCasePresenter(UseCaseService service) { + this.service = service; + } + + public void setView(IUseCaseView view) { + this.view = view; + } + + public void computeNoiseReduction() { + Image image1 = loadImage(NOISE_1_IMAGE); + Image image2 = loadImage(NOISE_2_IMAGE); + Image[] results = {service.reduceNoise(image1), service.reduceNoise(image2)}; + view.updateNoiseReduction(results[0], results[1]); + } + + public void computeHistogramEqualization() { + Image image = loadImage(HISTOGRAM_IMAGE); + Image[] results = service.equalizeHistogram(image); + view.updateHistogramEqualization(results[0], results[1]); + } + + public void computePeasSegmentation() { + Image image = loadImage(PEAS_IMAGE); + Image[] results = service.segmentPeas(image); + view.updatePeasSegmentation(results[0], results[1]); + } + + public void computeBarnacleSegmentation() { + Image image = loadImage(BARNACLES_IMAGE); + Image[] results = service.segmentBarnacles(image); + view.updateBarnacleSegmentation(results[0], results[1]); + } + + public void computeToolsSegmentation() { + Image image = loadImage(TOOLS_IMAGE); + Image result = service.segmentTools(image); + view.updateToolsSegmentation(result); + } + + public void computeSpacecraftExtraction() { + Image spacecraft = loadImage(SPACECRAFT_IMAGE); + Image planet = loadImage(PLANET_IMAGE); + Image[] results = service.extractSpacecraft(spacecraft, planet); + view.updateSpacecraftExtraction(results[0], results[1]); + } + + public void computeToastOutline() { + Image image = loadImage(TOAST_IMAGE); + Image result = service.detectToastContours(image); + view.updateToastContours(result); + } + + private Image loadImage(String resourcePath) { + try { + File file = new File( + Objects.requireNonNull( + getClass().getResource("/ImagesFournies/ImagesEtape5/" + resourcePath) + ).toURI() + ); + return ImageLoader.loadImage(file); + } catch (IOException | URISyntaxException e) { + throw new IllegalStateException("Unable to load image: " + resourcePath, e); + } + } + + public void dispose() { + view = null; + } +} \ No newline at end of file diff --git a/src/main/java/services/UseCaseService.java b/src/main/java/services/UseCaseService.java new file mode 100644 index 0000000..25471ae --- /dev/null +++ b/src/main/java/services/UseCaseService.java @@ -0,0 +1,97 @@ +package services; + +import domain.image.GrayScaleMatrix; +import domain.image.Image; +import domain.image.processing.filtering.GlobalLinearFiltering; +import domain.image.processing.morphology.ComplexMorphology; + +import java.util.function.Supplier; + +public class UseCaseService { + + public Image reduceNoise(Image i0) { + GrayScaleMatrix m0 = i0.toGrayScale(); + GrayScaleMatrix m1 = GlobalLinearFiltering.butterworthLowPassFiltering(m0, 10, 1); + Image i1 = m1.toImage(); + return ComplexMorphology.medianFilter(i1, 9).toImage(); + } + + public Image[] equalizeHistogram(Image image) { + Image rgbEqualized = equalizeRgb(image); + Image luminanceEqualized = equalizeLuminance(image); + return new Image[]{rgbEqualized, luminanceEqualized}; + } + + public Image[] segmentPeas(Image image) { + Image bluePeas = extractBluePeas(image); + Image redPeas = extractRedPeas(image); + return new Image[]{bluePeas, redPeas}; + } + + public Image[] segmentBarnacles(Image image) { + Image largeBarnacles = extractLargeBarnacles(image); + Image smallBarnacles = extractSmallBarnacles(image); + return new Image[]{largeBarnacles, smallBarnacles}; + } + + public Image segmentTools(Image image) { + return extractTools(image); + } + + public Image[] extractSpacecraft(Image spacecraftImage, Image planetImage) { + Image synthesis = createSynthesis(spacecraftImage, planetImage); + Image synthesis2 = addSpacecraftContour(synthesis); + return new Image[]{synthesis, synthesis2}; + } + + public Image detectToastContours(Image image) { + return extractToastContours(image); + } + + private Image equalizeRgb(Image image) { + return image; + } + + private Image equalizeLuminance(Image image) { + return image; + } + + private Image extractBluePeas(Image image) { + return image; + } + + private Image extractRedPeas(Image image) { + return image; + } + + private Image extractLargeBarnacles(Image image) { + return image; + } + + private Image extractSmallBarnacles(Image image) { + return image; + } + + private Image extractTools(Image image) { + return image; + } + + private Image createSynthesis(Image spacecraftImage, Image planetImage) { + return planetImage; + } + + private Image addSpacecraftContour(Image synthesis) { + return synthesis; + } + + private Image extractToastContours(Image image) { + return image; + } + + public long measureTime(Supplier operation) { + long start = System.nanoTime(); + operation.get(); + return (System.nanoTime() - start) / 1_000_000; + } + +} \ No newline at end of file diff --git a/src/main/java/ui/abstractions/IUseCaseView.java b/src/main/java/ui/abstractions/IUseCaseView.java new file mode 100644 index 0000000..599ba9c --- /dev/null +++ b/src/main/java/ui/abstractions/IUseCaseView.java @@ -0,0 +1,20 @@ +package ui.abstractions; + +import domain.image.Image; + +public interface IUseCaseView { + + void updateNoiseReduction(Image image1, Image image2); + + void updateHistogramEqualization(Image rgbEqualized, Image luminanceEqualized); + + void updatePeasSegmentation(Image bluePeas, Image redPeas); + + void updateBarnacleSegmentation(Image largeBarnacles, Image smallBarnacles); + + void updateToolsSegmentation(Image tools); + + void updateSpacecraftExtraction(Image synthesis, Image synthesis2); + + void updateToastContours(Image result); +} \ No newline at end of file diff --git a/src/main/java/ui/implementation/components/nav/NavBar.java b/src/main/java/ui/implementation/components/nav/NavBar.java index 645d20c..7ea02e1 100644 --- a/src/main/java/ui/implementation/components/nav/NavBar.java +++ b/src/main/java/ui/implementation/components/nav/NavBar.java @@ -37,6 +37,7 @@ public class NavBar extends JMenuBar implements INavBar { private Menu outlineMenu; private Menu thresholdingMenu; private JMenu histogramMenu; + private JMenu useCaseMenu; private NavPresenter presenter; @@ -112,6 +113,10 @@ public class NavBar extends JMenuBar implements INavBar { new MenuItem("Afficher", "/report_32_hot.jpg",this::displayHistogram) ); + useCaseMenu = new Menu("Applications","/report_48_hot.jpg", + new MenuItem("Afficher", "/report_32_hot.jpg",this::displayUseCase) + ); + this.add(imageMenu); this.add(drawingMenu); this.add(fourierMenu); @@ -120,6 +125,7 @@ public class NavBar extends JMenuBar implements INavBar { this.add(outlineMenu); this.add(thresholdingMenu); this.add(histogramMenu); + this.add(useCaseMenu); drawingMenu.setEnabled(false); fourierMenu.setEnabled(false); @@ -128,6 +134,7 @@ public class NavBar extends JMenuBar implements INavBar { outlineMenu.setEnabled(false); thresholdingMenu.setEnabled(false); histogramMenu.setEnabled(false); + useCaseMenu.setEnabled(true); } @@ -274,6 +281,8 @@ public class NavBar extends JMenuBar implements INavBar { private void displayThresholding(ActionEvent actionEvent) { presenter.goToThresholding(); } + private void displayUseCase(ActionEvent actionEvent) { presenter.goToUseCase(); } + private void displayErrorMessage(String title, String message) { JOptionPane.showMessageDialog( this, diff --git a/src/main/java/ui/implementation/views/MainView.java b/src/main/java/ui/implementation/views/MainView.java index fb8528f..2e2eaae 100644 --- a/src/main/java/ui/implementation/views/MainView.java +++ b/src/main/java/ui/implementation/views/MainView.java @@ -89,7 +89,7 @@ public class MainView extends JFrame implements IMainView .addContainerGap()) ); - setSize(new Dimension(850, 550)); + setSize(new Dimension(1100, 800)); setLocationRelativeTo(null); } diff --git a/src/main/java/ui/implementation/views/useCase/UseCaseView.java b/src/main/java/ui/implementation/views/useCase/UseCaseView.java new file mode 100644 index 0000000..42548c4 --- /dev/null +++ b/src/main/java/ui/implementation/views/useCase/UseCaseView.java @@ -0,0 +1,166 @@ +package ui.implementation.views.useCase; + +import com.google.inject.Inject; +import domain.image.Image; +import presenters.UseCasePresenter; +import ui.abstractions.AbstractView; +import ui.abstractions.IUseCaseView; +import ui.implementation.components.image.TabbedImagePanel; +import ui.implementation.components.image.TabbedPanelFactory; + +import javax.swing.*; +import java.awt.*; + +public class UseCaseView extends AbstractView implements IUseCaseView { + + private static final String NOISE_1_TAB_TITLE = "Bruit 1"; + private static final String NOISE_2_TAB_TITLE = "Bruit 2"; + + private static final String HISTOGRAM_RGB_TAB_TITLE = "Égalisation RGB"; + private static final String HISTOGRAM_LUMINANCE_TAB_TITLE = "Égalisation luminance"; + + private static final String PEAS_BLUE_TAB_TITLE = "Pois bleus"; + private static final String PEAS_RED_TAB_TITLE = "Pois rouges"; + + private static final String BARNACLE_LARGE_TAB_TITLE = "Balanes grandes"; + private static final String BARNACLE_SMALL_TAB_TITLE = "Balanes petites"; + + private static final String TOOLS_TAB_TITLE = "Outils"; + + private static final String SPACECRAFT_TAB_TITLE = "Synthèse"; + private static final String SPACECRAFT_CONTOUR_TAB_TITLE = "Synthèse contour"; + + private static final String TOAST_TAB_TITLE = "Tartines"; + + private final UseCasePresenter presenter; + private final TabbedPanelFactory tabbedPanelFactory; + + private TabbedImagePanel resultPanel; + + private JButton noiseButton; + private JButton histogramButton; + private JButton peasButton; + private JButton barnacleButton; + private JButton toolsButton; + private JButton spacecraftButton; + private JButton toastButton; + + @Inject + public UseCaseView(UseCasePresenter presenter, TabbedPanelFactory tabbedPanelFactory) { + this.presenter = presenter; + this.tabbedPanelFactory = tabbedPanelFactory; + } + + @Override + public void initComponents() { + resultPanel = tabbedPanelFactory.createTabbedImagePanel( + NOISE_1_TAB_TITLE, + NOISE_2_TAB_TITLE, + HISTOGRAM_RGB_TAB_TITLE, + HISTOGRAM_LUMINANCE_TAB_TITLE, + PEAS_BLUE_TAB_TITLE, + PEAS_RED_TAB_TITLE, + BARNACLE_LARGE_TAB_TITLE, + BARNACLE_SMALL_TAB_TITLE, + TOOLS_TAB_TITLE, + SPACECRAFT_TAB_TITLE, + SPACECRAFT_CONTOUR_TAB_TITLE, + TOAST_TAB_TITLE + ); + + noiseButton = new JButton("Bruit"); + histogramButton = new JButton("Histogramme"); + peasButton = new JButton("Petits pois"); + barnacleButton = new JButton("Balanes"); + toolsButton = new JButton("Outils"); + spacecraftButton = new JButton("Vaisseau"); + toastButton = new JButton("Tartines"); + + noiseButton.addActionListener(e -> presenter.computeNoiseReduction()); + histogramButton.addActionListener(e -> presenter.computeHistogramEqualization()); + peasButton.addActionListener(e -> presenter.computePeasSegmentation()); + barnacleButton.addActionListener(e -> presenter.computeBarnacleSegmentation()); + toolsButton.addActionListener(e -> presenter.computeToolsSegmentation()); + spacecraftButton.addActionListener(e -> presenter.computeSpacecraftExtraction()); + toastButton.addActionListener(e -> presenter.computeToastOutline()); + + JPanel controlPanel = createControlPanel(); + + JPanel mainPanel = new JPanel(new BorderLayout(10, 10)); + mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + mainPanel.add(resultPanel, BorderLayout.CENTER); + mainPanel.add(controlPanel, BorderLayout.SOUTH); + + setContentPane(mainPanel); + + setTitle("Applications"); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setSize(1200, 800); + } + + private JPanel createControlPanel() { + JPanel panel = new JPanel(new GridLayout(1, 7, 5, 5)); + + panel.add(noiseButton); + panel.add(histogramButton); + panel.add(peasButton); + panel.add(barnacleButton); + panel.add(toolsButton); + panel.add(spacecraftButton); + panel.add(toastButton); + + return panel; + } + + @Override + public void initValues() { + presenter.setView(this); + } + + @Override + public void updateNoiseReduction(Image image1, Image image2) { + resultPanel.loadImage(NOISE_1_TAB_TITLE, image1); + resultPanel.loadImage(NOISE_2_TAB_TITLE, image2); + } + + @Override + public void updateHistogramEqualization(Image rgbEqualized, Image luminanceEqualized) { + resultPanel.loadImage(HISTOGRAM_RGB_TAB_TITLE, rgbEqualized); + resultPanel.loadImage(HISTOGRAM_LUMINANCE_TAB_TITLE, luminanceEqualized); + } + + @Override + public void updatePeasSegmentation(Image bluePeas, Image redPeas) { + resultPanel.loadImage(PEAS_BLUE_TAB_TITLE, bluePeas); + resultPanel.loadImage(PEAS_RED_TAB_TITLE, redPeas); + } + + @Override + public void updateBarnacleSegmentation(Image largeBarnacles, Image smallBarnacles) { + resultPanel.loadImage(BARNACLE_LARGE_TAB_TITLE, largeBarnacles); + resultPanel.loadImage(BARNACLE_SMALL_TAB_TITLE, smallBarnacles); + } + + @Override + public void updateToolsSegmentation(Image tools) { + resultPanel.loadImage(TOOLS_TAB_TITLE, tools); + } + + @Override + public void updateSpacecraftExtraction(Image synthesis, Image synthesis2) { + resultPanel.loadImage(SPACECRAFT_TAB_TITLE, synthesis); + resultPanel.loadImage(SPACECRAFT_CONTOUR_TAB_TITLE, synthesis2); + } + + @Override + public void updateToastContours(Image result) { + resultPanel.loadImage(TOAST_TAB_TITLE, result); + } + + @Override + public void disposeCore() { + presenter.setView(null); + presenter.dispose(); + } +} \ No newline at end of file