/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2010-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2010-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.gui.swing.coverage; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import java.util.concurrent.atomic.AtomicReference; import org.opengis.coverage.grid.GridCoverage; import org.geotoolkit.coverage.grid.GridCoverage2D; import org.geotoolkit.coverage.grid.ViewType; import org.geotoolkit.coverage.io.GridCoverageReader; import org.geotoolkit.coverage.io.GridCoverageReadParam; import org.geotoolkit.coverage.io.ImageReaderAdapter; import org.geotoolkit.coverage.io.CoverageStoreException; import org.geotoolkit.coverage.sql.GridCoverageReference; import org.geotoolkit.gui.swing.image.ImageFileProperties; /** * A panel showing the properties of a coverage file. This widget is similar to * {@link ImageFileProperties}, except that it uses a {@link GridCoverageReader} * for loading the image instead than an {@link javax.imageio.ImageReader}. * * @author Martin Desruisseaux (Geomatys) * @version 3.14 * * @since 3.14 * @module */ @SuppressWarnings("serial") public class CoverageFileProperties extends ImageFileProperties { /** * The image reader used in the last call to {@link #setImageInput(Object)}, or * {@code null} if none. Note that this field is typically read and written from * a background thread. */ private final AtomicReference<Adapter> imageReader = new AtomicReference<>(); /** * The adapter used for wrapping {@link GridCoverageReader} as an {@link ImageReader}. * * @author Martin Desruisseaux (Geomatys) * @version 3.14 * * @since 3.14 * @module */ private static final class Adapter extends ImageReaderAdapter { /** * Creates a new adapter for the given reader. */ Adapter(final GridCoverageReader reader) { super(reader); } /** * Returns the wrapped reader. */ GridCoverageReader getReader() { return reader; } /** * Returns an adapter for the given reader. This method returns {@code this} * if this adapter is still applicable, or a new adapter otherwise. */ Adapter setReader(final GridCoverageReader reader) { return (this.reader == reader) ? this : new Adapter(reader); } /** * Reads the coverage at the given index and returns its rendered view. The use * of {@link ViewType#RENDERED} allows better rendering in the overview pane. */ @Override protected GridCoverage read(final int index, final GridCoverageReadParam param) throws IOException { GridCoverage coverage = super.read(index, param); if (coverage instanceof GridCoverage2D) { coverage = ((GridCoverage2D) coverage).view(ViewType.RENDERED); } return coverage; } } /** * Creates a new instance of {@code ImageFileProperties} with no image. One of * {@link #setImage(File) setImage(...)} methods must be invoked in order to set * the properties source. */ public CoverageFileProperties() { } /** * Sets the specified coverage reference as the source of metadata and thumbnails. * This method accepts the following kind of inputs: * <p> * <ul> * <li>{@link GridCoverageReference}</li> * <li>{@link GridCoverageReader} with its input set (see <cite>Resources management</cite> below).</li> * <li>{@link ImageReader} with its input set (see <cite>Resources management</cite> below).</li> * <li>Paths as {@link java.io.File}, {@link java.net.URL}, <i>etc.</i></li> * </ul> * * {@section Resources management} * If an {@code GridCoverageReader} or {@code ImageReader} is given to this method, and if the * reader uses an {@linkplain javax.imageio.stream.ImageInputStream Image Input Stream} or other * kind of {@linkplain java.io.Closeable closeable} input, then note that this method does * <strong>not</strong> close such input. It is caller responsibility to close the reader * input after this method call. */ @Override public void setImageInput(Object input) throws IOException { if (input instanceof GridCoverageReference) { /* * Get the GridCoverageReader. The existing instance will be recycled if * possible, provided that it is not an instance provided by the user. */ Adapter adapter = imageReader.getAndSet(null); try { GridCoverageReader reader = (adapter != null) ? adapter.getReader() : null; try { reader = ((GridCoverageReference) input).getCoverageReader(reader); } catch (CoverageStoreException e) { final Throwable cause = e.getCause(); if (cause instanceof IOException) { throw (IOException) cause; } throw new IIOException(e.getLocalizedMessage(), e); } adapter = (adapter != null) ? adapter.setReader(reader) : new Adapter(reader); adapter.setInput(input); super.setImageInput(adapter); adapter.setInput(null); // Close the input stream. } finally { imageReader.compareAndSet(null, adapter); } } else { if (input instanceof GridCoverageReader) { input = new Adapter((GridCoverageReader) input); } super.setImageInput(input); } } }