This repository has been archived on 2022-08-05. You can view files and clone it, but cannot push or open issues or pull requests.
school-projects/src/main/java/io/gitlab/jfronny/ImgJava/util/ImageStackViewer.java

225 lines
6.9 KiB
Java

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;
/**
* 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<BufferedImage> 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++;
resize();
}
fixTitle();
return image;
}
/**
* Ruft das letzte abgespeicherte Bild aus der History wieder auf.
*/
public void pop() {
if (history.size() > 0) {
history.remove(currentIndex);
if (currentIndex >= history.size())
currentIndex = history.size() - 1;
resize();
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();
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));
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 < 0)
currentIndex = 0;
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;
resize();
repaint();
}
case KeyEvent.VK_RIGHT -> {
int w = currentIndex + 1;
if (w < history.size())
currentIndex = w;
resize();
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;
}
}