All Implemented Interfaces:
ImageObserver, MenuContainer, Serializable, Accessible

public final class ImagePane extends JPanel
ImagePane is a lightweight container displaying an image that can be zoomed in and out and panned with ease and simplicity, using adaptive rendering for high quality display and satisfactory performance.

All configuration is done via an Observable/Value-based API, allowing reactive UI updates. Image

An image is loaded via the builder or controlled via the image() Value:

ImagePane pane = ImagePane.builder()
				.image(bufferedImage)
				.build();

// Or change the image reactively
pane.image().set(newImage);
When an image is set, it is initially painted centered in the component at the largest possible size, fully visible, with its aspect ratio preserved. This is defined as 100% of the image size and its corresponding zoom level is 1.0. Zooming Zooming can be controlled interactively using either the mouse scroll wheel (default) or mouse buttons, or programmatically via the zoom() Value. To change the zoom device:
ImagePane pane = ImagePane.builder()
				.zoomDevice(ZoomDevice.MOUSE_BUTTON)
				.build();

// Or change reactively
pane.zoomDevice().set(ZoomDevice.NONE);
When using ZoomDevice.MOUSE_BUTTON, the left mouse button zooms in and the right button zooms out. Each step zooms by one increment (default 20%), zooming in multiplying the zoom level by 1 + increment and zooming out dividing it, so zooming in and back out returns to the same level. The zoom increment can be controlled:
pane.zoomIncrement().set(0.3); // 30% increment
For programmatic zoom control, set the zoom device to ZoomDevice.NONE and use the zoom() Value:
pane.zoom().set(2.0); // Zoom to 200%
The zoom level, like the coordinate translation, is available once an image is set and the pane has a size, it need not have been painted. Mouse wheel zooming is always around the point the mouse pointer is currently at, ensuring that the area being zoomed into remains visible. Programmatic zooming via zoom().set() zooms around the center of the pane.

There are no lower or upper zoom level limits. Auto-Resize When auto-resize is enabled, the image automatically re-fits to the pane whenever the pane is resized:

ImagePane pane = ImagePane.builder()
				.autoResize(true)
				.build();

// Or toggle reactively
pane.autoResize().set(true);
When auto-resize is enabled, the image will reset to fit the pane dimensions on every resize event, regardless of the current zoom level. This is useful for responsive layouts where you want the image to always fill the available space. Navigation ImagePane does not use scroll bars for navigation, but can optionally display a navigation image in the upper left corner. The navigation image is a small replica of the main image. Clicking on any point of the navigation image displays that part of the image in the pane, centered. The navigation image can be enabled/disabled via the navigable() State:
ImagePane pane = ImagePane.builder()
				.navigable(true)
				.build();

// Or toggle reactively
pane.navigable().set(false);
The image can be dragged with the left mouse button when movable() is enabled (default):
pane.movable().set(false); // Disable dragging
For programmatic navigation, use center(). Coordinate Conversion The pane provides coordinate translation between pane and image coordinate spaces via coordinates(). Use this for overlay drawing or when working with mouse events on the image. Rendering ImagePane uses Nearest Neighbor interpolation for image rendering (default in Java). When the scaled image becomes larger than the original image, Bilinear interpolation is applied, but only to the part of the image displayed in the pane. Custom Overlays The pane supports custom overlay painting for drawing annotations, grids, highlights, or any custom graphics on top of the image. See ImagePane.Builder.overlay(BiConsumer) for details.

The origin() Value provides access to the current image origin (top-left corner position in pane coordinates), which can be used to programmatically position the image to make specific regions visible:

// Move image to show a specific region
pane.origin().set(new Point(-200, -100));

// React to origin changes
pane.origin().addConsumer(origin ->
				System.out.println("Image origin: " + origin));
Example Usage
BufferedImage image = ImageIO.read(new File("photo.jpg"));

ImagePane pane = ImagePane.builder()
				.image(image)
				.zoomDevice(ZoomDevice.MOUSE_WHEEL)
				.autoResize(true)
				.navigable(true)
				.movable(true)
				.build();

// Coordinate translation
Point2D.Double imagePoint = pane.coordinates().toImage(mouseEvent.getPoint());

// Center image on a specific point
pane.center().onImage(new Point2D.Double(500, 300));

// Programmatic zoom
pane.zoom().set(1.5);

// React to zoom changes
pane.zoom().addConsumer(zoom ->
				System.out.println("Zoom level: " + zoom));

Originally based on http://today.java.net/pub/a/today/2007/03/27/navigable-image-pane.html Included with express permission from the author, 2019.

Author:
Slav Boleslawski, Björn Darri Sigurðsson
See Also:
  • Field Details

  • Method Details

    • image

      public ImagePane.ImageValue image()
      Note that setting the image via this value without specifying the format does not populate the associated byte[] ComponentValue, for that to happen you must use ImagePane.ImageValue.set(BufferedImage, String)
      Returns:
      the ImagePane.ImageValue controlling the image
    • zoomDevice

      public Value<ImagePane.ZoomDevice> zoomDevice()
      Returns:
      the Value controlling the active ImagePane.ZoomDevice
    • autoResize

      public State autoResize()
      Returns the State controlling whether the image automatically re-fits to the pane on resize. When enabled, the image will reset to fit the pane dimensions whenever the pane is resized, regardless of the current zoom level.
      Returns:
      the State controlling the auto-resize behavior
    • movable

      public State movable()
      Returns:
      the State controlling whether the image is movable within the pane
    • zoomIncrement

      public Value<Double> zoomIncrement()
      Returns the Value controlling the zoom increment, a non-negative number, zooming in multiplying the zoom level by 1 + increment and zooming out dividing it.
      Returns:
      the Value controlling the zoom increment
    • zoom

      public Value<Double> zoom()
      Returns the Value controlling the zoom level, 1.0 being the image fitted to the pane. The zoom level must be positive, setting it to null sets it to 1.0. The zoom level is 0 while no image is set or the pane has no size, and setting it then throws IllegalStateException.
      Returns:
      the Value controlling the current zoom level
    • origin

      public Value<Point> origin()
      Returns the Value controlling the image origin (the position of the image's top-left corner in pane coordinates). This can be used to programmatically position the image within the pane.

      The origin is typically negative when the image is zoomed in and larger than the pane, representing how much of the image is scrolled off the top-left edge of the pane. Example Usage

      // Center image coordinates (500, 300) in the pane, as center().onImage() does
      Point2D.Double panePoint = pane.coordinates().toPane(new Point2D.Double(500, 300));
      Point origin = pane.origin().getOrThrow();
      pane.origin().set(new Point(
      				origin.x + pane.getWidth() / 2 - (int) panePoint.x,
      				origin.y + pane.getHeight() / 2 - (int) panePoint.y));
      
      // React to origin changes (e.g., when user drags the image)
      pane.origin().addConsumer(this::updateVisibleRegionIndicator);
      Returns:
      the Value controlling the image origin in pane coordinates
    • scale

      public double scale()
      Returns:
      the current scale, 0 while no image is set or the pane has no size
    • reset

      public void reset()
      Resets the view so the image is centered and fits the pane
    • coordinates

      public ImagePane.CoordinateTranslator coordinates()
      Returns:
      the coordinate translator
    • center

      public ImagePane.CenterImage center()
      Returns:
      image centerer
    • readImage

      public static BufferedImage readImage(String imagePath) throws IOException
      Reads an image from the given path
      Parameters:
      imagePath - the path, either file or http
      Returns:
      the loaded image
      Throws:
      IOException - in case of an exception
    • builder

      public static ImagePane.Builder builder()
      Returns:
      a new ImagePane.Builder instance
    • paintComponent

      protected void paintComponent(Graphics g)
      Paints the pane and its image at the current zoom level, location, and interpolation method dependent on the image scale.
      Overrides:
      paintComponent in class JComponent
      Parameters:
      g - the Graphics context for painting