Dies funktioniert auch soweit. Jedoch ab einer bestimmten Kombination aus Bildgröße und Zoomfakor verschwindet das Bild aus der Anzeige.
Verwendet man sehr sehr große Bilder werden die Bilddaten geladen aber kein Bild angezeigt.
Ich habe schon nach Beschränkungen bei Verwenden der AffinenTransformation gesucht aber denke da bewege ich mich noch im Rahmen.
Bei mir funktioniert der Code. Ich denke dass es sich um ein Speicherproblem handelt.
Verwende ich eine 32 -Bit VM. Bekomme ich eine OutofMemory Exception beim 2ten Bild.
Ich habe deinen Code etwas
überarbeitet, um ihn etwas
übersichtlicher zu gestalten und lasse zusätzlich den freien Speicher vor dem Laden und nach dem Laden der Grafik anzuzeigen. Beim 1ten Bild geht sich bei mir der Speicher gerade noch aus. Das bedeutet ich kann maximal skalieren und zoomen.
[CODE lang="java" title="ImageZoomer"]import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ImageZoomer {
public static boolean DEBUG = false;
final static String filename = "Pano2.jpg";
public static void main(String[] args) throws InterruptedException {
showMemory();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame frame = new JFrame("PicturePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
PicturePanel ucpanel = new PicturePanel(filename, 425);
frame.getContentPane().add(ucpanel, BorderLayout.CENTER);
frame.setSize(new Dimension(1920, 600));
frame.setVisible(true);
}
});
Thread.sleep(2000);
showMemory();
}
public static void showMemory() {
Runtime rt = Runtime.getRuntime();
long totalMem = rt.totalMemory();
long maxMem = rt.maxMemory();
long freeMem = rt.freeMemory();
double megs = 1048576.0;
System.out.println("------------------------------------------------");
System.out.println("Total Memory: " + totalMem + " (" + (totalMem / megs) + " MiB)");
System.out.println("Max Memory: " + maxMem + " (" + (maxMem / megs) + " MiB)");
System.out.println("Free Memory: " + freeMem + " (" + (freeMem / megs) + " MiB)");
}
}[/CODE]
[CODE lang="java" title="TransformParam Containerklasse mit Hilfsfunktionen"]import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
public class TransformParam {
double translateX = 0;
double translateY = 0;
double scaleX = 1;
double scaleY = 1;
double stretchX = 1;
double prescaler = 1;
public void fitInRangeTranslateX(double min, double max) {
if (translateX < min)
translateX = min;
else if (translateX > max)
translateX = max;
}
public void fitInRangeTranslateY(double min, double max) {
if (translateY < min)
translateY = min;
else if (translateY > max)
translateY = max;
}
public AffineTransform getAffineTransFormParam(BufferedImage image, Dimension dim) {
AffineTransform at = new AffineTransform();
double t1x = -(double) image.getWidth(null) / 2 * scaleX * prescaler;
double t1y = -(double) image.getHeight(null) / 2 * scaleY * prescaler;
double sx = scaleX * prescaler;
double sy = scaleY * prescaler;
double t2x = (double) dim.width / 2 / scaleX / prescaler;
double t2y = (double) dim.height / 2 / scaleY / prescaler;
if (ImageZoomer.DEBUG)
System.out.println("T1X: " + t1x + "\tT1Y: " + t1y + "\tSX: " + sx + "\tSY: " + sy + "\tT2X: " + t2x
+ "\tT2Y: " + t2y);
// // the prescale, stretch_x and zoom transformation
at.setToIdentity();
at.translate(t1x, t1y);
at.scale(sx, sy);
at.translate(t2x, t2y);
// The panning transformation
at.translate(translateX, translateY);
return at;
}
public void reset() {
translateX = translateY = 0;
scaleX = scaleY = stretchX = prescaler = 1;
}
@Override
public String toString() {
return "translateX: " + translateX + "\ttranslateY: " + translateY + "\tstretchX: " + stretchX + "\tscaleX: "
+ scaleX + "\tscaleY: " + scaleY + "\tprescaler: " + prescaler;
}
}[/CODE]
[CODE lang="java" title="PicturePanel"]import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PicturePanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final int MIN_ZOOM = 100;
private static final int MAX_ZOOM = 1000;
private PanAndZoomCanvas canvas;
private JSlider zoomSlider;
private JSlider horizontalScaleSlider;
private int zoomPercent = 100;
private TransformParam param = new TransformParam();
public PicturePanel(String imagename, int height) {
setPreferredSize(new Dimension(1840, height));
setBackground(Color.DARK_GRAY);
createComponents(imagename, height);
JLabel zoomSliderLabel = new JLabel("Zoom", JLabel.CENTER);
zoomSliderLabel.setForeground(Color.white);
JLabel horizontalScaleSliderLabel = new JLabel("Stretch", JLabel.CENTER);
horizontalScaleSliderLabel.setForeground(Color.white);
JSeparator separator = new JSeparator(SwingConstants.VERTICAL);
Dimension sDimension = new Dimension(100, 0);
separator.setPreferredSize(sDimension);
separator.setMaximumSize(sDimension);
add(separator);
add(zoomSliderLabel);
add(zoomSlider, BorderLayout.NORTH);
add(horizontalScaleSliderLabel);
add(horizontalScaleSlider, BorderLayout.NORTH);
add(canvas, BorderLayout.SOUTH);
}
public void createComponents(String imagename, int height) {
PanningHandler panner = new PanningHandler();
canvas = new PanAndZoomCanvas(imagename, height);
canvas.addMouseListener(panner);
canvas.addMouseMotionListener(panner);
canvas.setBorder(BorderFactory.createLineBorder(Color.black));
canvas.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
int notches = e.getWheelRotation();
int zoomStep = 50;
// Don't scale below 100% and above 1000%
if (notches > 0 && zoomPercent == MIN_ZOOM || notches < 0 && zoomPercent == MAX_ZOOM)
return;
zoomStep = (zoomPercent >= 300 && notches != 0) ? 50 : 20;
zoomPercent += notches < 0 ? zoomStep : -zoomStep;
zoomSlider.setValue(zoomPercent);
}
});
// code for handling zooming
zoomSlider = new JSlider(JSlider.HORIZONTAL, MIN_ZOOM, MAX_ZOOM, MIN_ZOOM);
zoomSlider.setMajorTickSpacing(200);
zoomSlider.setMinorTickSpacing(100);
zoomSlider.setPaintTicks(true);
zoomSlider.setPaintLabels(true);
zoomSlider.setToolTipText("Zoom");
zoomSlider.addChangeListener(new ScaleHandler());
zoomSlider.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
zoomSlider.setValue(100);
param.translateX = 0;
param.translateY = 0;
param.scaleX = 1;
param.scaleY = 1;
repaint();
}
}
});
// Slider for horizontal scaling
horizontalScaleSlider = new JSlider(JSlider.HORIZONTAL, 0, 500, 100);
horizontalScaleSlider.setMajorTickSpacing(100);
horizontalScaleSlider.setMinorTickSpacing(50);
horizontalScaleSlider.setPaintTicks(true);
horizontalScaleSlider.setPaintLabels(true);
horizontalScaleSlider.setToolTipText("Horizontal Stretch");
horizontalScaleSlider.addChangeListener(new HorizontalScaleHandler());
horizontalScaleSlider.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
horizontalScaleSlider.setValue(100);
}
}
});
}
public double getStretch_X() {
return param.stretchX;
}
public double getTranslateX() {
return param.translateX;
}
public double getTranslateY() {
return param.translateY;
}
public int getZoomPercent() {
return zoomPercent;
}
public void setStretch_X(double value) {
param.scaleX = value;
horizontalScaleSlider.setValue((int) (param.stretchX * 100));
repaint();
}
public void setTranslateX(double value) {
param.translateX = value;
this.repaint();
}
public void setTranslateY(double value) {
param.translateY = value;
this.repaint();
}
public void setZoomPercent(int value) {
zoomPercent = value;
zoomSlider.setValue(zoomPercent);
this.repaint();
}
class PanAndZoomCanvas extends JComponent {
public final int MAX_IMG_HEIGHT;
private static final long serialVersionUID = 1L;
private String ucImageURL;
private BufferedImage image = null;
PanAndZoomCanvas(String ucimagename, int height) {
MAX_IMG_HEIGHT = height;
param.reset();
ucImageURL = ucimagename;
}
@Override
public Dimension getPreferredSize() {
return getParent().getPreferredSize();
}
public boolean loadImage() {
if (ucImageURL == null || ucImageURL.length() < 2) // invalid URL
return false;
try {
image = ImageIO.read(new File(ucImageURL));
if (ImageZoomer.DEBUG && image != null)
System.out.println("Loaded new image: " + ucImageURL + "\tWidth: " + image.getWidth() + "\tHeight: "
+ image.getHeight());
} catch (IOException e) {
System.out.println("Unable to load file: " + ucImageURL.toString());
return false;
}
return true;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null && !loadImage())
return;
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
double translate_x_max = image.getWidth(null) / 2;
double translate_x_min = -image.getWidth(null) / 2;
double translate_y_max = image.getHeight(null) / 2;
double translate_y_min = -image.getHeight(null) / 2;
param.fitInRangeTranslateX(translate_x_min, translate_x_max);
param.fitInRangeTranslateY(translate_y_min, translate_y_max);
param.prescaler = (double) MAX_IMG_HEIGHT / (double) image.getHeight(null);
if (ImageZoomer.DEBUG)
System.out.println("Panel width: " + getWidth() + "\tHeight: " + getHeight());
// // the prescale, stretch_x and zoom transformation
AffineTransform at = param.getAffineTransFormParam(image,
new Dimension((int) getPreferredSize().getWidth(), MAX_IMG_HEIGHT));
if (ImageZoomer.DEBUG) {
System.out.println(param);
System.out.println("Transformation: " + at.toString());
}
g2D.drawImage(image, at, null);
g2D.dispose();
}
}
class PanningHandler extends MouseAdapter {
private int x;
private int y;
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
param.reset();
zoomSlider.setValue(100);
horizontalScaleSlider.setValue(100);
canvas.repaint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
// the size of the pan translations
// are defined by the current mouse location subtracted
// from the reference location
int deltaX = e.getX() - x;
int deltaY = e.getY() - y;
// make the reference point be the new mouse point.
param.translateX += deltaX / Math.max(0.00001, (param.scaleX * param.prescaler));
param.translateY += deltaY / Math.max(0.00001, (param.scaleY * param.prescaler));
x = e.getX();
y = e.getY();
canvas.repaint();
}
@Override
public void mousePressed(MouseEvent e) {
// capture the starting point
x = e.getX();
y = e.getY();
}
}
class ScaleHandler implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider slider = (JSlider) e.getSource();
zoomPercent = slider.getValue();
// make sure zoom never gets to actual 0, or else the objects will
// disappear and the matrix will be non-invertible.
param.scaleY = Math.max(0.00001, zoomPercent) / 100.0;
param.scaleX = param.scaleY * param.stretchX;
canvas.repaint();
}
}
class HorizontalScaleHandler implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider slider = (JSlider) e.getSource();
double horizontalScalePercent = slider.getValue();
// make sure zoom never gets to actual 0, or else the objects will
// disappear and the matrix will be non-invertible.
param.stretchX = Math.max(0.15, horizontalScalePercent / 100.0);
param.scaleY = Math.max(0.00001, zoomPercent) / 100.0;
param.scaleX = param.scaleY * param.stretchX;
canvas.repaint();
}
}
}[/CODE]