diff --git a/ImgJava/build.gradle.kts b/ImgJava/build.gradle.kts index 2c6aacf..0feb8e5 100644 --- a/ImgJava/build.gradle.kts +++ b/ImgJava/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("com.github.johnrengelman.shadow") version "6.0.0" + id("com.github.johnrengelman.shadow") version "7.0.0" } group = "io.gitlab.jfronny" 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 81b00a8..9097878 100644 --- a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/Main.java +++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/Main.java @@ -18,7 +18,16 @@ public class Main { 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")); + Picture pict = stackViewer.push(new Picture("iris.jpg")); + pict = stackViewer.push(ImageUtil.mirror(pict, ImageUtil.MirrorMode.Horizontal)); + pict = stackViewer.push(ImageUtil.mirror(pict, ImageUtil.MirrorMode.Vertical)); + pict = stackViewer.push(ImageUtil.rotate(pict, ImageUtil.RotateMode.Left)); + pict = stackViewer.push(ImageUtil.rotate(pict, ImageUtil.RotateMode.Right)); + pict = stackViewer.push(ImageUtil.mirror(pict, ImageUtil.MirrorMode.Vertical)); + //pict = stackViewer.push(ImageUtil.blurBox(pict, 10)); + pict = stackViewer.push(ImageUtil.blurGauss(pict, 3)); + pict = stackViewer.push(ImageUtil.sharpen(pict, 3)); + pict.save(run.resolve("moscov.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 07158d9..f235ddd 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 @@ -1,5 +1,6 @@ package io.gitlab.jfronny.ImgJava.imageProcessing; +import io.gitlab.jfronny.ImgJava.util.MColor; import io.gitlab.jfronny.ImgJava.util.Picture; import java.awt.*; @@ -12,13 +13,23 @@ import java.awt.*; * @version 1.1 (28.11.2019) */ public class ImageUtil { + public enum MirrorMode { + Vertical, + Horizontal + } + + public enum RotateMode { + Left, + Right + } + /** * Horizontally mirrors an image (mutates original instance) * * @param picture Picture to mirror * @return The mirrored image */ - public static Picture mirror(Picture picture) { + public static Picture mirror(Picture picture, MirrorMode mirrorMode) { int w = picture.getWidth(); int h = picture.getHeight(); @@ -26,7 +37,153 @@ public class ImageUtil { Color[][] pixelNeu = new Color[w][h]; for (int x = 0; x < w; x++) { - System.arraycopy(pixel[(w - 1) - x], 0, pixelNeu[x], 0, h); + for (int y = 0; y < h; y++) { + pixelNeu[x][y] = switch (mirrorMode) { + case Vertical -> pixel[x][h - y - 1]; + case Horizontal -> pixel[w - x - 1][y]; + }; + } + } + + picture.setPixelArray(pixelNeu); + return picture; + } + + /** + * Rotates an image by 90° (mutates original instance) + * + * @param picture Picture to mirror + * @return The mirrored image + */ + public static Picture rotate(Picture picture, RotateMode rotateMode) { + int w = picture.getWidth(); + int h = picture.getHeight(); + + Color[][] pixel = picture.getPixelArray(); + Color[][] pixelNeu = new Color[h][w]; + + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + pixelNeu[y][x] = switch (rotateMode) { + case Left -> pixel[w - x - 1][y]; + case Right -> pixel[x][h - y - 1]; + }; + } + } + + picture.setPixelArray(pixelNeu); + return picture; + } + + + public static Picture blurBox(Picture picture, int amount) { + int w = picture.getWidth(); + int h = picture.getHeight(); + + Color[][] pixel; + Color[][] pixelNeu = picture.getPixelArray(); + + for (int i = 0; i < amount; i++) { + pixel = pixelNeu; + pixelNeu = new Color[w][h]; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + if (x < 1 || y < 1 || x + 1 >= w || y + 1 >= h) { + pixelNeu[x][y] = pixel[x][y]; + continue; + } + pixelNeu[x][y] = pixel[x][y]; + //p p p + //p 0 p + //p p p + MColor sum = new MColor(pixel[x - 1][y + 1]) + .add(pixel[x + 0][y + 1]) + .add(pixel[x + 1][y + 1]) + .add(pixel[x - 1][y + 0]) + .add(pixel[x + 0][y + 0]) + .add(pixel[x + 1][y + 0]) + .add(pixel[x - 1][y - 1]) + .add(pixel[x + 0][y - 1]) + .add(pixel[x + 1][y - 1]); + + pixelNeu[x][y] = sum.div(9).get(); + } + } + } + + picture.setPixelArray(pixelNeu); + return picture; + } + + public static Picture blurGauss(Picture picture, int radius) { + int w = picture.getWidth(); + int h = picture.getHeight(); + + Color[][] pixel = picture.getPixelArray(); + Color[][] pixelNeu = new Color[w][h]; + + double sigma = radius / 2d; + + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + + pixelNeu[x][y] = pixel[x][y]; + + MColor sum = new MColor(); + + double gSum = 0; + + for (int dx = -radius; dx <= radius; dx++) { + for (int dy = -radius; dy <= radius; dy++) { + if (x + dx >= 0 && y + dy >= 0 && x + dx < w && y + dy < h) { + double g = gauss(dx, dy, sigma); + gSum += g; + sum.addM(pixel[x + dx][y + dy], g); + } + } + } + + pixelNeu[x][y] = sum.div(gSum).get(); + } + } + + picture.setPixelArray(pixelNeu); + return picture; + } + + private static double gauss(double dX, double dY, double stDev) { + return Math.exp(-((dX * dX + dY * dY) / (2 * stDev * stDev))) / (2 * Math.PI * stDev * stDev); + } + + public static Picture sharpen(Picture picture, int amount) { + int w = picture.getWidth(); + int h = picture.getHeight(); + + Color[][] pixel; + Color[][] pixelNeu = picture.getPixelArray(); + + for (int i = 0; i < amount; i++) { + pixel = pixelNeu; + pixelNeu = new Color[w][h]; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + if (x < 1 || y < 1 || x + 1 >= w || y + 1 >= h) { + pixelNeu[x][y] = pixel[x][y]; + continue; + } + pixelNeu[x][y] = pixel[x][y]; + //p p p + //p 0 p + //p p p + MColor sum = new MColor(pixel[x + 0][y + 1]).mult(-1) + .addM(pixel[x - 1][y + 0], -1) + .addM(pixel[x + 0][y + 0], 5) + .addM(pixel[x + 1][y + 0], -1) + .addM(pixel[x + 0][y - 1], -1); + + pixelNeu[x][y] = sum.get(); + } + } } picture.setPixelArray(pixelNeu); 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 index ae0fdf2..6c21d05 100644 --- a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageStackViewer.java +++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageStackViewer.java @@ -9,7 +9,6 @@ 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 @@ -65,8 +64,10 @@ public class ImageStackViewer extends JFrame implements MouseWheelListener, KeyL BufferedImage bNew = new BufferedImage(base.getWidth(), base.getHeight(), base.getType()); image.getImage().copyData(bNew.getRaster()); history.add(bNew); - if (history.size() == currentIndex + 2) + if (history.size() == currentIndex + 2) { currentIndex++; + resize(); + } fixTitle(); return image; } @@ -76,7 +77,10 @@ public class ImageStackViewer extends JFrame implements MouseWheelListener, KeyL */ public void pop() { if (history.size() > 0) { - history.remove(history.size() - 1); + history.remove(currentIndex); + if (currentIndex >= history.size()) + currentIndex = history.size() - 1; + resize(); repaint(); } fixTitle(); @@ -103,6 +107,8 @@ public class ImageStackViewer extends JFrame implements MouseWheelListener, KeyL */ public void resize() { BufferedImage pictureCurrent = getCurrent(); + if (pictureCurrent == null) + return; int pref_x = (int) (pictureCurrent.getWidth() * zoom); int pref_y = (int) (pictureCurrent.getHeight() * zoom); imagePane.setPreferredSize(new Dimension(pref_x, pref_y)); @@ -150,6 +156,8 @@ public class ImageStackViewer extends JFrame implements MouseWheelListener, KeyL } private BufferedImage getCurrent() { + if (currentIndex < 0) + currentIndex = 0; if (currentIndex >= history.size()) return null; return history.get(currentIndex); @@ -181,12 +189,14 @@ public class ImageStackViewer extends JFrame implements MouseWheelListener, KeyL int w = currentIndex - 1; if (w >= 0) currentIndex = w; + resize(); repaint(); } case KeyEvent.VK_RIGHT -> { int w = currentIndex + 1; if (w < history.size()) currentIndex = w; + resize(); repaint(); } default -> System.out.println(e.getKeyChar()); diff --git a/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/MColor.java b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/MColor.java new file mode 100644 index 0000000..bde8f77 --- /dev/null +++ b/ImgJava/src/main/java/io/gitlab/jfronny/ImgJava/util/MColor.java @@ -0,0 +1,61 @@ +package io.gitlab.jfronny.ImgJava.util; + +import java.awt.*; + +public class MColor { + public int r; + public int g; + public int b; + public int a; + + public MColor(Color c) { + this(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()); + } + + public MColor(int r, int g, int b, int a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + public MColor() { + this(0, 0, 0, 0); + } + + public Color get() { + return new Color(Math.max(r, 0), Math.max(g, 0), Math.max(b, 0), Math.max(a, 0)); + } + + public MColor add(Color c) { + return add(new MColor(c)); + } + + public MColor add(MColor m) { + r += m.r; + g += m.g; + b += m.b; + a += m.a; + return this; + } + + public MColor addM(Color c, double factor) { + return add(new MColor(c).mult(factor)); + } + + public MColor mult(double factor) { + r *= factor; + g *= factor; + b *= factor; + a *= factor; + return this; + } + + public MColor div(double factor) { + r /= factor; + g /= factor; + b /= factor; + a /= factor; + return this; + } +}