Update architecture
This commit is contained in:
@@ -5,14 +5,14 @@ import app.state.DoubleMatrixState;
|
|||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
import presenters.DoubleMatrixPresenter;
|
import presenters.doubleMatrix.DoubleMatrixPresenter;
|
||||||
import presenters.FilteringPresenter;
|
import presenters.filtering.FilteringPresenter;
|
||||||
import presenters.MainPresenter;
|
import presenters.MainPresenter;
|
||||||
import presenters.NavPresenter;
|
import presenters.NavPresenter;
|
||||||
import services.ImageService;
|
import services.ImageService;
|
||||||
import ui.implementation.components.nav.NavBar;
|
import ui.implementation.components.nav.NavBar;
|
||||||
import ui.implementation.views.DoubleMatrix;
|
import ui.implementation.views.DoubleMatrix;
|
||||||
import ui.implementation.views.FilteringView;
|
import ui.implementation.views.IdealFilteringView;
|
||||||
import ui.implementation.views.MainView;
|
import ui.implementation.views.MainView;
|
||||||
import ui.abstractions.IDoubleMatrix;
|
import ui.abstractions.IDoubleMatrix;
|
||||||
import ui.abstractions.IFilteringView;
|
import ui.abstractions.IFilteringView;
|
||||||
@@ -40,7 +40,7 @@ public class AppModule extends AbstractModule {
|
|||||||
bind(INavBar.class).to(NavBar.class);
|
bind(INavBar.class).to(NavBar.class);
|
||||||
bind(IMainView.class).to(MainView.class);
|
bind(IMainView.class).to(MainView.class);
|
||||||
bind(IDoubleMatrix.class).to(DoubleMatrix.class);
|
bind(IDoubleMatrix.class).to(DoubleMatrix.class);
|
||||||
bind(IFilteringView.class).to(FilteringView.class);
|
bind(IFilteringView.class).to(IdealFilteringView.class);
|
||||||
|
|
||||||
//--- Presentation layer ---
|
//--- Presentation layer ---
|
||||||
bind(MainPresenter.class);
|
bind(MainPresenter.class);
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ package app;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import ui.implementation.views.DoubleMatrix;
|
import ui.implementation.views.DoubleMatrix;
|
||||||
import ui.implementation.views.FilteringView;
|
import ui.implementation.views.IdealFilteringView;
|
||||||
import ui.implementation.views.ViewInitializer;
|
import ui.implementation.views.ViewInitializer;
|
||||||
|
|
||||||
import javax.swing.text.View;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implement of the INavigator interface.
|
* Concrete implement of the INavigator interface.
|
||||||
* Implements abstract endpoints to displays views in a Swing way
|
* Implements abstract endpoints to displays views in a Swing way
|
||||||
@@ -16,12 +14,12 @@ import javax.swing.text.View;
|
|||||||
public class SwingNavigator implements INavigator {
|
public class SwingNavigator implements INavigator {
|
||||||
|
|
||||||
private final Provider<DoubleMatrix> doubleMatrixProvider;
|
private final Provider<DoubleMatrix> doubleMatrixProvider;
|
||||||
private final Provider<FilteringView> filteringProvider;
|
private final Provider<IdealFilteringView> filteringProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SwingNavigator(
|
public SwingNavigator(
|
||||||
Provider<DoubleMatrix> doubleMatrixProvider,
|
Provider<DoubleMatrix> doubleMatrixProvider,
|
||||||
Provider<FilteringView> filteringProvider
|
Provider<IdealFilteringView> filteringProvider
|
||||||
) {
|
) {
|
||||||
this.doubleMatrixProvider = doubleMatrixProvider;
|
this.doubleMatrixProvider = doubleMatrixProvider;
|
||||||
this.filteringProvider = filteringProvider;
|
this.filteringProvider = filteringProvider;
|
||||||
@@ -36,7 +34,7 @@ public class SwingNavigator implements INavigator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showFiltering() {
|
public void showFiltering() {
|
||||||
FilteringView filteringView = filteringProvider.get();
|
IdealFilteringView filteringView = filteringProvider.get();
|
||||||
ViewInitializer.Initialize(filteringView);
|
ViewInitializer.Initialize(filteringView);
|
||||||
filteringView.setVisible(true);
|
filteringView.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,35 +6,47 @@ import com.google.inject.Singleton;
|
|||||||
import domain.common.Mode;
|
import domain.common.Mode;
|
||||||
import domain.events.ImageChangedEvent;
|
import domain.events.ImageChangedEvent;
|
||||||
import domain.events.ModeChangedEvent;
|
import domain.events.ModeChangedEvent;
|
||||||
|
import domain.events.listeners.Listener;
|
||||||
import domain.image.Image;
|
import domain.image.Image;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the global state of the app
|
* Represents the global state of the app
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AppState extends State {
|
public class AppState extends State {
|
||||||
|
|
||||||
private Mode mode;
|
private Mode mode;
|
||||||
private Image rgbImage;
|
private Image rgbImage;
|
||||||
|
private final List<AppStateListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AppState(EventBus eventBus) {
|
public AppState() {}
|
||||||
super(eventBus);
|
|
||||||
|
public void subscribe(AppStateListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsubscribe(AppStateListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMode(Mode mode) {
|
public void setMode(Mode mode) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
this.eventBus.post(new ModeChangedEvent(mode));
|
listeners.forEach(listener -> listener.onModeChanged(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImage(Image image) {
|
public void setImage(Image image) {
|
||||||
this.rgbImage = image;
|
this.rgbImage = image;
|
||||||
this.eventBus.post(new ImageChangedEvent(image));
|
listeners.forEach(listener -> listener.onImageChanged(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image getImage(){
|
public Image getImage() {
|
||||||
return this.rgbImage;
|
return rgbImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mode getMode() { return this.mode; }
|
public Mode getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/main/java/app/state/AppStateListener.java
Normal file
9
src/main/java/app/state/AppStateListener.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package app.state;
|
||||||
|
|
||||||
|
import domain.common.Mode;
|
||||||
|
import domain.image.Image;
|
||||||
|
|
||||||
|
public interface AppStateListener {
|
||||||
|
void onModeChanged(Mode mode);
|
||||||
|
void onImageChanged(Image image);
|
||||||
|
}
|
||||||
@@ -1,22 +1,32 @@
|
|||||||
package app.state;
|
package app.state;
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
|
||||||
import domain.events.fourier.*;
|
|
||||||
import domain.image.GrayScaleMatrix;
|
import domain.image.GrayScaleMatrix;
|
||||||
import domain.image.processing.complex.ComplexMatrix;
|
import domain.image.processing.complex.ComplexMatrix;
|
||||||
|
import presenters.doubleMatrix.DoubleMatrixListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class DoubleMatrixState extends State {
|
public class DoubleMatrixState extends State {
|
||||||
|
|
||||||
private ComplexMatrix fourier;
|
private ComplexMatrix fourier;
|
||||||
private GrayScaleMatrix module;
|
private GrayScaleMatrix module;
|
||||||
private GrayScaleMatrix phase;
|
private GrayScaleMatrix phase;
|
||||||
private GrayScaleMatrix real;
|
private GrayScaleMatrix real;
|
||||||
private GrayScaleMatrix imaginary;
|
private GrayScaleMatrix imaginary;
|
||||||
|
|
||||||
|
private final List<DoubleMatrixListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DoubleMatrixState() { super(new EventBus()); }
|
public DoubleMatrixState() {}
|
||||||
|
|
||||||
|
public void subscribe(DoubleMatrixListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsubscribe(DoubleMatrixListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public ComplexMatrix getFourier() {
|
public ComplexMatrix getFourier() {
|
||||||
return fourier;
|
return fourier;
|
||||||
@@ -24,26 +34,42 @@ public class DoubleMatrixState extends State {
|
|||||||
|
|
||||||
public void setFourier(ComplexMatrix fourier) {
|
public void setFourier(ComplexMatrix fourier) {
|
||||||
this.fourier = fourier;
|
this.fourier = fourier;
|
||||||
this.eventBus.post(new ComplexMatrixChanged(fourier));
|
listeners.forEach(listener -> listener.onFourierChanged(fourier));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setModule(GrayScaleMatrix matrix) {
|
public void setModule(GrayScaleMatrix matrix) {
|
||||||
this.module = matrix;
|
this.module = matrix;
|
||||||
this.eventBus.post(new ModuleChangedEvent(matrix));
|
listeners.forEach(listener -> listener.onModuleChanged(matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPhase(GrayScaleMatrix matrix) {
|
public void setPhase(GrayScaleMatrix matrix) {
|
||||||
this.phase = matrix;
|
this.phase = matrix;
|
||||||
this.eventBus.post(new PhaseChangedEvent(matrix));
|
listeners.forEach(listener -> listener.onPhaseChanged(matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReal(GrayScaleMatrix matrix) {
|
public void setReal(GrayScaleMatrix matrix) {
|
||||||
this.real = matrix;
|
this.real = matrix;
|
||||||
this.eventBus.post(new RealChangedEvent(matrix));
|
listeners.forEach(listener -> listener.onRealChanged(matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImaginary(GrayScaleMatrix matrix) {
|
public void setImaginary(GrayScaleMatrix matrix) {
|
||||||
this.imaginary = matrix;
|
this.imaginary = matrix;
|
||||||
this.eventBus.post(new ImaginaryChangedEvent(matrix));
|
listeners.forEach(listener -> listener.onImaginaryChanged(matrix));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrayScaleMatrix getModule() {
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrayScaleMatrix getPhase() {
|
||||||
|
return phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrayScaleMatrix getReal() {
|
||||||
|
return real;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrayScaleMatrix getImaginary() {
|
||||||
|
return imaginary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,64 @@
|
|||||||
package app.state;
|
package app.state;
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import domain.events.filtering.HighPassChangedEvent;
|
|
||||||
import domain.events.filtering.LowPassChangedEvent;
|
|
||||||
import domain.events.fourier.ModuleChangedEvent;
|
|
||||||
import domain.image.GrayScaleMatrix;
|
|
||||||
import domain.image.Image;
|
import domain.image.Image;
|
||||||
|
import presenters.filtering.FilteringListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class FilteringState extends State {
|
public class FilteringState extends State {
|
||||||
|
|
||||||
private Image lowPass;
|
private Image lowPass;
|
||||||
private Image highPass;
|
private Image highPass;
|
||||||
|
private Image butterworthLowPass;
|
||||||
|
private Image butterworthHighPass;
|
||||||
|
|
||||||
|
private final List<FilteringListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FilteringState() { super(new EventBus()); }
|
public FilteringState() {}
|
||||||
|
|
||||||
|
public void subscribe(FilteringListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsubscribe(FilteringListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void setLowPass(Image image) {
|
public void setLowPass(Image image) {
|
||||||
this.eventBus.post(new LowPassChangedEvent(image));
|
lowPass = image;
|
||||||
|
listeners.forEach(listener -> listener.onLowPassChanged(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHighPass(Image image) {
|
public void setHighPass(Image image) {
|
||||||
this.eventBus.post(new HighPassChangedEvent(image));
|
highPass = image;
|
||||||
|
listeners.forEach(listener -> listener.onHighPassChanged(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public void setButterworthLowPass(Image image) {
|
||||||
|
butterworthLowPass = image;
|
||||||
|
listeners.forEach(listener -> listener.onButterworthLowPassChanged(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButterworthHighPass(Image image) {
|
||||||
|
butterworthHighPass = image;
|
||||||
|
listeners.forEach(listener -> listener.onButterworthHighPassChanged(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getLowPass() {
|
||||||
|
return lowPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getHighPass() {
|
||||||
|
return highPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getButterworthLowPass() {
|
||||||
|
return butterworthLowPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getButterworthHighPass() {
|
||||||
|
return butterworthHighPass;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@ package app.state;
|
|||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents any states that could ever exist.
|
* Represents any states that could ever exist.
|
||||||
* In order to notify the caller about any change made to internal properties of a children state, the caller
|
* In order to notify the caller about any change made to internal properties of a children state, the caller
|
||||||
@@ -9,18 +13,4 @@ import com.google.common.eventbus.EventBus;
|
|||||||
* @author Laurent Crema
|
* @author Laurent Crema
|
||||||
*/
|
*/
|
||||||
public abstract class State {
|
public abstract class State {
|
||||||
|
}
|
||||||
protected EventBus eventBus;
|
|
||||||
|
|
||||||
public State(EventBus eventBus) {
|
|
||||||
this.eventBus = eventBus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the caller so it can be notifed from changes within the state
|
|
||||||
* @param obj the caller itself
|
|
||||||
*/
|
|
||||||
public void register(Object obj) {
|
|
||||||
eventBus.register(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package domain.events.filtering;
|
|
||||||
|
|
||||||
import domain.image.Image;
|
|
||||||
|
|
||||||
public record HighPassChangedEvent(Image image) { }
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package domain.events.filtering;
|
|
||||||
|
|
||||||
import domain.image.Image;
|
|
||||||
|
|
||||||
public record LowPassChangedEvent(Image image) { }
|
|
||||||
5
src/main/java/domain/events/listeners/Listener.java
Normal file
5
src/main/java/domain/events/listeners/Listener.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package domain.events.listeners;
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,136 +13,96 @@ import java.util.List;
|
|||||||
public class GlobalLinearFiltering {
|
public class GlobalLinearFiltering {
|
||||||
|
|
||||||
public static GrayScaleMatrix lowPassFiltering(GrayScaleMatrix matrix, double cutoff) {
|
public static GrayScaleMatrix lowPassFiltering(GrayScaleMatrix matrix, double cutoff) {
|
||||||
|
|
||||||
int width = matrix.getWidth();
|
int width = matrix.getWidth();
|
||||||
int height = matrix.getHeight();
|
int height = matrix.getHeight();
|
||||||
|
|
||||||
double minCutoff = 0;
|
validateCutoff(cutoff, width, height);
|
||||||
double maxCutoff = Math.sqrt(Math.pow(width / 2.0, 2) + Math.pow(height / 2.0, 2));
|
|
||||||
|
|
||||||
if(cutoff < minCutoff || cutoff > maxCutoff){
|
Mat mat = toMat(matrix);
|
||||||
throw new IllegalArgumentException(
|
Mat spectrum = fourierTransform(mat);
|
||||||
String.format("Cutoff value is out of bond (%f - %f)", minCutoff, maxCutoff)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat mat = new Mat(height, width, CvType.CV_64F);
|
shiftSpectrum(spectrum);
|
||||||
|
applyIdealLowPassFilter(spectrum, cutoff);
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
|
||||||
double[][] data = matrix.getRawData();
|
Mat filtered = inverseFourierTransform(spectrum);
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
return toGrayScaleMatrix(filtered);
|
||||||
mat.put(y, 0, data[y]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Fourier transform
|
public static GrayScaleMatrix highPassFiltering(GrayScaleMatrix matrix, double cutoff) {
|
||||||
Mat spectrum = new Mat();
|
int width = matrix.getWidth();
|
||||||
Core.dft(mat, spectrum, Core.DFT_COMPLEX_OUTPUT);
|
int height = matrix.getHeight();
|
||||||
|
|
||||||
|
validateCutoff(cutoff, width, height);
|
||||||
|
|
||||||
|
Mat mat = toMat(matrix);
|
||||||
|
Mat spectrum = fourierTransform(mat);
|
||||||
|
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
applyIdealHighPassFilter(spectrum, cutoff);
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
|
||||||
|
Mat filtered = inverseFourierTransform(spectrum);
|
||||||
|
|
||||||
|
return toGrayScaleMatrix(filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GrayScaleMatrix butterworthLowPassFiltering(GrayScaleMatrix matrix, double cutoff, int order) {
|
||||||
|
validateCutoff(cutoff, matrix.getWidth(), matrix.getHeight());
|
||||||
|
|
||||||
|
Mat spectrum = fourierTransform(toMat(matrix));
|
||||||
|
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
applyButterworthLowPassFilter(spectrum, cutoff, order);
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
|
||||||
|
return toGrayScaleMatrix(inverseFourierTransform(spectrum));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GrayScaleMatrix butterworthHighPassFiltering(GrayScaleMatrix matrix, double cutoff, int order) {
|
||||||
|
validateCutoff(cutoff, matrix.getWidth(), matrix.getHeight());
|
||||||
|
|
||||||
|
Mat spectrum = fourierTransform(toMat(matrix));
|
||||||
|
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
applyButterworthHighPassFilter(spectrum, cutoff, order);
|
||||||
|
shiftSpectrum(spectrum);
|
||||||
|
|
||||||
|
return toGrayScaleMatrix(inverseFourierTransform(spectrum));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyIdealLowPassFilter(Mat spectrum, double cutoff) {
|
||||||
|
int width = spectrum.cols();
|
||||||
|
int height = spectrum.rows();
|
||||||
|
|
||||||
// Shift zero frequency to the center
|
|
||||||
int cx = width / 2;
|
int cx = width / 2;
|
||||||
int cy = height / 2;
|
int cy = height / 2;
|
||||||
|
|
||||||
Mat q0 = spectrum.submat(0, cy, 0, cx);
|
|
||||||
Mat q1 = spectrum.submat(0, cy, cx, width);
|
|
||||||
Mat q2 = spectrum.submat(cy, height, 0, cx);
|
|
||||||
Mat q3 = spectrum.submat(cy, height, cx, width);
|
|
||||||
|
|
||||||
Mat tmp = new Mat();
|
|
||||||
|
|
||||||
q0.copyTo(tmp);
|
|
||||||
q3.copyTo(q0);
|
|
||||||
tmp.copyTo(q3);
|
|
||||||
|
|
||||||
q1.copyTo(tmp);
|
|
||||||
q2.copyTo(q1);
|
|
||||||
tmp.copyTo(q2);
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
double distance = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2));
|
|
||||||
|
double distance = Math.sqrt(
|
||||||
|
Math.pow(x - cx, 2) + Math.pow(y - cy, 2)
|
||||||
|
);
|
||||||
|
|
||||||
if (distance > cutoff) {
|
if (distance > cutoff) {
|
||||||
spectrum.put(y, x, 0, 0);
|
spectrum.put(y, x, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift back
|
|
||||||
q0.copyTo(tmp);
|
|
||||||
q3.copyTo(q0);
|
|
||||||
tmp.copyTo(q3);
|
|
||||||
|
|
||||||
q1.copyTo(tmp);
|
|
||||||
q2.copyTo(q1);
|
|
||||||
tmp.copyTo(q2);
|
|
||||||
|
|
||||||
// Inverse Fourier transform
|
|
||||||
Mat filtered = new Mat();
|
|
||||||
|
|
||||||
Core.idft(
|
|
||||||
spectrum,
|
|
||||||
filtered,
|
|
||||||
Core.DFT_REAL_OUTPUT | Core.DFT_SCALE
|
|
||||||
);
|
|
||||||
|
|
||||||
// Convert result back to your Image
|
|
||||||
double[][] pixels = new double[height][width];
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
pixels[y][x] = Math.clamp(filtered.get(y, x)[0], 0.0, 255.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GrayScaleMatrix(pixels);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GrayScaleMatrix highPassFiltering(GrayScaleMatrix matrix, double cutoff){
|
private static void applyIdealHighPassFilter(Mat spectrum, double cutoff) {
|
||||||
int width = matrix.getWidth();
|
int width = spectrum.cols();
|
||||||
int height = matrix.getHeight();
|
int height = spectrum.rows();
|
||||||
|
|
||||||
double minCutoff = 0;
|
|
||||||
double maxCutoff = Math.sqrt(Math.pow(width / 2.0, 2) + Math.pow(height / 2.0, 2));
|
|
||||||
|
|
||||||
if(cutoff < minCutoff || cutoff > maxCutoff){
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String.format("Cutoff value is out of bond (%f - %f)", minCutoff, maxCutoff)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat mat = new Mat(height, width, CvType.CV_64F);
|
|
||||||
|
|
||||||
double[][] data = matrix.getRawData();
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
mat.put(y, 0, data[y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fourier transform
|
|
||||||
Mat spectrum = new Mat();
|
|
||||||
Core.dft(mat, spectrum, Core.DFT_COMPLEX_OUTPUT);
|
|
||||||
|
|
||||||
// Shift zero frequency to the center
|
|
||||||
int cx = width / 2;
|
int cx = width / 2;
|
||||||
int cy = height / 2;
|
int cy = height / 2;
|
||||||
|
|
||||||
Mat q0 = spectrum.submat(0, cy, 0, cx);
|
|
||||||
Mat q1 = spectrum.submat(0, cy, cx, width);
|
|
||||||
Mat q2 = spectrum.submat(cy, height, 0, cx);
|
|
||||||
Mat q3 = spectrum.submat(cy, height, cx, width);
|
|
||||||
|
|
||||||
Mat tmp = new Mat();
|
|
||||||
|
|
||||||
q0.copyTo(tmp);
|
|
||||||
q3.copyTo(q0);
|
|
||||||
tmp.copyTo(q3);
|
|
||||||
|
|
||||||
q1.copyTo(tmp);
|
|
||||||
q2.copyTo(q1);
|
|
||||||
tmp.copyTo(q2);
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
|
|
||||||
double distance = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2));
|
double distance = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2));
|
||||||
|
|
||||||
if (distance <= cutoff) {
|
if (distance <= cutoff) {
|
||||||
@@ -150,8 +110,94 @@ public class GlobalLinearFiltering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyButterworthLowPassFilter(Mat spectrum, double cutoff, int order) {
|
||||||
|
int width = spectrum.cols();
|
||||||
|
int height = spectrum.rows();
|
||||||
|
|
||||||
|
int cx = width / 2;
|
||||||
|
int cy = height / 2;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
|
||||||
|
double distance = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2) );
|
||||||
|
|
||||||
|
double coefficient = 1.0 / (1.0 + Math.pow(distance / cutoff, 2 * order));
|
||||||
|
|
||||||
|
double[] value = spectrum.get(y, x);
|
||||||
|
|
||||||
|
spectrum.put(y, x, value[0] * coefficient, value[1] * coefficient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyButterworthHighPassFilter(Mat spectrum, double cutoff, int order) {
|
||||||
|
int width = spectrum.cols();
|
||||||
|
int height = spectrum.rows();
|
||||||
|
|
||||||
|
int cx = width / 2;
|
||||||
|
int cy = height / 2;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
|
||||||
|
double distance = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2));
|
||||||
|
|
||||||
|
double coefficient;
|
||||||
|
|
||||||
|
if (distance == 0) {
|
||||||
|
coefficient = 0;
|
||||||
|
} else {
|
||||||
|
coefficient = 1.0 / (1.0 + Math.pow(cutoff / distance, 2 * order));
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] value = spectrum.get(y, x);
|
||||||
|
|
||||||
|
spectrum.put(y, x, value[0] * coefficient, value[1] * coefficient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateCutoff(double cutoff, int width, int height) {
|
||||||
|
double minCutoff = 0;
|
||||||
|
double maxCutoff = Math.sqrt(
|
||||||
|
Math.pow(width / 2.0, 2) +
|
||||||
|
Math.pow(height / 2.0, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (cutoff < minCutoff || cutoff > maxCutoff) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"Cutoff value is out of bounds (%f - %f)",
|
||||||
|
minCutoff,
|
||||||
|
maxCutoff
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Mat fourierTransform(Mat mat) {
|
||||||
|
Mat spectrum = new Mat();
|
||||||
|
Core.dft(mat, spectrum, Core.DFT_COMPLEX_OUTPUT);
|
||||||
|
return spectrum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void shiftSpectrum(Mat spectrum) {
|
||||||
|
int width = spectrum.cols();
|
||||||
|
int height = spectrum.rows();
|
||||||
|
|
||||||
|
int cx = width / 2;
|
||||||
|
int cy = height / 2;
|
||||||
|
|
||||||
|
Mat q0 = spectrum.submat(0, cy, 0, cx);
|
||||||
|
Mat q1 = spectrum.submat(0, cy, cx, width);
|
||||||
|
Mat q2 = spectrum.submat(cy, height, 0, cx);
|
||||||
|
Mat q3 = spectrum.submat(cy, height, cx, width);
|
||||||
|
|
||||||
|
Mat tmp = new Mat();
|
||||||
|
|
||||||
// Shift back
|
|
||||||
q0.copyTo(tmp);
|
q0.copyTo(tmp);
|
||||||
q3.copyTo(q0);
|
q3.copyTo(q0);
|
||||||
tmp.copyTo(q3);
|
tmp.copyTo(q3);
|
||||||
@@ -159,8 +205,9 @@ public class GlobalLinearFiltering {
|
|||||||
q1.copyTo(tmp);
|
q1.copyTo(tmp);
|
||||||
q2.copyTo(q1);
|
q2.copyTo(q1);
|
||||||
tmp.copyTo(q2);
|
tmp.copyTo(q2);
|
||||||
|
}
|
||||||
|
|
||||||
// Inverse Fourier transform
|
private static Mat inverseFourierTransform(Mat spectrum) {
|
||||||
Mat filtered = new Mat();
|
Mat filtered = new Mat();
|
||||||
|
|
||||||
Core.idft(
|
Core.idft(
|
||||||
@@ -169,23 +216,41 @@ public class GlobalLinearFiltering {
|
|||||||
Core.DFT_REAL_OUTPUT | Core.DFT_SCALE
|
Core.DFT_REAL_OUTPUT | Core.DFT_SCALE
|
||||||
);
|
);
|
||||||
|
|
||||||
// Convert result back to your Image
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GrayScaleMatrix toGrayScaleMatrix(Mat filtered) {
|
||||||
|
int width = filtered.cols();
|
||||||
|
int height = filtered.rows();
|
||||||
|
|
||||||
double[][] pixels = new double[height][width];
|
double[][] pixels = new double[height][width];
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
pixels[y][x] = Math.clamp(filtered.get(y, x)[0], 0.0, 255.0);
|
pixels[y][x] = Math.clamp(
|
||||||
|
filtered.get(y, x)[0],
|
||||||
|
0.0,
|
||||||
|
255.0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GrayScaleMatrix(pixels);
|
return new GrayScaleMatrix(pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void butterworthLowPassFiltering(){
|
private static Mat toMat(GrayScaleMatrix matrix) {
|
||||||
|
int width = matrix.getWidth();
|
||||||
|
int height = matrix.getHeight();
|
||||||
|
|
||||||
|
Mat mat = new Mat(height, width, CvType.CV_64F);
|
||||||
|
|
||||||
|
double[][] data = matrix.getRawData();
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
mat.put(y, 0, data[y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void butterworthHighPassFiltering(){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
package presenters;
|
|
||||||
|
|
||||||
import app.state.FilteringState;
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import domain.events.filtering.HighPassChangedEvent;
|
|
||||||
import domain.events.filtering.LowPassChangedEvent;
|
|
||||||
import domain.image.GrayScaleMatrix;
|
|
||||||
import domain.image.Image;
|
|
||||||
import services.FilteringService;
|
|
||||||
import services.ImageService;
|
|
||||||
import ui.abstractions.IFilteringView;
|
|
||||||
|
|
||||||
public class FilteringPresenter {
|
|
||||||
|
|
||||||
private final FilteringState state;
|
|
||||||
private final ImageService imageService;
|
|
||||||
private final FilteringService filteringService;
|
|
||||||
private IFilteringView view;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public FilteringPresenter(FilteringState state, ImageService imageService, FilteringService filteringService) {
|
|
||||||
this.state = state;
|
|
||||||
this.state.register(this);
|
|
||||||
|
|
||||||
this.imageService = imageService;
|
|
||||||
this.filteringService = filteringService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setView(IFilteringView view){
|
|
||||||
this.view = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void computeLowPassFiltering(int percentage){
|
|
||||||
GrayScaleMatrix matrix = imageService.getGrayScale();
|
|
||||||
Image image = filteringService.lowPassFiltering(matrix, (double) percentage /100);
|
|
||||||
this.state.setLowPass(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void computeHighPassFiltering(int percentage){
|
|
||||||
GrayScaleMatrix matrix = imageService.getGrayScale();
|
|
||||||
Image image = filteringService.highPassFiltering(matrix, (double) percentage /100);
|
|
||||||
this.state.setHighPass(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onLowPassUpdate(LowPassChangedEvent event){
|
|
||||||
view.updateLowPassFiltering(event.image());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onHighPassUpdate(HighPassChangedEvent event){
|
|
||||||
view.updateHighPassFiltering(event.image());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +1,63 @@
|
|||||||
package presenters;
|
package presenters;
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import app.state.AppState;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import app.state.AppStateListener;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import domain.common.Mode;
|
import domain.common.Mode;
|
||||||
import domain.events.ImageChangedEvent;
|
|
||||||
import domain.events.ModeChangedEvent;
|
|
||||||
import domain.image.Image;
|
import domain.image.Image;
|
||||||
import services.ImageService;
|
import services.ImageService;
|
||||||
import services.ModeService;
|
import services.ModeService;
|
||||||
import ui.abstractions.IMainView;
|
import ui.abstractions.IMainView;
|
||||||
|
|
||||||
/**
|
public class MainPresenter implements AppStateListener {
|
||||||
* @author Laurent Crema
|
|
||||||
*/
|
|
||||||
public class MainPresenter {
|
|
||||||
|
|
||||||
private IMainView view;
|
private IMainView view;
|
||||||
|
private final AppState appState;
|
||||||
private final ModeService modeService;
|
private final ModeService modeService;
|
||||||
private final ImageService imageService;
|
private final ImageService imageService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MainPresenter(ModeService modeService, ImageService imageService, EventBus eventBus) {
|
public MainPresenter(AppState appState, ModeService modeService, ImageService imageService) {
|
||||||
|
this.appState = appState;
|
||||||
this.modeService = modeService;
|
this.modeService = modeService;
|
||||||
this.imageService = imageService;
|
this.imageService = imageService;
|
||||||
eventBus.register(this);
|
this.appState.subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setView(IMainView view) {
|
public void setView(IMainView view) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Override
|
||||||
public void onImageChanged(ImageChangedEvent e){
|
public void onImageChanged(Image image) {
|
||||||
view.displayImage(e.image());
|
view.displayImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Override
|
||||||
public void onModeChanged(ModeChangedEvent e){
|
public void onModeChanged(Mode mode) {
|
||||||
view.changeMode(e.mode());
|
view.changeMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawPixel(int x, int y, int red, int green, int blue){
|
public void drawPixel(int x, int y, int red, int green, int blue) {
|
||||||
if(modeService.getMode() != Mode.DRAW_PIXEL) return;
|
if (modeService.getMode() != Mode.DRAW_PIXEL) return;
|
||||||
Image image = imageService.getImage();
|
|
||||||
|
Image image = appState.getImage();
|
||||||
image.setPixelColor(x, y, red, green, blue);
|
image.setPixelColor(x, y, red, green, blue);
|
||||||
imageService.setImage(image);
|
appState.setImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawShape(int x1, int x2, int y1, int y2, int red, int green, int blue){
|
public void drawShape(int x1, int x2, int y1, int y2, int red, int green, int blue) {
|
||||||
Image image = imageService.getImage();
|
Image image = appState.getImage();
|
||||||
|
|
||||||
switch (modeService.getMode()) {
|
switch (modeService.getMode()) {
|
||||||
case DRAW_RECTANGLE:
|
case DRAW_RECTANGLE -> image.setRectangleColor(x1, x2, y1, y2, red, green, blue);
|
||||||
image.setRectangleColor(x1, x2, y1, y2, red, green, blue);
|
case DRAW_LINE -> image.setLineColor(x1, x2, y1, y2, red, green, blue);
|
||||||
break;
|
case DRAW_CIRCLE -> {}
|
||||||
case DRAW_LINE:
|
|
||||||
image.setLineColor(x1, x2, y1, y2, red, green, blue);
|
|
||||||
break;
|
|
||||||
case DRAW_CIRCLE:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
imageService.setImage(image);
|
|
||||||
|
appState.setImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
}
|
appState.unsubscribe(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package presenters;
|
package presenters;
|
||||||
|
|
||||||
import app.INavigator;
|
import app.INavigator;
|
||||||
|
import app.state.AppState;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import domain.common.Mode;
|
import domain.common.Mode;
|
||||||
import domain.image.GrayScaleMatrix;
|
import domain.image.GrayScaleMatrix;
|
||||||
|
import domain.image.Image;
|
||||||
import services.ImageService;
|
import services.ImageService;
|
||||||
import services.ModeService;
|
import services.ModeService;
|
||||||
import ui.abstractions.INavBar;
|
import ui.abstractions.INavBar;
|
||||||
@@ -11,19 +13,17 @@ import ui.abstractions.INavBar;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Laurent Crema
|
|
||||||
*/
|
|
||||||
public class NavPresenter {
|
public class NavPresenter {
|
||||||
|
|
||||||
private INavBar navBar;
|
private INavBar navBar;
|
||||||
private INavigator navigator;
|
private final INavigator navigator;
|
||||||
|
private final AppState appState;
|
||||||
private final ImageService imageService;
|
private final ImageService imageService;
|
||||||
private final ModeService modeService;
|
private final ModeService modeService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NavPresenter(INavigator navigator, ImageService imageService, ModeService modeService) {
|
public NavPresenter(INavigator navigator, AppState appState, ImageService imageService, ModeService modeService) {
|
||||||
this.navigator = navigator;
|
this.navigator = navigator;
|
||||||
|
this.appState = appState;
|
||||||
this.imageService = imageService;
|
this.imageService = imageService;
|
||||||
this.modeService = modeService;
|
this.modeService = modeService;
|
||||||
}
|
}
|
||||||
@@ -33,27 +33,28 @@ public class NavPresenter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void createImage(int red, int green, int blue, int height, int width) {
|
public void createImage(int red, int green, int blue, int height, int width) {
|
||||||
imageService.createImage(red, green, blue, height, width);
|
Image image = imageService.createImage(red, green, blue, height, width);
|
||||||
|
appState.setImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadImage(File f) throws IOException {
|
public void loadImage(File file) throws IOException {
|
||||||
imageService.loadImage(f);
|
Image image = imageService.loadImage(file);
|
||||||
|
appState.setImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goToFourier(){
|
public void goToFourier() {
|
||||||
navigator.showFourier();
|
navigator.showFourier();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goToFiltering(){
|
public void goToFiltering() {
|
||||||
navigator.showFiltering();
|
navigator.showFiltering();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GrayScaleMatrix getImageGrayMatrix() {
|
public GrayScaleMatrix getImageGrayMatrix() {
|
||||||
//return ((CImageNG)appState.getImage()).getMatrice();
|
return appState.getImage().toGrayScale();
|
||||||
return imageService.getImage().toGrayScale();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMode(Mode mode) {
|
public void setMode(Mode mode) {
|
||||||
modeService.setMode(mode);
|
modeService.setMode(mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package presenters.doubleMatrix;
|
||||||
|
|
||||||
|
import domain.image.GrayScaleMatrix;
|
||||||
|
import domain.image.processing.complex.ComplexMatrix;
|
||||||
|
|
||||||
|
public interface DoubleMatrixListener {
|
||||||
|
void onFourierChanged(ComplexMatrix fourier);
|
||||||
|
void onModuleChanged(GrayScaleMatrix matrix);
|
||||||
|
void onPhaseChanged(GrayScaleMatrix matrix);
|
||||||
|
void onRealChanged(GrayScaleMatrix matrix);
|
||||||
|
void onImaginaryChanged(GrayScaleMatrix matrix);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package presenters;
|
package presenters.doubleMatrix;
|
||||||
|
|
||||||
|
import app.state.AppState;
|
||||||
import app.state.DoubleMatrixState;
|
import app.state.DoubleMatrixState;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -18,25 +19,26 @@ import java.io.IOException;
|
|||||||
/**
|
/**
|
||||||
* @author Laurent Crema
|
* @author Laurent Crema
|
||||||
*/
|
*/
|
||||||
public class DoubleMatrixPresenter {
|
public class DoubleMatrixPresenter implements DoubleMatrixListener {
|
||||||
|
|
||||||
private IDoubleMatrix view;
|
private IDoubleMatrix view;
|
||||||
|
private final AppState appState;
|
||||||
private final DoubleMatrixState state;
|
private final DoubleMatrixState state;
|
||||||
private final ImageService imageService;
|
private final ImageService imageService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DoubleMatrixPresenter(ImageService imageService, DoubleMatrixState state) {
|
public DoubleMatrixPresenter(AppState appState, ImageService imageService, DoubleMatrixState state) {
|
||||||
|
this.appState = appState;
|
||||||
this.imageService = imageService;
|
this.imageService = imageService;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.state.register(this);
|
this.state.subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setView(IDoubleMatrix view){
|
public void setView(IDoubleMatrix view) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveImage(Image image) throws IOException {
|
public void saveImage(Image image) throws IOException {
|
||||||
this.imageService.saveImage(image);
|
imageService.saveImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadModule(){
|
public void loadModule(){
|
||||||
@@ -87,28 +89,32 @@ public class DoubleMatrixPresenter {
|
|||||||
state.setImaginary(matrix);
|
state.setImaginary(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Override
|
||||||
public void onModuleUpdate(ModuleChangedEvent event) {
|
public void onModuleChanged(GrayScaleMatrix matrix) {
|
||||||
GrayScaleMatrix module = new GrayScaleMatrix(getFourier().getModule());
|
GrayScaleMatrix module = new GrayScaleMatrix(getFourier().getModule());
|
||||||
view.updateModule(module, event.matrix());
|
view.updateModule(module, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Override
|
||||||
public void onPhaseUpdate(PhaseChangedEvent event) {
|
public void onPhaseChanged(GrayScaleMatrix matrix) {
|
||||||
GrayScaleMatrix phase = new GrayScaleMatrix(getFourier().getPhase());
|
GrayScaleMatrix phase = new GrayScaleMatrix(getFourier().getPhase());
|
||||||
view.updatePhase(phase, event.matrix());
|
view.updatePhase(phase, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Override
|
||||||
public void onRealUpdate(RealChangedEvent event) {
|
public void onRealChanged(GrayScaleMatrix matrix) {
|
||||||
GrayScaleMatrix real = new GrayScaleMatrix(getFourier().getPartieReelle());
|
GrayScaleMatrix real = new GrayScaleMatrix(getFourier().getPartieReelle());
|
||||||
view.updateReal(real, event.matrix());
|
view.updateReal(real, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Override
|
||||||
public void onImaginaryUpdate(ImaginaryChangedEvent event) {
|
public void onFourierChanged(ComplexMatrix fourier) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImaginaryChanged(GrayScaleMatrix matrix) {
|
||||||
GrayScaleMatrix imaginary = new GrayScaleMatrix(getFourier().getPartieImaginaire());
|
GrayScaleMatrix imaginary = new GrayScaleMatrix(getFourier().getPartieImaginaire());
|
||||||
view.updateImaginary(imaginary, event.matrix());
|
view.updateImaginary(imaginary, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GrayScaleMatrix clip(GrayScaleMatrix matrix, double black, double white){
|
private GrayScaleMatrix clip(GrayScaleMatrix matrix, double black, double white){
|
||||||
@@ -119,7 +125,7 @@ public class DoubleMatrixPresenter {
|
|||||||
|
|
||||||
private ComplexMatrix getFourier() {
|
private ComplexMatrix getFourier() {
|
||||||
if (state.getFourier() == null) {
|
if (state.getFourier() == null) {
|
||||||
state.setFourier(imageService.computeFourier());
|
state.setFourier(imageService.computeFourier(appState.getImage()));
|
||||||
}
|
}
|
||||||
return state.getFourier();
|
return state.getFourier();
|
||||||
}
|
}
|
||||||
11
src/main/java/presenters/filtering/FilteringListener.java
Normal file
11
src/main/java/presenters/filtering/FilteringListener.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package presenters.filtering;
|
||||||
|
|
||||||
|
import domain.events.listeners.Listener;
|
||||||
|
import domain.image.Image;
|
||||||
|
|
||||||
|
public interface FilteringListener extends Listener {
|
||||||
|
void onLowPassChanged(Image image);
|
||||||
|
void onHighPassChanged(Image image);
|
||||||
|
void onButterworthLowPassChanged(Image image);
|
||||||
|
void onButterworthHighPassChanged(Image image);
|
||||||
|
}
|
||||||
79
src/main/java/presenters/filtering/FilteringPresenter.java
Normal file
79
src/main/java/presenters/filtering/FilteringPresenter.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package presenters.filtering;
|
||||||
|
|
||||||
|
import app.state.AppState;
|
||||||
|
import app.state.FilteringState;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import domain.image.GrayScaleMatrix;
|
||||||
|
import domain.image.Image;
|
||||||
|
import services.FilteringService;
|
||||||
|
import services.ImageService;
|
||||||
|
import ui.abstractions.IFilteringView;
|
||||||
|
|
||||||
|
public class FilteringPresenter implements FilteringListener {
|
||||||
|
private final AppState appState;
|
||||||
|
private final FilteringState state;
|
||||||
|
private final ImageService imageService;
|
||||||
|
private final FilteringService filteringService;
|
||||||
|
private IFilteringView view;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public FilteringPresenter(AppState appState, FilteringState state, ImageService imageService, FilteringService filteringService) {
|
||||||
|
this.appState = appState;
|
||||||
|
this.state = state;
|
||||||
|
this.imageService = imageService;
|
||||||
|
this.filteringService = filteringService;
|
||||||
|
this.state.subscribe(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setView(IFilteringView view) {
|
||||||
|
this.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void computeLowPassFiltering(float percentage) {
|
||||||
|
GrayScaleMatrix matrix = imageService.getGrayScale(appState.getImage());
|
||||||
|
Image image = filteringService.lowPassFiltering(matrix, percentage / 100);
|
||||||
|
state.setLowPass(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void computeHighPassFiltering(float percentage) {
|
||||||
|
GrayScaleMatrix matrix = imageService.getGrayScale(appState.getImage());
|
||||||
|
Image image = filteringService.highPassFiltering(matrix, percentage / 100);
|
||||||
|
state.setHighPass(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void computeButterworthLowPassFiltering(float percentage) {
|
||||||
|
GrayScaleMatrix matrix = imageService.getGrayScale(appState.getImage());
|
||||||
|
Image image = filteringService.butterworthLowPassFiltering(matrix, percentage / 100);
|
||||||
|
state.setButterworthLowPass(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void computeButterworthHighPassFiltering(float percentage) {
|
||||||
|
GrayScaleMatrix matrix = imageService.getGrayScale(appState.getImage());
|
||||||
|
Image image = filteringService.butterworthHighPassFiltering(matrix, percentage / 100);
|
||||||
|
state.setButterworthHighPass(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLowPassChanged(Image image) {
|
||||||
|
view.updateLowPassFiltering(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHighPassChanged(Image image) {
|
||||||
|
view.updateHighPassFiltering(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onButterworthLowPassChanged(Image image) {
|
||||||
|
view.updateButterworthLowPassFiltering(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onButterworthHighPassChanged(Image image) {
|
||||||
|
view.updateButterworthHighPassFiltering(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
state.unsubscribe(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,4 +22,11 @@ public class FilteringService {
|
|||||||
return Math.sqrt(Math.pow(width / 2.0, 2) + Math.pow(height / 2.0, 2));
|
return Math.sqrt(Math.pow(width / 2.0, 2) + Math.pow(height / 2.0, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Image butterworthLowPassFiltering(GrayScaleMatrix matrix, float v) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image butterworthHighPassFiltering(GrayScaleMatrix matrix, float v) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package services;
|
package services;
|
||||||
|
|
||||||
import app.state.AppState;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import domain.image.Image;
|
|
||||||
import domain.image.GrayScaleMatrix;
|
import domain.image.GrayScaleMatrix;
|
||||||
|
import domain.image.Image;
|
||||||
import domain.image.processing.complex.ComplexMatrix;
|
import domain.image.processing.complex.ComplexMatrix;
|
||||||
import domain.image.processing.fourier.Fourier;
|
import domain.image.processing.fourier.Fourier;
|
||||||
import infrastructure.image.io.ImageLoader;
|
import infrastructure.image.io.ImageLoader;
|
||||||
@@ -17,42 +15,25 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class ImageService {
|
public class ImageService {
|
||||||
|
|
||||||
private final AppState appState;
|
public Image createImage(int red, int green, int blue, int height, int width) {
|
||||||
|
return new Image(red, green, blue, height, width);
|
||||||
@Inject
|
|
||||||
public ImageService(AppState appState) {
|
|
||||||
this.appState = appState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createImage(int red, int green, int blue, int height, int width) {
|
public Image loadImage(File file) throws IOException {
|
||||||
Image image = new Image(red, green, blue, height, width);
|
return ImageLoader.loadImage(file);
|
||||||
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 {
|
public void saveImage(Image image) throws IOException {
|
||||||
ImageSaver.saveImage(image);
|
ImageSaver.saveImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComplexMatrix computeFourier(){
|
public ComplexMatrix computeFourier(Image image) {
|
||||||
GrayScaleMatrix matrix = appState.getImage().toGrayScale();
|
GrayScaleMatrix matrix = image.toGrayScale();
|
||||||
ComplexMatrix fourier = Fourier.Fourier2D(matrix.getRawData());
|
ComplexMatrix fourier = Fourier.Fourier2D(matrix.getRawData());
|
||||||
return Fourier.decroise(fourier);
|
return Fourier.decroise(fourier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image getImage(){
|
public GrayScaleMatrix getGrayScale(Image image) {
|
||||||
return appState.getImage();
|
return image.toGrayScale();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void setImage(Image img){
|
|
||||||
appState.setImage(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GrayScaleMatrix getGrayScale(){
|
|
||||||
return appState.getImage().toGrayScale();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,4 +5,11 @@ import javax.swing.*;
|
|||||||
public abstract class AbstractView extends JFrame {
|
public abstract class AbstractView extends JFrame {
|
||||||
public abstract void initComponents();
|
public abstract void initComponents();
|
||||||
public abstract void initValues();
|
public abstract void initValues();
|
||||||
|
public abstract void disposeCore();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
disposeCore();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package ui.implementation.components.controls;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
public class IntensitySlider extends JSlider {
|
||||||
|
|
||||||
|
public IntensitySlider() {
|
||||||
|
super();
|
||||||
|
setMinimum(0);
|
||||||
|
setMaximum(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPercentage(){
|
||||||
|
return (float) getValue() /10;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ui.implementation.components.button;
|
package ui.implementation.components.controls;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package ui.implementation.components.image;
|
||||||
|
|
||||||
|
import domain.image.Image;
|
||||||
|
import infrastructure.ui.ImageMapper;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TabbedImagePanel extends JTabbedPane {
|
||||||
|
|
||||||
|
private final Map<String, ImagePanel> tabs;
|
||||||
|
|
||||||
|
public TabbedImagePanel() {
|
||||||
|
this.tabs = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPreviewTab(String title) {
|
||||||
|
ImagePanel panel = new ImagePanel();
|
||||||
|
tabs.put(title, panel);
|
||||||
|
addTab(title, panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadImage(String title, Image image) {
|
||||||
|
BufferedImage bufferedImage = ImageMapper.toBufferedImage(image);
|
||||||
|
tabs.get(title).loadImage(bufferedImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,9 @@ package ui.implementation.views;
|
|||||||
|
|
||||||
import domain.image.GrayScaleMatrix;
|
import domain.image.GrayScaleMatrix;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import presenters.DoubleMatrixPresenter;
|
import presenters.doubleMatrix.DoubleMatrixPresenter;
|
||||||
import ui.abstractions.AbstractView;
|
import ui.abstractions.AbstractView;
|
||||||
import ui.implementation.components.button.SaveButton;
|
import ui.implementation.components.controls.SaveButton;
|
||||||
import ui.implementation.components.image.ImagePanel;
|
import ui.implementation.components.image.ImagePanel;
|
||||||
import ui.implementation.components.intent.FileChooser;
|
import ui.implementation.components.intent.FileChooser;
|
||||||
import ui.abstractions.IDoubleMatrix;
|
import ui.abstractions.IDoubleMatrix;
|
||||||
@@ -96,6 +96,11 @@ public class DoubleMatrix extends AbstractView implements IDoubleMatrix
|
|||||||
this.whiteTextField.addActionListener(this::jTextFieldBlancActionPerformed);
|
this.whiteTextField.addActionListener(this::jTextFieldBlancActionPerformed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disposeCore() {
|
||||||
|
this.presenter.setView(null);
|
||||||
|
}
|
||||||
|
|
||||||
private JSlider buildSlider() {
|
private JSlider buildSlider() {
|
||||||
return new JSlider(JSlider.VERTICAL);
|
return new JSlider(JSlider.VERTICAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,39 +2,42 @@ package ui.implementation.views;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import domain.image.Image;
|
import domain.image.Image;
|
||||||
import infrastructure.ui.ImageMapper;
|
import presenters.filtering.FilteringPresenter;
|
||||||
import presenters.FilteringPresenter;
|
|
||||||
import ui.abstractions.AbstractView;
|
import ui.abstractions.AbstractView;
|
||||||
import ui.implementation.components.button.SaveButton;
|
import ui.implementation.components.controls.IntensitySlider;
|
||||||
import ui.implementation.components.image.ImagePanel;
|
import ui.implementation.components.controls.SaveButton;
|
||||||
import ui.abstractions.IFilteringView;
|
import ui.abstractions.IFilteringView;
|
||||||
|
import ui.implementation.components.image.TabbedImagePanel;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
|
|
||||||
public class FilteringView extends AbstractView implements IFilteringView {
|
public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||||
|
|
||||||
private ImagePanel lowPassContainer;
|
private final static String LOW_PASS_TAB_TITLE = "Passe-haut";
|
||||||
private ImagePanel highPassContainer;
|
private final static String HIGH_PASS_TAB_TITLE = "Passe-bas";
|
||||||
private JTabbedPane modeTab;
|
|
||||||
private JSlider intensitySlider;
|
private TabbedImagePanel modeTab;
|
||||||
|
private IntensitySlider intensitySlider;
|
||||||
private JLabel intensityLabel;
|
private JLabel intensityLabel;
|
||||||
private final FilteringPresenter presenter;
|
private final FilteringPresenter presenter;
|
||||||
private boolean isUpdating;
|
private boolean isUpdating;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FilteringView(FilteringPresenter presenter) {
|
public IdealFilteringView(FilteringPresenter presenter) {
|
||||||
this.presenter = presenter;
|
this.presenter = presenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initComponents(){
|
public void initComponents(){
|
||||||
this.lowPassContainer = new ImagePanel();
|
|
||||||
this.highPassContainer = new ImagePanel();
|
|
||||||
this.modeTab = buildModeTab();
|
|
||||||
this.intensitySlider = new JSlider(0,100,0);
|
|
||||||
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
|
||||||
this.intensityLabel = new JLabel();
|
this.intensityLabel = new JLabel();
|
||||||
|
this.intensitySlider = new IntensitySlider();
|
||||||
|
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
||||||
|
|
||||||
|
this.modeTab = new TabbedImagePanel();
|
||||||
|
this.modeTab.addPreviewTab(LOW_PASS_TAB_TITLE);
|
||||||
|
this.modeTab.addPreviewTab(HIGH_PASS_TAB_TITLE);
|
||||||
|
|
||||||
JButton saveButton = new SaveButton();
|
JButton saveButton = new SaveButton();
|
||||||
|
|
||||||
saveButton.addActionListener(e -> {});
|
saveButton.addActionListener(e -> {});
|
||||||
@@ -45,33 +48,7 @@ public class FilteringView extends AbstractView implements IFilteringView {
|
|||||||
pack();
|
pack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initValues(){
|
|
||||||
this.presenter.setView(this);
|
|
||||||
|
|
||||||
this.intensitySlider.setMinimum(0);
|
|
||||||
this.intensitySlider.setMaximum(100);
|
|
||||||
this.intensitySlider.setValue(50);
|
|
||||||
this.intensitySlider.addChangeListener(this::onCutoffUpdate);
|
|
||||||
|
|
||||||
this.intensityLabel.setText(String.valueOf(intensitySlider.getValue()));
|
|
||||||
|
|
||||||
this.modeTab.addChangeListener(e -> {
|
|
||||||
switch (modeTab.getSelectedIndex()) {
|
|
||||||
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getValue());
|
|
||||||
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.presenter.computeLowPassFiltering(intensitySlider.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JTabbedPane buildModeTab(){
|
|
||||||
JTabbedPane modeTabs = new JTabbedPane();
|
|
||||||
modeTabs.addTab("Passe-bas", lowPassContainer);
|
|
||||||
modeTabs.addTab("Passe-haut", highPassContainer);
|
|
||||||
return modeTabs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildLayout(JTabbedPane modeTab,
|
private void buildLayout(JTabbedPane modeTab,
|
||||||
JLabel valueTextField,
|
JLabel valueTextField,
|
||||||
@@ -158,10 +135,10 @@ public class FilteringView extends AbstractView implements IFilteringView {
|
|||||||
if (isUpdating) return;
|
if (isUpdating) return;
|
||||||
isUpdating = true;
|
isUpdating = true;
|
||||||
try {
|
try {
|
||||||
this.intensityLabel.setText(String.valueOf(intensitySlider.getValue()));
|
this.intensityLabel.setText(String.valueOf(intensitySlider.getPercentage()));
|
||||||
switch (modeTab.getSelectedIndex()) {
|
switch (modeTab.getSelectedIndex()) {
|
||||||
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getValue());
|
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||||
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getValue());
|
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getPercentage());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
isUpdating = false;
|
isUpdating = false;
|
||||||
@@ -170,12 +147,12 @@ public class FilteringView extends AbstractView implements IFilteringView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLowPassFiltering(Image image) {
|
public void updateLowPassFiltering(Image image) {
|
||||||
lowPassContainer.loadImage(ImageMapper.toBufferedImage(image));
|
modeTab.loadImage(LOW_PASS_TAB_TITLE, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateHighPassFiltering(Image image) {
|
public void updateHighPassFiltering(Image image) {
|
||||||
highPassContainer.loadImage(ImageMapper.toBufferedImage(image));
|
modeTab.loadImage(HIGH_PASS_TAB_TITLE, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -187,4 +164,27 @@ public class FilteringView extends AbstractView implements IFilteringView {
|
|||||||
public void updateButterworthLowPassFiltering(Image image) {
|
public void updateButterworthLowPassFiltering(Image image) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initValues(){
|
||||||
|
this.presenter.setView(this);
|
||||||
|
|
||||||
|
this.intensitySlider.addChangeListener(this::onCutoffUpdate);
|
||||||
|
this.intensityLabel.setText(String.valueOf(intensitySlider.getValue()));
|
||||||
|
|
||||||
|
this.modeTab.addChangeListener(e -> {
|
||||||
|
switch (modeTab.getSelectedIndex()) {
|
||||||
|
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||||
|
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getPercentage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disposeCore() {
|
||||||
|
this.presenter.setView(null);
|
||||||
|
this.presenter.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
190
src/main/java/ui/implementation/views/NonIdealFilteringView.java
Normal file
190
src/main/java/ui/implementation/views/NonIdealFilteringView.java
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
package ui.implementation.views;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import domain.image.Image;
|
||||||
|
import presenters.filtering.FilteringPresenter;
|
||||||
|
import ui.abstractions.AbstractView;
|
||||||
|
import ui.abstractions.IFilteringView;
|
||||||
|
import ui.implementation.components.controls.IntensitySlider;
|
||||||
|
import ui.implementation.components.controls.SaveButton;
|
||||||
|
import ui.implementation.components.image.TabbedImagePanel;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
|
||||||
|
public class NonIdealFilteringView extends AbstractView implements IFilteringView {
|
||||||
|
|
||||||
|
private final static String LOW_PASS_TAB_TITLE = "Passe-haut";
|
||||||
|
private final static String HIGH_PASS_TAB_TITLE = "Passe-bas";
|
||||||
|
|
||||||
|
private TabbedImagePanel modeTab;
|
||||||
|
private IntensitySlider intensitySlider;
|
||||||
|
private JLabel intensityLabel;
|
||||||
|
private final FilteringPresenter presenter;
|
||||||
|
private boolean isUpdating;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NonIdealFilteringView(FilteringPresenter presenter) {
|
||||||
|
this.presenter = presenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void buildLayout(JTabbedPane modeTab,
|
||||||
|
JLabel valueTextField,
|
||||||
|
JSlider intensitySlider,
|
||||||
|
JButton saveButton) {
|
||||||
|
|
||||||
|
JPanel rightPanel = new JPanel();
|
||||||
|
GroupLayout rightLayout = new GroupLayout(rightPanel);
|
||||||
|
rightPanel.setLayout(rightLayout);
|
||||||
|
|
||||||
|
rightLayout.setHorizontalGroup(
|
||||||
|
rightLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(valueTextField, GroupLayout.PREFERRED_SIZE, 90, GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addGroup(rightLayout.createSequentialGroup()
|
||||||
|
.addComponent(intensitySlider)
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
rightLayout.setVerticalGroup(
|
||||||
|
rightLayout.createSequentialGroup()
|
||||||
|
.addComponent(valueTextField, GroupLayout.PREFERRED_SIZE,
|
||||||
|
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||||
|
.addComponent(intensitySlider)
|
||||||
|
)
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
);
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// MAIN LAYOUT
|
||||||
|
// -------------------------
|
||||||
|
GroupLayout layout = new GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
|
||||||
|
// TOP BAR
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
//.addComponent(valeurMin)
|
||||||
|
.addGap(50)
|
||||||
|
.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(saveButton)
|
||||||
|
)
|
||||||
|
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
|
||||||
|
// MAIN CONTENT
|
||||||
|
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(modeTab)
|
||||||
|
.addComponent(rightPanel)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCutoffUpdate(ChangeEvent e) {
|
||||||
|
if (isUpdating) return;
|
||||||
|
isUpdating = true;
|
||||||
|
try {
|
||||||
|
this.intensityLabel.setText(String.valueOf(intensitySlider.getPercentage()));
|
||||||
|
switch (modeTab.getSelectedIndex()) {
|
||||||
|
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||||
|
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getPercentage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isUpdating = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLowPassFiltering(Image image) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateHighPassFiltering(Image image) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateButterworthHighPassFiltering(Image image) {
|
||||||
|
modeTab.loadImage(LOW_PASS_TAB_TITLE, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateButterworthLowPassFiltering(Image image) {
|
||||||
|
modeTab.loadImage(HIGH_PASS_TAB_TITLE, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initComponents(){
|
||||||
|
this.intensityLabel = new JLabel();
|
||||||
|
this.intensitySlider = new IntensitySlider();
|
||||||
|
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
||||||
|
|
||||||
|
this.modeTab = new TabbedImagePanel();
|
||||||
|
this.modeTab.addPreviewTab(LOW_PASS_TAB_TITLE);
|
||||||
|
this.modeTab.addPreviewTab(HIGH_PASS_TAB_TITLE);
|
||||||
|
|
||||||
|
JButton saveButton = new SaveButton();
|
||||||
|
|
||||||
|
saveButton.addActionListener(e -> {});
|
||||||
|
|
||||||
|
buildLayout(modeTab, intensityLabel, intensitySlider, saveButton);
|
||||||
|
setTitle("Filtering");
|
||||||
|
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initValues(){
|
||||||
|
this.presenter.setView(this);
|
||||||
|
|
||||||
|
this.intensitySlider.addChangeListener(this::onCutoffUpdate);
|
||||||
|
this.intensityLabel.setText(String.valueOf(intensitySlider.getValue()));
|
||||||
|
|
||||||
|
this.modeTab.addChangeListener(e -> {
|
||||||
|
switch (modeTab.getSelectedIndex()) {
|
||||||
|
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||||
|
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getPercentage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disposeCore() {
|
||||||
|
this.presenter.setView(null);
|
||||||
|
this.presenter.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user