Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.awt.AWTEvent;
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.GraphicsEnvironment;
- import java.awt.Image;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.awt.RenderingHints;
- import java.awt.Toolkit;
- import java.awt.event.ComponentAdapter;
- import java.awt.event.ComponentEvent;
- import java.awt.event.MouseAdapter;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseMotionListener;
- import java.awt.event.MouseWheelEvent;
- import java.awt.event.MouseWheelListener;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.util.Arrays;
- import javax.imageio.ImageIO;
- import javax.swing.JFrame;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.SwingUtilities;
- /**
- * <p>
- * <code>NavigableImagePanel</code> is a lightweight container displaying
- * an image that can be zoomed in and out and panned with ease and simplicity,
- * using an adaptive rendering for high quality display and satisfactory performance.
- * </p>
- * <p>
- * <h3>Image</h3>
- * <p>An image is loaded either via a constructor:</p>
- * <pre>
- * NavigableImagePanel panel = new NavigableImagePanel(image);
- * </pre>
- * or using a setter:
- * <pre>
- * NavigableImagePanel panel = new NavigableImagePanel();
- * panel.setImage(image);
- * </pre>
- * When an image is set, it is initially painted centered in the component,
- * at the largest possible size, fully visible, with its aspect ratio is preserved.
- * This is defined as 100% of the image size and its corresponding zoom level is 1.0.
- * </p>
- * <h3>Zooming</h3>
- * <p>
- * Zooming can be controlled interactively, using either the mouse scroll wheel (default)
- * or the mouse two buttons, or programmatically, allowing the programmer to
- * implement other custom zooming methods. If the mouse does not have a scroll wheel,
- * set the zooming device to mouse buttons:
- * <pre>
- * panel.setZoomDevice(ZoomDevice.MOUSE_BUTTON);
- * </pre>
- * The left mouse button works as a toggle switch between zooming in and zooming out
- * modes, and the right button zooms an image by one increment (default is 20%).
- * You can change the zoom increment value by:
- * <pre>
- * panel.setZoomIncrement(newZoomIncrement);
- * </pre>
- * If you intend to provide programmatic zoom control, set the zoom device to none
- * to disable both the mouse wheel and buttons for zooming purposes:
- * <pre>
- * panel.setZoomDevice(ZoomDevice.NONE);
- * </pre>
- * and use <code>setZoom()</code> to change the zoom level.
- * </p>
- * <p>
- * Zooming is always around the point the mouse pointer is currently at, so that
- * this point (called a zooming center) remains stationary ensuring that the area
- * of an image we are zooming into does not disappear off the screen. The zooming center
- * stays at the same location on the screen and all other points move radially away from
- * it (when zooming in), or towards it (when zooming out). For programmatically
- * controlled zooming the zooming center is either specified when <code>setZoom()</code>
- * is called:
- * <pre>
- * panel.setZoom(newZoomLevel, newZoomingCenter);
- * </pre>
- * or assumed to be the point of an image which is
- * the closest to the center of the panel, if no zooming center is specified:
- * <pre>
- * panel.setZoom(newZoomLevel);
- * </pre>
- * </p>
- * <p>
- * There are no lower or upper zoom level limits.
- * </p>
- * <h3>Navigation</h3>
- * <p><code>NavigableImagePanel</code> does not use scroll bars for navigation,
- * but relies on a navigation image located in the upper left corner of the panel.
- * The navigation image is a small replica of the image displayed in the panel.
- * When you click on any point of the navigation image that part of the image
- * is displayed in the panel, centered. The navigation image can also be
- * zoomed in the same way as the main image.</p>
- * <p>In order to adjust the position of an image in the panel, it can be dragged
- * with the mouse, using the left button.
- * </p>
- * <p>For programmatic image navigation, disable the navigation image:
- * <pre>
- * panel.setNavigationImageEnabled(false)
- * </pre>
- * and use <code>getImageOrigin()</code> and
- * <code>setImageOrigin()</code> to move the image around the panel.
- * </p>
- * <h3>Rendering</h3>
- * <p><code>NavigableImagePanel</code> uses the Nearest Neighbor interpolation
- * for image rendering (default in Java).
- * When the scaled image becomes larger than the original image,
- * the Bilinear interpolation is applied, but only to the part
- * of the image which is displayed in the panel. This interpolation change threshold
- * can be controlled by adjusting the value of
- * <code>HIGH_QUALITY_RENDERING_SCALE_THRESHOLD</code>.</p>
- */
- public class NavigableImagePanel extends JPanel {
- /**
- * <p>Identifies a change to the zoom level.</p>
- */
- public static final String ZOOM_LEVEL_CHANGED_PROPERTY = "zoomLevel";
- /**
- * <p>Identifies a change to the zoom increment.</p>
- */
- public static final String ZOOM_INCREMENT_CHANGED_PROPERTY = "zoomIncrement";
- /**
- * <p>Identifies that the image in the panel has changed.</p>
- */
- public static final String IMAGE_CHANGED_PROPERTY = "image";
- private static final double SCREEN_NAV_IMAGE_FACTOR = 0.15; // 15% of panel's width
- private static final double NAV_IMAGE_FACTOR = 0.3; // 30% of panel's width
- private static final double HIGH_QUALITY_RENDERING_SCALE_THRESHOLD = 1.0;
- private static final Object INTERPOLATION_TYPE =
- RenderingHints.VALUE_INTERPOLATION_BILINEAR;
- private double zoomIncrement = 0.2;
- private double zoomFactor = 1.0 + zoomIncrement;
- private double navZoomFactor = 1.0 + zoomIncrement;
- private BufferedImage image;
- private BufferedImage navigationImage;
- private int navImageWidth;
- private int navImageHeight;
- private double initialScale = 0.0;
- private double scale = 0.0;
- private double navScale = 0.0;
- private int originX = 0;
- private int originY = 0;
- private Point mousePosition;
- private Dimension previousPanelSize;
- private boolean navigationImageEnabled = true;
- private boolean highQualityRenderingEnabled = true;
- private WheelZoomDevice wheelZoomDevice = null;
- private ButtonZoomDevice buttonZoomDevice = null;
- /**
- * <p>Defines zoom devices.</p>
- */
- public static class ZoomDevice {
- /**
- * <p>Identifies that the panel does not implement zooming,
- * but the component using the panel does (programmatic zooming method).</p>
- */
- public static final ZoomDevice NONE = new ZoomDevice("none");
- /**
- * <p>Identifies the left and right mouse buttons as the zooming device.</p>
- */
- public static final ZoomDevice MOUSE_BUTTON = new ZoomDevice("mouseButton");
- /**
- * <p>Identifies the mouse scroll wheel as the zooming device.</p>
- */
- public static final ZoomDevice MOUSE_WHEEL = new ZoomDevice("mouseWheel");
- private String zoomDevice;
- private ZoomDevice(String zoomDevice) {
- this.zoomDevice = zoomDevice;
- }
- public String toString() {
- return zoomDevice;
- }
- }
- //This class is required for high precision image coordinates translation.
- private class Coords {
- public double x;
- public double y;
- public Coords(double x, double y) {
- this.x = x;
- this.y = y;
- }
- public int getIntX() {
- return (int)Math.round(x);
- }
- public int getIntY() {
- return (int)Math.round(y);
- }
- public String toString() {
- return "[Coords: x=" + x + ",y=" + y + "]";
- }
- }
- private class WheelZoomDevice implements MouseWheelListener {
- public void mouseWheelMoved(MouseWheelEvent e) {
- Point p = e.getPoint();
- boolean zoomIn = (e.getWheelRotation() < 0);
- if (isInNavigationImage(p)) {
- if (zoomIn) {
- navZoomFactor = 1.0 + zoomIncrement;
- } else {
- navZoomFactor = 1.0 - zoomIncrement;
- }
- zoomNavigationImage();
- } else if (isInImage(p)) {
- if (zoomIn) {
- zoomFactor = 1.0 + zoomIncrement;
- } else {
- zoomFactor = 1.0 - zoomIncrement;
- }
- zoomImage();
- }
- }
- }
- private class ButtonZoomDevice extends MouseAdapter {
- public void mouseClicked(MouseEvent e) {
- Point p = e.getPoint();
- if (SwingUtilities.isRightMouseButton(e)) {
- if (isInNavigationImage(p)) {
- navZoomFactor = 1.0 - zoomIncrement;
- zoomNavigationImage();
- } else if (isInImage(p)) {
- zoomFactor = 1.0 - zoomIncrement;
- zoomImage();
- }
- } else {
- if (isInNavigationImage(p)) {
- navZoomFactor = 1.0 + zoomIncrement;
- zoomNavigationImage();
- } else if (isInImage(p)) {
- zoomFactor = 1.0 + zoomIncrement;
- zoomImage();
- }
- }
- }
- }
- /**
- * <p>Creates a new navigable image panel with no default image and
- * the mouse scroll wheel as the zooming device.</p>
- */
- public NavigableImagePanel() {
- setOpaque(false);
- addComponentListener(new ComponentAdapter() {
- public void componentResized(ComponentEvent e) {
- if (scale > 0.0) {
- if (isFullImageInPanel()) {
- centerImage();
- } else if (isImageEdgeInPanel()) {
- scaleOrigin();
- }
- if (isNavigationImageEnabled()) {
- createNavigationImage();
- }
- repaint();
- }
- previousPanelSize = getSize();
- }
- });
- addMouseListener(new MouseAdapter() {
- public void mousePressed(MouseEvent e) {
- if (SwingUtilities.isLeftMouseButton(e)) {
- if (isInNavigationImage(e.getPoint())) {
- Point p = e.getPoint();
- displayImageAt(p);
- }
- }
- }
- });
- addMouseMotionListener(new MouseMotionListener() {
- public void mouseDragged(MouseEvent e) {
- if (SwingUtilities.isLeftMouseButton(e)
- && !isInNavigationImage(e.getPoint())) {
- Point p = e.getPoint();
- moveImage(p);
- }
- }
- public void mouseMoved(MouseEvent e) {
- //we need the mouse position so that after zooming
- //that position of the image is maintained
- mousePosition = e.getPoint();
- }
- });
- setZoomDevice(ZoomDevice.MOUSE_WHEEL);
- }
- /**
- * <p>Creates a new navigable image panel with the specified image
- * and the mouse scroll wheel as the zooming device.</p>
- */
- public NavigableImagePanel(BufferedImage image) throws IOException {
- this();
- setImage(image);
- }
- private void addWheelZoomDevice() {
- if (wheelZoomDevice == null) {
- wheelZoomDevice = new WheelZoomDevice();
- addMouseWheelListener(wheelZoomDevice);
- }
- }
- private void addButtonZoomDevice() {
- if (buttonZoomDevice == null) {
- buttonZoomDevice = new ButtonZoomDevice();
- addMouseListener(buttonZoomDevice);
- }
- }
- private void removeWheelZoomDevice() {
- if (wheelZoomDevice != null) {
- removeMouseWheelListener(wheelZoomDevice);
- wheelZoomDevice = null;
- }
- }
- private void removeButtonZoomDevice() {
- if (buttonZoomDevice != null) {
- removeMouseListener(buttonZoomDevice);
- buttonZoomDevice = null;
- }
- }
- /**
- * <p>Sets a new zoom device.</p>
- *
- * @param newZoomDevice specifies the type of a new zoom device.
- */
- public void setZoomDevice(ZoomDevice newZoomDevice) {
- if (newZoomDevice == ZoomDevice.NONE) {
- removeWheelZoomDevice();
- removeButtonZoomDevice();
- } else if (newZoomDevice == ZoomDevice.MOUSE_BUTTON) {
- removeWheelZoomDevice();
- addButtonZoomDevice();
- } else if (newZoomDevice == ZoomDevice.MOUSE_WHEEL) {
- removeButtonZoomDevice();
- addWheelZoomDevice();
- }
- }
- /**
- * <p>Gets the current zoom device.</p>
- */
- public ZoomDevice getZoomDevice() {
- if (buttonZoomDevice != null) {
- return ZoomDevice.MOUSE_BUTTON;
- } else if (wheelZoomDevice != null) {
- return ZoomDevice.MOUSE_WHEEL;
- } else {
- return ZoomDevice.NONE;
- }
- }
- //Called from paintComponent() when a new image is set.
- private void initializeParams() {
- double xScale = (double)getWidth() / image.getWidth();
- double yScale = (double)getHeight() / image.getHeight();
- initialScale = Math.min(xScale, yScale);
- scale = initialScale;
- //An image is initially centered
- centerImage();
- if (isNavigationImageEnabled()) {
- createNavigationImage();
- }
- }
- //Centers the current image in the panel.
- private void centerImage() {
- originX = (int)(getWidth() - getScreenImageWidth()) / 2;
- originY = (int)(getHeight() - getScreenImageHeight()) / 2;
- }
- //Creates and renders the navigation image in the upper let corner of the panel.
- private void createNavigationImage() {
- //We keep the original navigation image larger than initially
- //displayed to allow for zooming into it without pixellation effect.
- navImageWidth = (int)(getWidth() * NAV_IMAGE_FACTOR);
- navImageHeight = navImageWidth * image.getHeight() / image.getWidth();
- int scrNavImageWidth = (int)(getWidth() * SCREEN_NAV_IMAGE_FACTOR);
- int scrNavImageHeight = scrNavImageWidth * image.getHeight() / image.getWidth();
- navScale = (double)scrNavImageWidth / navImageWidth;
- navigationImage = new BufferedImage(navImageWidth, navImageHeight,
- image.getType());
- Graphics g = navigationImage.getGraphics();
- g.drawImage(image, 0, 0, navImageWidth, navImageHeight, null);
- }
- /**
- * <p>Sets an image for display in the panel.</p>
- *
- * @param image an image to be set in the panel
- */
- public void setImage(BufferedImage image) {
- BufferedImage oldImage = this.image;
- this.image = image;
- //Reset scale so that initializeParameters() is called in paintComponent()
- //for the new image.
- scale = 0.0;
- firePropertyChange(IMAGE_CHANGED_PROPERTY, (Image)oldImage, (Image)image);
- repaint();
- }
- /**
- * <p>Tests whether an image uses the standard RGB color space.</p>
- */
- public static boolean isStandardRGBImage(BufferedImage bImage) {
- return bImage.getColorModel().getColorSpace().isCS_sRGB();
- }
- //Converts this panel's coordinates into the original image coordinates
- private Coords panelToImageCoords(Point p) {
- return new Coords((p.x - originX) / scale, (p.y - originY) / scale);
- }
- //Converts the original image coordinates into this panel's coordinates
- private Coords imageToPanelCoords(Coords p) {
- return new Coords((p.x * scale) + originX, (p.y * scale) + originY);
- }
- //Converts the navigation image coordinates into the zoomed image coordinates
- private Point navToZoomedImageCoords(Point p) {
- int x = p.x * getScreenImageWidth() / getScreenNavImageWidth();
- int y = p.y * getScreenImageHeight() / getScreenNavImageHeight();
- return new Point(x, y);
- }
- //The user clicked within the navigation image and this part of the image
- //is displayed in the panel.
- //The clicked point of the image is centered in the panel.
- private void displayImageAt(Point p) {
- Point scrImagePoint = navToZoomedImageCoords(p);
- originX = -(scrImagePoint.x - getWidth() / 2);
- originY = -(scrImagePoint.y - getHeight() / 2);
- repaint();
- }
- //Tests whether a given point in the panel falls within the image boundaries.
- private boolean isInImage(Point p) {
- Coords coords = panelToImageCoords(p);
- int x = coords.getIntX();
- int y = coords.getIntY();
- return (x >= 0 && x < image.getWidth() && y >= 0 && y < image.getHeight());
- }
- //Tests whether a given point in the panel falls within the navigation image
- //boundaries.
- private boolean isInNavigationImage(Point p) {
- return (isNavigationImageEnabled() && p.x < getScreenNavImageWidth()
- && p.y < getScreenNavImageHeight());
- }
- //Used when the image is resized.
- private boolean isImageEdgeInPanel() {
- if (previousPanelSize == null) {
- return false;
- }
- return (originX > 0 && originX < previousPanelSize.width
- || originY > 0 && originY < previousPanelSize.height);
- }
- //Tests whether the image is displayed in its entirety in the panel.
- private boolean isFullImageInPanel() {
- return (originX >= 0 && (originX + getScreenImageWidth()) < getWidth()
- && originY >= 0 && (originY + getScreenImageHeight()) < getHeight());
- }
- /**
- * <p>Indicates whether the high quality rendering feature is enabled.</p>
- *
- * @return true if high quality rendering is enabled, false otherwise.
- */
- public boolean isHighQualityRenderingEnabled() {
- return highQualityRenderingEnabled;
- }
- /**
- * <p>Enables/disables high quality rendering.</p>
- *
- * @param enabled enables/disables high quality rendering
- */
- public void setHighQualityRenderingEnabled(boolean enabled) {
- highQualityRenderingEnabled = enabled;
- }
- //High quality rendering kicks in when when a scaled image is larger
- //than the original image. In other words,
- //when image decimation stops and interpolation starts.
- private boolean isHighQualityRendering() {
- return (highQualityRenderingEnabled
- && scale > HIGH_QUALITY_RENDERING_SCALE_THRESHOLD);
- }
- /**
- * <p>Indicates whether navigation image is enabled.<p>
- *
- * @return true when navigation image is enabled, false otherwise.
- */
- public boolean isNavigationImageEnabled() {
- return navigationImageEnabled;
- }
- /**
- * <p>Enables/disables navigation with the navigation image.</p>
- * <p>Navigation image should be disabled when custom, programmatic navigation
- * is implemented.</p>
- *
- * @param enabled true when navigation image is enabled, false otherwise.
- */
- public void setNavigationImageEnabled(boolean enabled) {
- navigationImageEnabled = enabled;
- repaint();
- }
- //Used when the panel is resized
- private void scaleOrigin() {
- originX = originX * getWidth() / previousPanelSize.width;
- originY = originY * getHeight() / previousPanelSize.height;
- repaint();
- }
- //Converts the specified zoom level to scale.
- private double zoomToScale(double zoom) {
- return initialScale * zoom;
- }
- /**
- * <p>Gets the current zoom level.</p>
- *
- * @return the current zoom level
- */
- public double getZoom() {
- return scale / initialScale;
- }
- /**
- * <p>Sets the zoom level used to display the image.</p>
- * <p>This method is used in programmatic zooming. The zooming center is
- * the point of the image closest to the center of the panel.
- * After a new zoom level is set the image is repainted.</p>
- *
- * @param newZoom the zoom level used to display this panel's image.
- */
- public void setZoom(double newZoom) {
- Point zoomingCenter = new Point(getWidth() / 2, getHeight() / 2);
- setZoom(newZoom, zoomingCenter);
- }
- /**
- * <p>Sets the zoom level used to display the image, and the zooming center,
- * around which zooming is done.</p>
- * <p>This method is used in programmatic zooming.
- * After a new zoom level is set the image is repainted.</p>
- *
- * @param newZoom the zoom level used to display this panel's image.
- */
- public void setZoom(double newZoom, Point zoomingCenter) {
- Coords imageP = panelToImageCoords(zoomingCenter);
- if (imageP.x < 0.0) {
- imageP.x = 0.0;
- }
- if (imageP.y < 0.0) {
- imageP.y = 0.0;
- }
- if (imageP.x >= image.getWidth()) {
- imageP.x = image.getWidth() - 1.0;
- }
- if (imageP.y >= image.getHeight()) {
- imageP.y = image.getHeight() - 1.0;
- }
- Coords correctedP = imageToPanelCoords(imageP);
- double oldZoom = getZoom();
- scale = zoomToScale(newZoom);
- Coords panelP = imageToPanelCoords(imageP);
- originX += (correctedP.getIntX() - (int)panelP.x);
- originY += (correctedP.getIntY() - (int)panelP.y);
- firePropertyChange(ZOOM_LEVEL_CHANGED_PROPERTY, new Double(oldZoom),
- new Double(getZoom()));
- repaint();
- }
- /**
- * <p>Gets the current zoom increment.</p>
- *
- * @return the current zoom increment
- */
- public double getZoomIncrement() {
- return zoomIncrement;
- }
- /**
- * <p>Sets a new zoom increment value.</p>
- *
- * @param newZoomIncrement new zoom increment value
- */
- public void setZoomIncrement(double newZoomIncrement) {
- double oldZoomIncrement = zoomIncrement;
- zoomIncrement = newZoomIncrement;
- firePropertyChange(ZOOM_INCREMENT_CHANGED_PROPERTY,
- new Double(oldZoomIncrement), new Double(zoomIncrement));
- }
- //Zooms an image in the panel by repainting it at the new zoom level.
- //The current mouse position is the zooming center.
- private void zoomImage() {
- Coords imageP = panelToImageCoords(mousePosition);
- double oldZoom = getZoom();
- scale *= zoomFactor;
- Coords panelP = imageToPanelCoords(imageP);
- originX += (mousePosition.x - (int)panelP.x);
- originY += (mousePosition.y - (int)panelP.y);
- firePropertyChange(ZOOM_LEVEL_CHANGED_PROPERTY, new Double(oldZoom),
- new Double(getZoom()));
- repaint();
- }
- //Zooms the navigation image
- private void zoomNavigationImage() {
- navScale *= navZoomFactor;
- repaint();
- }
- /**
- * <p>Gets the image origin.</p>
- * <p>Image origin is defined as the upper, left corner of the image in
- * the panel's coordinate system.</p>
- * @return the point of the upper, left corner of the image in the panel's coordinates
- * system.
- */
- public Point getImageOrigin() {
- return new Point(originX, originY);
- }
- /**
- * <p>Sets the image origin.</p>
- * <p>Image origin is defined as the upper, left corner of the image in
- * the panel's coordinate system. After a new origin is set, the image is repainted.
- * This method is used for programmatic image navigation.</p>
- * @param x the x coordinate of the new image origin
- * @param y the y coordinate of the new image origin
- */
- public void setImageOrigin(int x, int y) {
- setImageOrigin(new Point(x, y));
- }
- /**
- * <p>Sets the image origin.</p>
- * <p>Image origin is defined as the upper, left corner of the image in
- * the panel's coordinate system. After a new origin is set, the image is repainted.
- * This method is used for programmatic image navigation.</p>
- * @param newOrigin the value of a new image origin
- */
- public void setImageOrigin(Point newOrigin) {
- originX = newOrigin.x;
- originY = newOrigin.y;
- repaint();
- }
- //Moves te image (by dragging with the mouse) to a new mouse position p.
- private void moveImage(Point p) {
- int xDelta = p.x - mousePosition.x;
- int yDelta = p.y - mousePosition.y;
- originX += xDelta;
- originY += yDelta;
- mousePosition = p;
- repaint();
- }
- //Gets the bounds of the image area currently displayed in the panel (in image
- //coordinates).
- private Rectangle getImageClipBounds() {
- Coords startCoords = panelToImageCoords(new Point(0, 0));
- Coords endCoords = panelToImageCoords(new Point(getWidth() - 1, getHeight() - 1));
- int panelX1 = startCoords.getIntX();
- int panelY1 = startCoords.getIntY();
- int panelX2 = endCoords.getIntX();
- int panelY2 = endCoords.getIntY();
- //No intersection?
- if (panelX1 >= image.getWidth() || panelX2 < 0 || panelY1 >= image.getHeight() || panelY2 < 0) {
- return null;
- }
- int x1 = (panelX1 < 0) ? 0 : panelX1;
- int y1 = (panelY1 < 0) ? 0 : panelY1;
- int x2 = (panelX2 >= image.getWidth()) ? image.getWidth() - 1 : panelX2;
- int y2 = (panelY2 >= image.getHeight()) ? image.getHeight() - 1 : panelY2;
- return new Rectangle(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
- }
- /**
- * Paints the panel and its image at the current zoom level, location, and
- * interpolation method dependent on the image scale.</p>
- *
- * @param g the <code>Graphics</code> context for painting
- */
- protected void paintComponent(Graphics g) {
- super.paintComponent(g); // Paints the background
- if (image == null) {
- return;
- }
- if (scale == 0.0) {
- initializeParams();
- }
- if (isHighQualityRendering()) {
- Rectangle rect = getImageClipBounds();
- if (rect == null || rect.width == 0 || rect.height == 0) { // no part of image is displayed in the panel
- return;
- }
- BufferedImage subimage = image.getSubimage(rect.x, rect.y, rect.width,
- rect.height);
- Graphics2D g2 = (Graphics2D)g;
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, INTERPOLATION_TYPE);
- g2.drawImage(subimage, Math.max(0, originX), Math.max(0, originY),
- Math.min((int)(subimage.getWidth() * scale), getWidth()),
- Math.min((int)(subimage.getHeight() * scale), getHeight()), null);
- } else {
- g.drawImage(image, originX, originY, getScreenImageWidth(),
- getScreenImageHeight(), null);
- }
- //Draw navigation image
- if (isNavigationImageEnabled()) {
- g.drawImage(navigationImage, 0, 0, getScreenNavImageWidth(),
- getScreenNavImageHeight(), null);
- drawZoomAreaOutline(g);
- }
- }
- //Paints a white outline over the navigation image indicating
- //the area of the image currently displayed in the panel.
- private void drawZoomAreaOutline(Graphics g) {
- if (isFullImageInPanel()) {
- return;
- }
- int x = -originX * getScreenNavImageWidth() / getScreenImageWidth();
- int y = -originY * getScreenNavImageHeight() / getScreenImageHeight();
- int width = getWidth() * getScreenNavImageWidth() / getScreenImageWidth();
- int height = getHeight() * getScreenNavImageHeight() / getScreenImageHeight();
- g.setColor(Color.white);
- g.drawRect(x, y, width, height);
- }
- private int getScreenImageWidth() {
- return (int)(scale * image.getWidth());
- }
- private int getScreenImageHeight() {
- return (int)(scale * image.getHeight());
- }
- private int getScreenNavImageWidth() {
- return (int)(navScale * navImageWidth);
- }
- private int getScreenNavImageHeight() {
- return (int)(navScale * navImageHeight);
- }
- private static String[] getImageFormatExtensions() {
- String[] names = ImageIO.getReaderFormatNames();
- for(int i = 0; i < names.length; i++) {
- names[i] = names[i].toLowerCase();
- }
- Arrays.sort(names);
- return names;
- }
- private static boolean endsWithImageFormatExtension(String name) {
- int dotIndex = name.lastIndexOf(".");
- if (dotIndex == -1) {
- return false;
- }
- String extension = name.substring(dotIndex + 1).toLowerCase();
- return (Arrays.binarySearch(getImageFormatExtensions(), extension) >= 0);
- }
- public static void main(String[] args) {
- if (args.length == 0) {
- System.out.println("Usage: java NavigableImagePanel imageFilename");
- System.exit(1);
- }
- final String filename = args[0];
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- final JFrame frame = new JFrame("Navigable Image Panel");
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- NavigableImagePanel panel = new NavigableImagePanel();
- try {
- final BufferedImage image = ImageIO.read(new File(filename));
- panel.setImage(image);
- } catch (IOException e) {
- JOptionPane.showMessageDialog(null, e.getMessage(), "",
- JOptionPane.ERROR_MESSAGE);
- System.exit(1);
- }
- frame.getContentPane().add(panel, BorderLayout.CENTER);
- GraphicsEnvironment ge =
- GraphicsEnvironment.getLocalGraphicsEnvironment();
- Rectangle bounds = ge.getMaximumWindowBounds();
- frame.setSize(new Dimension(bounds.width, bounds.height));
- frame.setVisible(true);
- }
- });
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement