diff --git a/ImgJava/.gitignore b/ImgJava/.gitignore
new file mode 100644
index 0000000..26ce0b3
--- /dev/null
+++ b/ImgJava/.gitignore
@@ -0,0 +1,4 @@
+run/
+.idea/
+.gradle/
+build/
\ No newline at end of file
diff --git a/ImgJava/.idea/.gitignore b/ImgJava/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/ImgJava/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/ImgJava/.idea/compiler.xml b/ImgJava/.idea/compiler.xml
deleted file mode 100644
index b73660a..0000000
--- a/ImgJava/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ImgJava/.idea/gradle.xml b/ImgJava/.idea/gradle.xml
deleted file mode 100644
index 1fdf7d2..0000000
--- a/ImgJava/.idea/gradle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ImgJava/.idea/jarRepositories.xml b/ImgJava/.idea/jarRepositories.xml
deleted file mode 100644
index fdc392f..0000000
--- a/ImgJava/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ImgJava/.idea/misc.xml b/ImgJava/.idea/misc.xml
deleted file mode 100644
index 1700c77..0000000
--- a/ImgJava/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ImgJava/.idea/uiDesigner.xml b/ImgJava/.idea/uiDesigner.xml
deleted file mode 100644
index e96534f..0000000
--- a/ImgJava/.idea/uiDesigner.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
-
\ No newline at end of file
diff --git a/ImgJava/build.gradle.kts b/ImgJava/build.gradle.kts
index 5b78a64..2c6aacf 100644
--- a/ImgJava/build.gradle.kts
+++ b/ImgJava/build.gradle.kts
@@ -16,8 +16,6 @@ dependencies {
shadow(dependencyNotation)
}
- testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
- testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
dependency("org.jdom:jdom:1.1")
}
diff --git a/ImgJava/cum.png b/ImgJava/cum.png
deleted file mode 100644
index 7da097a..0000000
Binary files a/ImgJava/cum.png and /dev/null differ
diff --git a/ImgJava/gradle/wrapper/gradle-wrapper.properties b/ImgJava/gradle/wrapper/gradle-wrapper.properties
index da9702f..f371643 100644
--- a/ImgJava/gradle/wrapper/gradle-wrapper.properties
+++ b/ImgJava/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/Main.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/Main.java
index b9398d8..81b00a8 100644
--- a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/Main.java
+++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/Main.java
@@ -1,14 +1,25 @@
package io.gitlab.jfronny.ImgJava;
import io.gitlab.jfronny.ImgJava.imageProcessing.ImageUtil;
+import io.gitlab.jfronny.ImgJava.util.ImageStackViewer;
import io.gitlab.jfronny.ImgJava.util.Picture;
+import java.awt.*;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
public class Main {
public static void main(String[] args) {
try {
- ImageUtil.mirror(new Picture("iris.jpg")).save("cum.png");
+ ImageStackViewer stackViewer = new ImageStackViewer(new Dimension(1000, 1000));
+ stackViewer.setTitle("Jf Example");
+ Path run = Paths.get("./run/");
+ if (!Files.isDirectory(run))
+ Files.createDirectory(run);
+ stackViewer.push(ImageUtil.mirror(stackViewer.push(new Picture("iris.jpg")))).save(run.resolve("cum.png"));
+ stackViewer.repaint();
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/imageProcessing/ImageUtil.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/imageProcessing/ImageUtil.java
index d1cbee5..07158d9 100644
--- a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/imageProcessing/ImageUtil.java
+++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/imageProcessing/ImageUtil.java
@@ -13,26 +13,23 @@ import java.awt.*;
*/
public class ImageUtil {
/**
- * spiegeleHorizontal spiegelt das Bild, so dass rechts und links getauscht werden
+ * Horizontally mirrors an image (mutates original instance)
*
- * @param originalbild Ein Bild (Picture), das gespiegelt werden soll
- * @return Eine gespiegelte Kopie des Bildes
+ * @param picture Picture to mirror
+ * @return The mirrored image
*/
- public static Picture mirror(Picture originalbild) {
- int breite = originalbild.getWidth();
- int hoehe = originalbild.getHeight();
+ public static Picture mirror(Picture picture) {
+ int w = picture.getWidth();
+ int h = picture.getHeight();
- Color[][] pixel = originalbild.getPixelArray();
- Color[][] pixelNeu = new Color[breite][hoehe];
+ Color[][] pixel = picture.getPixelArray();
+ Color[][] pixelNeu = new Color[w][h];
- for (int x = 0; x < breite; x++) {
- for (int y = 0; y < hoehe; y++) {
- pixelNeu[x][y] = pixel[(breite - 1) - x][y];
- }
+ for (int x = 0; x < w; x++) {
+ System.arraycopy(pixel[(w - 1) - x], 0, pixelNeu[x], 0, h);
}
- Picture neuesBild = new Picture();
- neuesBild.setPixelArray(pixelNeu);
- return neuesBild;
+ picture.setPixelArray(pixelNeu);
+ return picture;
}
}
diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageObserver.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageObserver.java
new file mode 100644
index 0000000..5f2a7aa
--- /dev/null
+++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageObserver.java
@@ -0,0 +1,6 @@
+package io.gitlab.jfronny.ImgJava.util;
+
+public interface ImageObserver {
+ void resize();
+ void repaint(Picture p);
+}
diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageStackViewer.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageStackViewer.java
new file mode 100644
index 0000000..ae0fdf2
--- /dev/null
+++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageStackViewer.java
@@ -0,0 +1,214 @@
+package io.gitlab.jfronny.ImgJava.util;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * Der PictureViewer ist ein JFrame, der in der Lage ist ein
+ * Objekt der Klasse Picture anzuzeigen. Zusätzlich können
+ * mehrere Verarbeitungsschritte gespeichert werden, um ein
+ * "zurück"-Funktion zu ermöglichen.
+ *
+ * @author Thomas Schaller
+ * @version V1.2 vom 06.12.2019
+ */
+public class ImageStackViewer extends JFrame implements MouseWheelListener, KeyListener {
+ public static final int FIT = -1;
+ public static final int NORMAL = 1;
+
+ private double zoom;
+ private final List history = new ArrayList<>();
+ private int currentIndex = 0;
+ private final JLabel imagePane = new JLabel();
+ private final JScrollPane scrollPane;
+
+ public ImageStackViewer(Dimension imageSize) {
+ this.zoom = NORMAL;
+ setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ Container cp = getContentPane();
+ cp.setLayout(new BorderLayout());
+ imagePane.setPreferredSize(imageSize);
+ scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ scrollPane.setViewportView(imagePane);
+
+ cp.add(scrollPane, BorderLayout.CENTER);
+ pack();
+ this.setVisible(true);
+
+ Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+ int x = (d.width - getSize().width);
+ int y = 0;
+ setLocation(x, y);
+
+ scrollPane.addMouseWheelListener(this);
+ scrollPane.addKeyListener(this);
+ this.addMouseWheelListener(this);
+ this.addKeyListener(this);
+
+ setTitle("ImageViewer");
+ }
+
+ /**
+ * Speichert das übergebene Bild in der History.
+ */
+ public Picture push(Picture image) {
+ BufferedImage base = image.getImage();
+ BufferedImage bNew = new BufferedImage(base.getWidth(), base.getHeight(), base.getType());
+ image.getImage().copyData(bNew.getRaster());
+ history.add(bNew);
+ if (history.size() == currentIndex + 2)
+ currentIndex++;
+ fixTitle();
+ return image;
+ }
+
+ /**
+ * Ruft das letzte abgespeicherte Bild aus der History wieder auf.
+ */
+ public void pop() {
+ if (history.size() > 0) {
+ history.remove(history.size() - 1);
+ repaint();
+ }
+ fixTitle();
+ }
+
+ /**
+ * Setzt den Zoom-Faktor für das Bild.
+ * Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
+ *
+ * @param zoom Zoomfaktor (1.0 = 100%).
+ */
+ public void setZoom(double zoom) {
+ if (zoom > 0.01 && zoom < 10.0) {
+ this.zoom = zoom;
+ }
+ // else this.zoom = NORMAL;
+ resize();
+ repaint();
+ fixTitle();
+ }
+
+ /**
+ * Passt die Framegröße an das anzuzeigende Bild an.
+ */
+ public void resize() {
+ BufferedImage pictureCurrent = getCurrent();
+ int pref_x = (int) (pictureCurrent.getWidth() * zoom);
+ int pref_y = (int) (pictureCurrent.getHeight() * zoom);
+ imagePane.setPreferredSize(new Dimension(pref_x, pref_y));
+
+ Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+ if ((pref_x > d.getWidth() - 30) || (pref_y > d.getHeight() - 100)) {
+ pref_x = Math.min(pref_x, (int) d.getWidth() - 30);
+ pref_y = Math.min(pref_y, (int) d.getHeight() - 100);
+ scrollPane.setPreferredSize(new Dimension(pref_x, pref_y));
+ } else scrollPane.setPreferredSize(null);
+
+ imagePane.revalidate();
+ pack();
+ }
+
+ /**
+ * Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
+ */
+ @Override
+ public void repaint() {
+ double f = zoom;
+
+ BufferedImage pictureCurrent = getCurrent();
+ if (pictureCurrent != null) {
+ if (zoom == FIT) {
+ double faktorw = (double) imagePane.getWidth() / pictureCurrent.getWidth();
+ double faktorh = (double) imagePane.getHeight() / pictureCurrent.getHeight();
+ f = Math.min(faktorw, faktorh);
+ }
+ int disp_width = (int) (pictureCurrent.getWidth() * f);
+ int disp_height = (int) (pictureCurrent.getHeight() * f);
+
+ BufferedImage image = new BufferedImage(disp_width, disp_height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = image.createGraphics();
+ g.drawImage(pictureCurrent, 0, 0, disp_width, disp_height, 0, 0, pictureCurrent.getWidth(), pictureCurrent.getHeight(), null);
+ g.setColor(new java.awt.Color(0, 0, 0));
+ g.setStroke(new BasicStroke((float) 1));
+ g.drawRect(0, 0, disp_width - 1, disp_height - 1);
+
+ imagePane.setIcon(new ImageIcon(image));
+ }
+
+ imagePane.repaint();
+ super.repaint();
+ }
+
+ private BufferedImage getCurrent() {
+ if (currentIndex >= history.size())
+ return null;
+ return history.get(currentIndex);
+ }
+
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ int notches = e.getWheelRotation();
+ if (notches < 0) {
+ setZoom(zoom * 1.1);
+ } else {
+ setZoom(zoom / 1.1);
+ }
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ switch (e.getKeyCode()) {
+ case KeyEvent.VK_DELETE -> pop();
+ case KeyEvent.VK_LEFT -> {
+ int w = currentIndex - 1;
+ if (w >= 0)
+ currentIndex = w;
+ repaint();
+ }
+ case KeyEvent.VK_RIGHT -> {
+ int w = currentIndex + 1;
+ if (w < history.size())
+ currentIndex = w;
+ repaint();
+ }
+ default -> System.out.println(e.getKeyChar());
+ }
+ fixTitle();
+ }
+
+ private void fixTitle() {
+ setTitle(getTitle());
+ }
+
+ @Override
+ public void setTitle(String title) {
+ super.setTitle(title + " @ " + (currentIndex + 1) + "/" + history.size() + " # " + Math.round(zoom * 10000) / 10000d);
+ }
+
+ @Override
+ public String getTitle() {
+ String t = super.getTitle();
+ if (t.contains(" @ ")) {
+ t = t.split(" @ ")[0];
+ }
+ return t;
+ }
+}
diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/Picture.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/Picture.java
index 500b18b..d925298 100644
--- a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/Picture.java
+++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/Picture.java
@@ -24,7 +24,7 @@ import java.nio.file.Paths;
* @author Thomas Schaller (ZPG Informatik Klasse 9)
* @version 1.2 from 06.12.2019
*/
-
+//TODO arrays to proper classes
public class Picture {
// Einstellungmoeglichkeiten fuer das Zeichnen von Rechtecken und Ellipsen
@@ -38,7 +38,6 @@ public class Picture {
// gespeichertes Bild,
private BufferedImage image;
private Graphics2D g;
- private boolean antialiasing;
// aktuelle Farbeinstellungen
private Color background;
@@ -56,7 +55,7 @@ public class Picture {
private Font textfont = null;
// muss ein Bildanzeiger benachrichtigt werden
- private PictureViewer observer = null;
+ private ImageObserver observer = null;
private boolean autorefresh = true;
/**
@@ -82,9 +81,7 @@ public class Picture {
* @param file Dateiname des Bildes
*/
public Picture(Path file) throws IOException {
- this.antialiasing = true;
load(file);
- showInFrame();
}
/**
@@ -93,9 +90,7 @@ public class Picture {
* @param resourceName Name der Ressource
*/
public Picture(String resourceName) throws IOException {
- this.antialiasing = true;
loadResource("images/" + resourceName);
- showInFrame();
}
/**
@@ -106,27 +101,22 @@ public class Picture {
* @param background Farbe des Hintergrunds
*/
public Picture(int width, int height, String background) {
- this.antialiasing = true;
- this.background = decode(background);
+ this.background = Color.decode("0x" + background);
this.pencolor = new Color(0, 0, 0);
this.stroke = 1;
this.fillcolor = null;
makeImage(width, height);
- showInFrame();
- }
-
- public void showInFrame() {
- PictureViewer v = new PictureViewer(this);
}
private void makeImage(int width, int height) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- g = (Graphics2D) this.image.getGraphics();
+ g = createGraphics();
g.setColor(this.background);
g.fillRect(0, 0, width - 1, height - 1);
}
-
- protected void antialise() {
+
+ private Graphics2D createGraphics() {
+ Graphics2D g = image.createGraphics();
// Antialiasing
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Rendering
@@ -135,25 +125,7 @@ public class Picture {
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
// Color
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
-
- // Sonstiges
- // g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
- // g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
- // g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
- // g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
- // g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
- }
-
- public void setAntialising(boolean neuerWert) {
- this.antialiasing = neuerWert;
- }
-
- public boolean isAntialiasing() {
- return antialiasing;
- }
-
- public PictureViewer getObserver() {
- return observer;
+ return g;
}
/**
@@ -162,8 +134,9 @@ public class Picture {
*
* @param observer Anzeiger des Bildes
*/
- public void setObserver(PictureViewer observer) {
+ public Picture setObserver(ImageObserver observer) {
this.observer = observer;
+ return this;
}
/**
@@ -180,8 +153,9 @@ public class Picture {
*
* @param b Bild, das gespeichert werden soll.
*/
- public void setImage(BufferedImage b) {
+ public Picture setImage(BufferedImage b) {
image = b;
+ return this;
}
/**
@@ -192,14 +166,13 @@ public class Picture {
* @param width Breite des Bildes
* @param height Hoehe des Bildes
*/
- public void size(int width, int height) {
- pushImage();
+ public Picture size(int width, int height) {
makeImage(width, height);
g.setColor(background);
g.fillRect(0, 0, width - 1, height - 1);
if (observer != null) observer.resize();
- repaint();
+ return repaint();
}
/**
@@ -220,19 +193,6 @@ public class Picture {
return image.getHeight();
}
- /**
- * Erzeugt eine Kopie des Bildes und uebergibt sie an den Observer (falls existent), damit dieser die Versionen speichern kann
- */
- private void pushImage() {
- if (observer != null) {
- observer.pushImage();
- }
- }
-
- public void setTitle(String titel) {
- getObserver().setTitle(titel);
- }
-
/**
* Legt fest, ob nach jedem Zeichenbefehl automatisch das Bild auch in
* der Oberflaeche aktualisiert wird. Die Einstellung "false" beschleunigt
@@ -241,26 +201,26 @@ public class Picture {
*
* @param autoRefresh true = nach jedem Zeichenbefehl die Anzeige aktualisieren, false= nur durch die Methode refresh neu zeichnen
*/
- public void setAutoRefresh(boolean autoRefresh) {
+ public Picture setAutoRefresh(boolean autoRefresh) {
this.autorefresh = autoRefresh;
+ return this;
}
/**
* Auch die anzeigenden Klasse wird zum Neuzeichnen aufgefordert.
*/
- private void repaint() {
- if (observer != null && autorefresh) {
- observer.repaint();
- }
+ public Picture repaint() {
+ return repaint(false);
}
/**
* Ein repaint() (das Neuzeichnen) kann manuell erzwungen werden.
*/
- public void forceRepaint() {
- if (observer != null) {
- observer.repaint();
+ public Picture repaint(boolean force) {
+ if (observer != null && (force || autorefresh)) {
+ observer.repaint(this);
}
+ return this;
}
// ----------------------------------------- Zeichenfunktionen -----------------------------------------------
@@ -270,13 +230,12 @@ public class Picture {
* Der Hintergrund wird mit der Hintergrundfarbe neu gefuellt.
*/
- public void clear() {
- pushImage();
+ public Picture clear() {
makeImage(image.getWidth(), image.getHeight());
g.setColor(background);
g.fillRect(0, 0, image.getWidth() - 1, image.getHeight() - 1);
- repaint();
+ return repaint();
}
/**
@@ -286,7 +245,7 @@ public class Picture {
* @param coord Array mit vier Koordinateneintraegen im gegebenen Modus
* @param mode Modus der Koordinaten (CORNER, CORNERS, RADIUS oder CENTER)
*/
- private void convert(int[] coord, int mode) {
+ private Picture convert(int[] coord, int mode) {
switch (mode) {
case CORNER:
break;
@@ -301,6 +260,7 @@ public class Picture {
coord[0] -= coord[2] / 2;
coord[1] -= coord[3] / 2;
}
+ return this;
}
/**
@@ -317,8 +277,9 @@ public class Picture {
*
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
- public void rectMode(int mode) {
+ public Picture rectMode(int mode) {
rectMode = mode;
+ return this;
}
/**
@@ -335,8 +296,9 @@ public class Picture {
*
* @param mode Modus der Koordinateninterpretation (CORNER, CORNERS, CENTER oder RADIUS)
*/
- public void ellipseMode(int mode) {
+ public Picture ellipseMode(int mode) {
ellipseMode = mode;
+ return this;
}
/**
@@ -350,16 +312,14 @@ public class Picture {
* @param x2 x-Koordinate des 2. Punktes
* @param y2 y-Koordinate des 2. Punktes
*/
- public void line(int x1, int y1, int x2, int y2) {
- pushImage();
-
+ public Picture line(int x1, int y1, int x2, int y2) {
if (stroke > 0) {
g.setColor(pencolor);
g.setStroke(new BasicStroke((float) stroke));
// if(antialiasing) antialise();
g.drawLine(x1, y1, x2, y2);
}
- repaint();
+ return repaint();
}
/**
@@ -373,9 +333,7 @@ public class Picture {
* @param c meist die Breite des Rechtecks (kann durch rectMode() geaendert werden).
* @param d meist die Hoehe des Rechtecks (kann durch rectMode() geaendert werden).
*/
- public void rect(int a, int b, int c, int d) {
- pushImage();
-
+ public Picture rect(int a, int b, int c, int d) {
int[] coord = {a, b, c, d};
convert(coord, rectMode);
if (fillcolor != null) {
@@ -387,7 +345,7 @@ public class Picture {
g.setStroke(new BasicStroke((float) stroke));
g.drawRect(coord[0], coord[1], coord[2], coord[3]);
}
- repaint();
+ return repaint();
}
/**
@@ -401,9 +359,7 @@ public class Picture {
* @param c meist die Breite des Rechtecks (kann durch ellipseMode() geaendert werden).
* @param d meist die Hoehe des Rechtecks (kann durch ellipseMode() geaendert werden).
*/
- public void ellipse(int a, int b, int c, int d) {
- pushImage();
-
+ public Picture ellipse(int a, int b, int c, int d) {
int[] coord = {a, b, c, d};
convert(coord, ellipseMode);
if (fillcolor != null) {
@@ -416,7 +372,7 @@ public class Picture {
// if(antialiasing) antialise();
g.drawOval(coord[0], coord[1], coord[2], coord[3]);
}
- repaint();
+ return repaint();
}
/**
@@ -432,10 +388,10 @@ public class Picture {
* @param x3 meist die x-Koordinate des 3. Punkts.
* @param y3 meist die y-Koordinate des 3. Punkts.
*/
- public void triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
+ public Picture triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
int[] px = {x1, x2, x3};
int[] py = {y1, y2, y3};
- polygon(px, py);
+ return polygon(px, py);
}
/**
@@ -454,10 +410,11 @@ public class Picture {
* @param x4 meist die x-Koordinate des 3. Punkts.
* @param y4 meist die y-Koordinate des 3. Punkts.
*/
- public void quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
+ public Picture quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int[] px = {x1, x2, x3, x4};
int[] py = {y1, y2, y3, y4};
polygon(px, py);
+ return this;
}
/**
@@ -469,9 +426,7 @@ public class Picture {
* @param y Liste der y-Koordinaten der Punkte.
*/
- public void polygon(int[] x, int[] y) {
- pushImage();
-
+ public Picture polygon(int[] x, int[] y) {
if (fillcolor != null) {
g.setColor(fillcolor);
g.fillPolygon(x, y, y.length);
@@ -482,7 +437,7 @@ public class Picture {
// if(antialiasing) antialise();
g.drawPolygon(x, y, x.length);
}
- repaint();
+ return repaint();
}
/**
@@ -492,8 +447,9 @@ public class Picture {
* @param x x-Koordinate des Punktes
* @param y y-Koordinate des Punktes
*/
- public void point(int x, int y) {
+ public Picture point(int x, int y) {
ellipse(x, y, 1, 1);
+ return this;
}
// ----------------------------------------- Schriftdarstellung -----------------------------------------------
@@ -506,9 +462,7 @@ public class Picture {
* @param x x-Koordinate des Textanfangs
* @param y y-Koordinate der Grundlinie des Textes.
*/
- public void text(String s, int x, int y) {
- pushImage();
-
+ public Picture text(String s, int x, int y) {
if (pencolor != null) {
if (fillcolor == null)
g.setColor(Color.black);
@@ -519,7 +473,7 @@ public class Picture {
// if(antialiasing)g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.drawString(s, x, y);
}
- repaint();
+ return repaint();
}
/**
@@ -528,46 +482,13 @@ public class Picture {
*
* @param font ein Font-Objekt
*/
- public void textFont(Font font) {
+ public Picture textFont(Font font) {
this.textfont = font;
+ return this;
}
// ----------------------------------------- Farbfestlegungen -----------------------------------------------
- /**
- * Hilfsfunktion zur Interpretation von Farben
- */
- private Color decode(String color) {
- try {
- return new Color(
- Integer.valueOf(color.substring(0, 2), 16),
- Integer.valueOf(color.substring(2, 4), 16),
- Integer.valueOf(color.substring(4, 6), 16));
- } catch (Exception e) {
- System.err.println("Falscher Farbcode");
- return Color.BLACK;
- }
- }
-
- /**
- * Hilfsfunktion zur Interpretation von Farben
- */
- private Color decode(int color) {
- try {
- if (color >= 0 && color < 256) {
- return new Color(color, color, color);
- } else {
- int r = color / 0x010000 % 0xFF;
- int g = color / 0x000100 % 0xFF;
- int b = color % 0xFF;
- // System.out.println(""+r+","+g+","+b);
- return new Color(r, g, b);
- }
- } catch (Exception e) {
- System.err.println("Falscher Farbcode");
- return Color.BLACK;
- }
- }
/**
* Legt die Farbe fest, mit der Linien und Raender um Formen gezeichnet werden.
@@ -576,8 +497,9 @@ public class Picture {
*
* @param pencolor Stiftfarbe in Hexadezimaldarstellung
*/
- public void stroke(String pencolor) {
- this.pencolor = decode(pencolor);
+ public Picture stroke(String pencolor) {
+ this.pencolor = Color.decode("0x" + pencolor);
+ return this;
}
/**
@@ -586,8 +508,9 @@ public class Picture {
*
* @param pencolor Stiftfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiss, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
- public void stroke(int pencolor) {
- this.pencolor = decode(pencolor);
+ public Picture stroke(int pencolor) {
+ this.pencolor = new Color(pencolor);
+ return this;
}
/**
@@ -598,15 +521,17 @@ public class Picture {
* @param g Gruenanteil (0-255) der Stiftfarbe
* @param b Blauanteil (0-255) der Stiftfarbe
*/
- public void stroke(int r, int g, int b) {
+ public Picture stroke(int r, int g, int b) {
this.pencolor = new Color(r, g, b);
+ return this;
}
/**
* Legt fest, dass keine Linien oder Raender um Formen gezeichnet werden soll.
*/
- public void noStroke() {
+ public Picture noStroke() {
this.pencolor = null;
+ return this;
}
/**
@@ -615,8 +540,9 @@ public class Picture {
*
* @param width Breite in Pixel
*/
- public void strokeWeight(double width) {
+ public Picture strokeWeight(double width) {
this.stroke = width;
+ return this;
}
/**
@@ -626,8 +552,9 @@ public class Picture {
*
* @param fillcolor Fuellfarbe in Hexadezimaldarstellung
*/
- public void fill(String fillcolor) {
- this.fillcolor = decode(fillcolor);
+ public Picture fill(String fillcolor) {
+ this.fillcolor = Color.decode("0x" + fillcolor);
+ return this;
}
/**
@@ -636,8 +563,9 @@ public class Picture {
*
* @param fillcolor Fuellfarbe (0-255: Graustufe zwischen 0 schwarz und 255 weiss, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
- public void fill(int fillcolor) {
- this.fillcolor = decode(fillcolor);
+ public Picture fill(int fillcolor) {
+ this.fillcolor = new Color(fillcolor);
+ return this;
}
/**
@@ -648,15 +576,17 @@ public class Picture {
* @param g Gruenanteil (0-255) der Fuellfarbe
* @param b Blauanteil (0-255) der Fuellfarbe
*/
- public void fill(int r, int g, int b) {
+ public Picture fill(int r, int g, int b) {
this.fillcolor = new Color(r, g, b);
+ return this;
}
/**
* Legt fest, dass die Formen nicht gefuellt werden sollen.
*/
- public void noFill() {
+ public Picture noFill() {
this.fillcolor = null;
+ return this;
}
/**
@@ -665,16 +595,13 @@ public class Picture {
*
* @param c Farbe fuer den Hintergrund (0-255: Graustufe zwischen 0 schwarz und 255 weiss, sonst: c wird als 3-Byte RGB-Wert interpretiert)
*/
- public void background(int c) {
+ public Picture background(int c) {
if (c < 256) {
this.background = new Color(c, c, c);
} else {
- int r = c / 0x010000;
- int g = c / 0x000100 % 0xFF;
- int b = c % 0xFF;
- this.background = new Color(r, g, b);
+ this.background = new Color(c);
}
- this.clear();
+ return this.clear();
}
/**
@@ -685,9 +612,9 @@ public class Picture {
* @param g Gruenanteil (0-255) der Hintergrundfarbe
* @param b Blauanteil (0-255) der Hintergrundfarbe
*/
- public void background(int r, int g, int b) {
+ public Picture background(int r, int g, int b) {
this.background = new Color(r, g, b);
- this.clear();
+ return this.clear();
}
/**
@@ -696,9 +623,9 @@ public class Picture {
*
* @param hex String Farbe in Hexadezimalangabe
*/
- public void background(String hex) {
- this.background = decode(hex);
- this.clear();
+ public Picture background(String hex) {
+ this.background = Color.decode("0x" + hex);
+ return this.clear();
}
// ----------------------------------------- Dateioperationen -----------------------------------------------
@@ -709,8 +636,8 @@ public class Picture {
*
* @param file Dateipfad
*/
- public void load(String file) throws IOException {
- load(Files.newInputStream(Paths.get(".").toAbsolutePath().normalize().resolve(file)));
+ public Picture load(String file) throws IOException {
+ return load(Files.newInputStream(Paths.get(".").toAbsolutePath().normalize().resolve(file)));
}
/**
@@ -719,8 +646,8 @@ public class Picture {
*
* @param file Dateipfad
*/
- public void load(Path file) throws IOException {
- load(Files.newInputStream(file));
+ public Picture load(Path file) throws IOException {
+ return load(Files.newInputStream(file));
}
/**
@@ -729,15 +656,15 @@ public class Picture {
*
* @param stream Bildquelle
*/
- public void load(InputStream stream) throws IOException {
+ public Picture load(InputStream stream) throws IOException {
this.image = ImageIO.read(stream);
- this.g = (Graphics2D) image.getGraphics();
- this.background = decode("D0D0D0");
+ this.g = createGraphics();
+ this.background = Color.decode("0xD0D0D0");
this.pencolor = new Color(0, 0, 0);
this.fillcolor = null;
this.stroke = 1;
if (observer != null) observer.resize();
- this.repaint();
+ return this.repaint();
}
/**
@@ -745,8 +672,8 @@ public class Picture {
*
* @param resource Ressourcenpfad
*/
- public void loadResource(String resource) throws IOException {
- load(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource));
+ public Picture loadResource(String resource) throws IOException {
+ return load(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource));
}
/**
@@ -756,16 +683,17 @@ public class Picture {
*
* @param file Neuer Dateipfad
*/
- public void save(Path file) throws IOException {
+ public Picture save(Path file) throws IOException {
String[] fn = file.getFileName().toString().split("\\.");
if (fn.length == 0) {
- save(file.resolve("unnamed.png"));
+ return save(file.resolve("unnamed.png"));
}
else if (fn.length < 2) {
- save(file.getParent().resolve(fn[0] + ".png"));
+ return save(file.getParent().resolve(fn[0] + ".png"));
}
else {
ImageIO.write(image, fn[fn.length - 1].toUpperCase(), Files.newOutputStream(file));
+ return this;
}
}
@@ -776,8 +704,8 @@ public class Picture {
*
* @param file Neuer Dateipfad
*/
- public void save(String file) throws IOException {
- save(Paths.get(".").toAbsolutePath().normalize().resolve(file));
+ public Picture save(String file) throws IOException {
+ return save(Paths.get(".").toAbsolutePath().normalize().resolve(file));
}
// ----------------------------------------- Sonstiges -----------------------------------------------
@@ -804,7 +732,7 @@ public class Picture {
*
* @param pixel zweidimensionales Array von Color-Objekten
*/
- public void setPixelArray(Color[][] pixel) {
+ public Picture setPixelArray(Color[][] pixel) {
size(pixel.length, pixel[0].length);
for (int x = 0; x < image.getWidth(); x++) {
@@ -814,18 +742,6 @@ public class Picture {
}
}
repaint();
- }
-
- /**
- * Hilfsfunktion zum Verzoegern der Ausgabe
- *
- * @param millis Wartezeit in Millisekunden
- */
- public void delay(int millis) {
- try {
- Thread.sleep(millis);
- } catch (Exception e) {
- System.out.println("Fehler beim Verzoegern der Ausgabe");
- }
+ return this;
}
}
diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/PictureViewer.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/PictureViewer.java
deleted file mode 100644
index 4bee87f..0000000
--- a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/PictureViewer.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package io.gitlab.jfronny.ImgJava.util;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.awt.image.BufferedImage;
-import java.util.Vector;
-
-/**
- * Der PictureViewer ist ein JFrame, der in der Lage ist ein
- * Objekt der Klasse Picture anzuzeigen. Zusätzlich können
- * mehrere Verarbeitungsschritte gespeichert werden, um ein
- * "zurück"-Funktion zu ermöglichen.
- *
- * @author Thomas Schaller
- * @version V1.2 vom 06.12.2019
- */
-public class PictureViewer extends JFrame implements MouseWheelListener {
- public static final int FIT = -1;
- public static final int NORMAL = 1;
-
- private static final int ANZ_BACK = 0;
- protected Picture picture = null;
- private double zoom;
- private final Vector history;
- private final JLabel imagePane = new JLabel();
- private final JScrollPane scrollPane;
- // private boolean antialiasing;
-
- /**
- * Erzeugt ein ScrollPanel der Größe 500x400
- */
- public PictureViewer() {
- this(800, 500);
- }
-
- /**
- * Erzeugt ein ScrollPanel der angegebenen Größe
- *
- * @param width Breite des Bildes
- * @param height Höhe des Bildes
- */
- public PictureViewer(int width, int height) {
- this(new Picture(width, height));
- }
-
- public PictureViewer(Picture p) {
- picture = p;
- picture.setObserver(this);
- this.history = new Vector();
- this.zoom = NORMAL;
- setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
- Container cp = getContentPane();
- cp.setLayout(new BorderLayout());
- imagePane.setPreferredSize(new Dimension(p.getWidth(), p.getHeight()));
- scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
- scrollPane.setViewportView(imagePane);
-
- cp.add(scrollPane, BorderLayout.CENTER);
- pack();
- this.setVisible(true);
-
- repaint();
-
- Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
- int x = (d.width - getSize().width);
- //int x = 0;
- int y = 0;
- setLocation(x, y);
-
- scrollPane.addMouseWheelListener(this);
- }
-
- /**
- * Speichert das übergebene Bild in der History.
- *
- * @param b zu speicherndes Bild
- */
- public void pushImage() {
- if (ANZ_BACK > 0) {
- if (history.size() == ANZ_BACK) {
- history.removeElementAt(0);
- }
-
- BufferedImage b = new BufferedImage(picture.getWidth(), picture.getHeight(), picture.getImage().getType());
- Graphics g = b.getGraphics();
- g.drawImage(picture.getImage(), 0, 0, null);
- g.dispose();
-
- history.add(b);
- }
- }
-
- /**
- * Ruft das letzte abgespeicherte Bild aus der History wieder auf.
- */
- private void popImage() {
- int anz = history.size();
- if (anz > 0) {
- BufferedImage i = history.get(anz - 1);
- history.removeElementAt(anz - 1);
- picture.setImage(i);
- repaint();
- }
- }
-
- /**
- * Ruft das letzte abgespeicherte Bild aus der History wieder auf.
- */
- public void back() {
- popImage();
- }
-
- /**
- * Setzt den Zoom-Faktor für das Bild.
- * Als Zoomfaktor sind auch die Konstanten Bildanzeiger.FIT (auf Bildschirmgröße zoomen) und Bildanzeiger.NORMAL (100%) möglich.
- *
- * @param factor Zoomfaktor (1.0 = 100%).
- */
- public void setZoom(double zoom) {
- if (zoom > 0.01 && zoom < 10.0) {
- this.zoom = zoom;
- }
- // else this.zoom = NORMAL;
- resize();
- repaint();
- }
-
- // public void setAntialiasing(boolean antialiasing) {
- // this.antialiasing = antialiasing;
- // }
-
- /**
- * Setzt die automatische Neuanzeige des Bildes.
- * Mit dieser Methode kann man einstellen, ob nach jedem Zeichenbefehl
- * die Anzeige auf dem Bildschirm aktualisiert werden soll. Bei sehr
- * vielen Zeichenbefehlen wird die Ausgabe dadurch sehr langsam. Es reicht
- * eine Anzeige am Ende der Zeichenbefehle. Rufen Sie dann für das Neuzeichnen
- * die Methode refresh() auf.
- *
- * @param autoRefresh true, wenn nach jedem Zeichenbefehl die Anzeige aktualisiert werden soll.
- */
- public void setAutoRefresh(boolean autoRefresh) {
- picture.setAutoRefresh(autoRefresh);
- }
-
- /**
- * Sorgt für die Aktualisierung der Bildschrimanzeige. Das aktuelle Bild
- * wird dadurch angezeigt. Durch Einstellung von autoRefresh kann die
- * Anzeige automatisiert werden.
- */
- public void refresh() {
- repaint();
- }
-
- /**
- * Passt die Framegröße an das anzuzeigende Bild an.
- */
- public void resize() {
- int pref_x = (int) (picture.getWidth() * zoom);
- int pref_y = (int) (picture.getHeight() * zoom);
- imagePane.setPreferredSize(new Dimension(pref_x, pref_y));
-
- Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
- if ((pref_x > d.getWidth() - 30) || (pref_y > d.getHeight() - 100)) {
- pref_x = Math.min(pref_x, (int) d.getWidth() - 30);
- pref_y = Math.min(pref_y, (int) d.getHeight() - 100);
- scrollPane.setPreferredSize(new Dimension(pref_x, pref_y));
- } else scrollPane.setPreferredSize(null);
-
- imagePane.revalidate();
- pack();
- }
-
- /**
- * Setzt das angezeigt Bild neu und beachtet dabei den Zoomfaktor.
- */
-
- public void repaint() {
- double faktor = zoom;
-
- if (zoom == FIT) {
- double faktorw = (double) imagePane.getWidth() / picture.getWidth();
- double faktorh = (double) imagePane.getHeight() / picture.getHeight();
- faktor = Math.min(faktorw, faktorh);
- }
- int disp_width = (int) (picture.getWidth() * faktor);
- int disp_height = (int) (picture.getHeight() * faktor);
-
- BufferedImage image = new BufferedImage(disp_width, disp_height, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g = (Graphics2D) image.getGraphics();
-
- if (picture.isAntialiasing()) {
- picture.antialise();
- } else g.getRenderingHints().clear();
-
- g.drawImage(picture.getImage(), 0, 0, disp_width, disp_height, 0, 0, picture.getWidth(), picture.getHeight(), null);
- g.setColor(new java.awt.Color(0, 0, 0));
- g.setStroke(new BasicStroke((float) 1));
- g.drawRect(0, 0, disp_width - 1, disp_height - 1);
-
- imagePane.setIcon(new ImageIcon(image));
- imagePane.repaint();
-
- }
-
- /**
- * Setzt ZoomFaktor über MouseWheel
- */
- public void mouseWheelMoved(MouseWheelEvent e) {
- int notches = e.getWheelRotation();
- if (notches < 0) {
- setZoom(zoom * 1.1);
- } else {
- setZoom(zoom * 1.0 / 1.1);
- }
- }
-}