org.jaitools.swing.SimpleImagePane Maven / Gradle / Ivy
Show all versions of jt-all Show documentation
/*
* Copyright (c) 2011, Michael Bedward. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jaitools.swing;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.image.RenderedImage;
import javax.swing.JPanel;
/**
* A basic Swing widget to display a {@code RenderedImage}. Used with JAITools
* example applications.
*
* @author Michael Bedward
* @since 1.1
* @version $Id$
*/
public class SimpleImagePane extends JPanel {
private RenderedImage image;
private AffineTransform imageToDisplay;
private AffineTransform displayToImage;
private int margin;
private final Object lock = new Object();
/**
* Creatss a new instance.
*/
public SimpleImagePane() {
margin = 0;
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent ce) {
setTransform();
}
});
}
/**
* Sets the image to display and repaints.
*
* @param image the image to display
*/
public void setImage(RenderedImage image) {
this.image = image;
setTransform();
repaint();
}
/**
* Removes the current display image and repaints.
*/
public void clear() {
image = null;
repaint();
}
/**
* Forces recalculation of the {@code AffineTransform} used to
* scale the image display.
*/
public void resetTransform() {
setTransform();
}
/**
* Converts a window position into the corresponding image position.
* If {@code imageCoords} is not {@code null} it will be set to the
* image position, otherwise a new {@code Point} object will be created.
* In either case, the image position is returned for convenience.
*
* If no image is currently set, {@code null} is returned.
*
* @param paneCoords window position
* @param imageCoords object to receive image position, or {@code null}
*
* @return image position or {@code null} if no image is set
*/
public Point getImageCoords(Point paneCoords, Point imageCoords) {
if (image != null) {
Point2D p = displayToImage.transform(paneCoords, null);
if (imageCoords != null) {
imageCoords.x = (int) p.getX();
imageCoords.y = (int) p.getY();
return imageCoords;
}
return new Point((int) p.getX(), (int) p.getY());
}
return null;
}
/**
* Converts an image position into the corresponding window position.
* If {@code paneCoords} is not {@code null} it will be set to the
* window position, otherwise a new {@code Point} object will be created.
* In either case, the window position is returned for convenience.
*
* If no image is currently set, {@code null} is returned.
*
* @param imageCoords image position
* @param paneCoords object to receive window position, or {@code null}
*
* @return window position or {@code null} if no image is set
*/
public Point getPaneCoords(Point imageCoords, Point paneCoords) {
if (image != null) {
Point2D p = imageToDisplay.transform(imageCoords, null);
if (paneCoords != null) {
paneCoords.x = (int) p.getX();
paneCoords.y = (int) p.getY();
return paneCoords;
}
return new Point((int) p.getX(), (int) p.getY());
}
return null;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
synchronized(lock) {
if (image != null) {
if (imageToDisplay == null) {
setTransform();
}
Graphics2D g2d = (Graphics2D) g;
g2d.drawRenderedImage(image, imageToDisplay);
}
}
}
private void setTransform() {
synchronized(lock) {
if (image != null) {
Rectangle visr = getVisibleRect();
if (visr.isEmpty()) {
return;
}
if (imageToDisplay == null) {
imageToDisplay = new AffineTransform();
}
double xscale = (visr.getWidth() - 2*margin) / image.getWidth();
double yscale = (visr.getHeight() - 2*margin) / image.getHeight();
double scale = Math.min(xscale, yscale);
double xoff = margin - (scale * image.getMinX());
double yoff = margin - (scale * image.getMinY());
imageToDisplay.setTransform(scale, 0, 0, scale, xoff, yoff);
try {
displayToImage = imageToDisplay.createInverse();
} catch (NoninvertibleTransformException ex) {
// we shouldn't ever be here
throw new RuntimeException(ex);
}
}
}
}
}