All Implemented Interfaces:
ImageObserver, MenuContainer, Serializable, Accessible

public final class ImagePanel extends JPanel
ImagePanel 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:

 ImagePanel panel = ImagePanel.builder()
     .image(bufferedImage)
     .build();

 // Or change the image reactively
 panel.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:
 ImagePanel panel = ImagePanel.builder()
     .zoomDevice(ZoomDevice.MOUSE_BUTTON)
     .build();

 // Or change reactively
 panel.zoomDevice().set(ZoomDevice.NONE);
 
When using ZoomDevice.MOUSE_BUTTON, the left mouse button toggles between zooming in and out modes, and the right button zooms by one increment (default 20%). The zoom increment can be controlled:
 panel.zoomIncrement().set(0.3); // 30% increment
 
For programmatic zoom control, set the zoom device to ZoomDevice.NONE and use the zoom() Value:
 panel.zoom().set(2.0); // Zoom to 200%
 
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 panel.

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

 ImagePanel panel = ImagePanel.builder()
     .autoResize(true)
     .build();

 // Or toggle reactively
 panel.autoResize().set(true);
 
When auto-resize is enabled, the image will reset to fit the panel 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 ImagePanel 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 panel, centered. The navigation image can be enabled/disabled via the navigable() State:
 ImagePanel panel = ImagePanel.builder()
     .navigable(true)
     .build();

 // Or toggle reactively
 panel.navigable().set(false);
 
The image can be dragged with the left mouse button when movable() is enabled (default):
 panel.movable().set(false); // Disable dragging
 
For programmatic navigation, use centerImage(Point) or centerImage(Point2D.Double). Coordinate Conversion The panel provides methods to convert between panel coordinates and image coordinates: Rendering ImagePanel 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 panel. Custom Overlays The panel supports custom overlay painting via a BiConsumer<Graphics2D, ImagePanel> that is called after the image is painted but before the navigation image. This is useful for drawing annotations, grids, highlighting regions, or any custom graphics on top of the image:
 ImagePanel imagePanel = ImagePanel.builder()
     .image(image)
     .overlay((g2d, panel) -> {
         // Draw a red rectangle at image coordinates (100, 100)
         Point2D.Double imagePoint = new Point2D.Double(100, 100);
         Point2D.Double panelPoint = panel.toPanelCoordinates(imagePoint);
         g2d.setColor(Color.RED);
         g2d.drawRect((int) panelPoint.x, (int) panelPoint.y, 50, 50);
     })
     .build();
 
The overlay painter receives the Graphics2D context for drawing and the ImagePanel for accessing coordinate conversion methods (toImageCoordinates(Point) and toPanelCoordinates(Point2D.Double)) and other panel state like scale().

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

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

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

 ImagePanel imagePanel = ImagePanel.builder()
     .image(image)
     .zoomDevice(ZoomDevice.MOUSE_WHEEL)
     .autoResize(true)
     .navigable(true)
     .movable(true)
     .overlay((g2d, panel) -> {
         // Draw custom annotations
         g2d.setColor(new Color(255, 0, 0, 128));
         g2d.fillOval(100, 100, 50, 50);
     })
     .build();

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

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

 // Change image dynamically
 panel.image().set(newImage);

 // Position image to show specific region
 panel.origin().set(new Point(-100, -50));
 

Originally based on http://today.java.net/pub/a/today/2007/03/27/navigable-image-panel.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 ImagePanel.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 ImagePanel.ImageValue.set(BufferedImage, String)
      Returns:
      the ImagePanel.ImageValue controlling the image
    • zoomDevice

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

      public State autoResize()
      Returns the State controlling whether the image automatically re-fits to the panel on resize. When enabled, the image will reset to fit the panel dimensions whenever the panel 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 panel
    • zoomIncrement

      public Value<Double> zoomIncrement()
      Returns:
      the Value controlling the zoom increment
    • zoom

      public Value<Double> zoom()
      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 panel coordinates). This can be used to programmatically position the image within the panel.

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

       // Move image to show a region at image coordinates (500, 300)
       Point2D.Double imagePoint = new Point2D.Double(500, 300);
       Point2D.Double panelPoint = panel.toPanelCoordinates(imagePoint);
      
       // Center that point in the panel
       int centerX = panel.getWidth() / 2;
       int centerY = panel.getHeight() / 2;
       panel.origin().set(new Point(
           centerX - (int) panelPoint.x,
           centerY - (int) panelPoint.y));
      
       // React to origin changes (e.g., when user drags the image)
       panel.origin().addConsumer(origin ->
           updateVisibleRegionIndicator(origin));
       
      Returns:
      the Value controlling the image origin in panel coordinates
    • scale

      public double scale()
      Returns:
      the current scale
    • reset

      public void reset()
      Resets the view so the image is centered and fits the panel
    • toImageCoordinates

      public Point2D.Double toImageCoordinates(Point panelCoordinates)
      Converts this panel's point into the original image coordinates
      Parameters:
      panelCoordinates - the panel coordinates
      Returns:
      the image coordinates
    • toPanelCoordinates

      public Point2D.Double toPanelCoordinates(Point2D.Double imageCoordinates)
      Converts the original image point into this panel's coordinates
      Parameters:
      imageCoordinates - the image coordinates
      Returns:
      the panel coordinates
    • centerImage

      public void centerImage(Point2D.Double imagePoint)
      Centers the image on the given image point
      Parameters:
      imagePoint - the image point on which to center the image
    • centerImage

      public void centerImage(Point panelPoint)
      Centers the image on the given point on the panel, if it is within the image boundaries.
      Parameters:
      panelPoint - the point on which to center the image
    • isWithinImage

      public boolean isWithinImage(Point panelPoint)
      Tests whether a given point in the panel falls within the image boundaries.
      Parameters:
      panelPoint - the point on the panel
      Returns:
      true if an image is available and the given point is within the image
    • 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 ImagePanel.Builder builder()
      Returns:
      a new ImagePanel.Builder instance
    • paintComponent

      protected void paintComponent(Graphics g)
      Paints the panel 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