/* JAI-Ext - OpenSource Java Advanced Image Extensions Library * http://www.geo-solutions.it/ * Copyright 2014 GeoSolutions * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.geosolutions.rendered.viewer; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.image.RenderedImage; import javax.swing.JPanel; /** * Simple viwer for rendered images, allows for zoom in/out, tile grid display * * @author Andrea Aime * */ class ZoomableImageDisplay extends JPanel { /** The image to display. */ protected RenderedImage image; protected double scale = 1.0; protected boolean tileGridVisible = true; /** * Constructs a <code>DisplayJAI</code> and sets its the layout to * <code>null</code>. */ public ZoomableImageDisplay() { setLayout(null); } /** * Constructs a <code>DisplayJAI</code>, sets its layout to * <code>null</code>, and sets its displayed image. * * <p> * The preferred size is set such that its width is the image width plus the * left and right insets and its height is the image height plus the top and * bottom insets. * </p> * * @param image * The image to display. * @throws IllegalArgumentException * if <code>image</code> is <code>null</code>. */ public ZoomableImageDisplay(RenderedImage image) { this(); setImage(image); } public void setScale(double scale) { if (scale <= 0) { throw new IllegalArgumentException("Scale must be a positive number"); } this.scale = scale; refreshComponent(); } public double getScale() { return scale; } /** * Sets a new image to display. * * @param image * The image to display. * @throws IllegalArgumentException * if <code>im</code> is <code>null</code>. */ public void setImage(RenderedImage image) { if (image == null) { throw new IllegalArgumentException("Image displayed cannot be null"); } this.image = image; refreshComponent(); } public RenderedImage getImage() { return image; } private void refreshComponent() { int w = (int) Math.ceil(image.getWidth() * scale); int h = (int) Math.ceil(image.getHeight() * scale); int minX = (int) Math.ceil(image.getMinX() * scale); int minY = (int) Math.ceil(image.getMinY() * scale); Insets insets = getInsets(); Dimension dim = new Dimension(w + insets.left + insets.right + minX, h + insets.top + insets.bottom + minY); setPreferredSize(dim); revalidate(); repaint(); } @Override public synchronized void paintComponent(Graphics g) { if (g instanceof Graphics2D) { Graphics2D g2d = (Graphics2D) g; // clear damaged area Rectangle clipBounds = g2d.getClipBounds(); g2d.setColor(getBackground()); g2d.fillRect(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height); if (image == null) { return; } // Translation moves the entire image within the container try { g2d.drawRenderedImage(image, AffineTransform.getScaleInstance(scale, scale)); } catch (Throwable e) { e.printStackTrace(); } if (tileGridVisible) { g2d.setColor(Color.WHITE); g2d.setXORMode(Color.BLACK); // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP)); final int x = (int) Math.floor(image.getTileGridXOffset() * scale); final int y = (int) Math.floor(image.getTileGridYOffset() * scale); final int th = (int) Math.round(image.getTileHeight() * scale); final int tw = (int) Math.round(image.getTileWidth() * scale); final int xCount = image.getNumXTiles(); final int yCount = image.getNumYTiles(); final int minty = image.getMinTileY(); final int mintx = image.getMinTileX(); for (int i = mintx; i < (xCount + mintx + 1); i++) { g2d.drawLine(x + (tw * i), y + (th * minty), x + (tw * i), y + (th * (yCount + minty))); } for (int j = minty; j < (yCount + minty + 1); j++) { g2d.drawLine(x + (mintx * tw), y + (th * j), x + (tw * (xCount + mintx)), y + (th * j)); } } } } public boolean isTileGridVisible() { return tileGridVisible; } public void setTileGridVisible(boolean visible) { this.tileGridVisible = visible; repaint(); } }