/* (c) 2014-2015 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wms.map; import java.awt.image.RenderedImage; import java.io.IOException; import java.io.OutputStream; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import org.geoserver.platform.ServiceException; import org.geoserver.wms.MapProducerCapabilities; import org.geoserver.wms.RasterCleaner; import org.geoserver.wms.WMS; import org.geoserver.wms.WMSMapContent; import org.geotools.image.io.ImageIOExt; import org.geotools.util.logging.Logging; /** * Map response to encode Tiff images out of a map. * * @author Simone Giannecchini * @since 1.4.x * */ public final class TIFFMapResponse extends RenderedImageMapResponse { /** A logger for this class. */ private static final Logger LOGGER = Logging.getLogger(TIFFMapResponse.class); private final static ImageWriterSpi writerSPI = new it.geosolutions.imageioimpl.plugins.tiff.TIFFImageWriterSpi(); /** the only MIME type this map producer supports */ private static final String MIME_TYPE = "image/tiff"; private static final String IMAGE_TIFF8 = "image/tiff8"; private static final String[] OUTPUT_FORMATS = { MIME_TYPE, IMAGE_TIFF8 }; /** * Default capabilities for TIFF format. * * <p> * <ol> * <li>tiled = supported</li> * <li>multipleValues = unsupported</li> * <li>paletteSupported = supported</li> * <li>transparency = supported</li> * </ol> */ private static MapProducerCapabilities CAPABILITIES= new MapProducerCapabilities(true, false, true, true, null); /** * Creates a {@link GetMapProducer} to encode the {@link RenderedImage} generated in * <code>outputFormat</code> format. * * @param wms * service facade */ public TIFFMapResponse(WMS wms) { super(OUTPUT_FORMATS, wms); } /** * Transforms the rendered image into the appropriate format, streaming to the output stream. * * @param format * The name of the format * @param image * The image to be formatted. * @param outStream * The stream to write to. * * @throws ServiceException * not really. * @throws IOException * if the image writing fails. */ public void formatImageOutputStream(RenderedImage image, OutputStream outStream, WMSMapContent mapContent) throws ServiceException, IOException { // getting a writer if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Getting a writer for tiff"); } // get a writer final ImageWriter writer = writerSPI.createWriterInstance(); // getting a stream caching in memory final ImageOutputStream ioutstream = ImageIOExt.createImageOutputStream(image, outStream); if (ioutstream == null) throw new ServiceException("Unable to create ImageOutputStream."); // tiff if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Writing tiff image ..."); } // do we want it to be 8 bits? image = applyPalette(image, mapContent, IMAGE_TIFF8, false); // write it out try { writer.setOutput(ioutstream); writer.write(image); } finally { try { ioutstream.close(); } catch (Throwable e) { // eat exception to release resources silently if (LOGGER.isLoggable(Level.FINEST)) LOGGER.log(Level.FINEST, "Unable to properly close output stream", e); } try { writer.dispose(); } catch (Throwable e) { // eat exception to release resources silently if (LOGGER.isLoggable(Level.FINEST)) LOGGER.log(Level.FINEST, "Unable to properly dispose writer", e); } // let go of the image RasterCleaner.addImage(image); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Writing tiff image done!"); } } @Override public MapProducerCapabilities getCapabilities(String outputFormat) { return CAPABILITIES; } }