Package org.geotools.coverageio

Source Code of org.geotools.coverageio.RasterLayerResponse

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
*    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.geotools.coverageio;

import it.geosolutions.imageio.stream.input.FileImageInputStreamExtImpl;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.awt.image.SampleModel;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.spi.ImageReaderSpi;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;

import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.TypeMap;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.factory.Hints;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.operation.transform.ConcatenatedTransform;
import org.geotools.referencing.operation.transform.ProjectiveTransform;
import org.opengis.coverage.ColorInterpretation;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

/**
* A RasterLayerResponse. An instance of this class is produced everytime a
* requestCoverage is called to a reader.
*
* @author Daniele Romagnoli, GeoSolutions
*/
@SuppressWarnings("deprecation")
class RasterLayerResponse {

    /** Logger. */
    private final static Logger LOGGER = org.geotools.util.logging.Logging
            .getLogger("org.geotools.coverageio");

    /**
     * The GridCoverage produced after a {@link #compute()} method call
     */
    private GridCoverage gridCoverage;

    /** The {@link RasterLayerRequest} originating this response */
    private RasterLayerRequest originatingCoverageRequest;

    /** The readerSPI to be used for data read operations */
    private ImageReaderSpi readerSpi;

    /** The coverage factory producing a {@link GridCoverage} from an image */
    private GridCoverageFactory coverageFactory;

    /** The hints to be used to produce this coverage */
    private Hints hints;

    // ////////////////////////////////////////////////////////////////////////
    //
    // Information obtained by the coverageRequest instance
    //
    // ////////////////////////////////////////////////////////////////////////
    /** The coverage grid to world transformation */
    private MathTransform raster2Model;

    /** The base envelope related to the input coverage */
    private GeneralEnvelope coverageEnvelope;

    /** The CRS of the input coverage */
    private CoordinateReferenceSystem coverageCRS;

    /** The name of the input coverage */
    private String coverageName;

    /**
     * Construct a {@code RasterLayerResponse} given a specific
     * {@link RasterLayerRequest}, a {@code GridCoverageFactory} to produce
     * {@code GridCoverage}s and an {@code ImageReaderSpi} to be used for
     * instantiating an Image Reader for a read operation,
     *
     * @param request
     *                a {@link RasterLayerRequest} originating this response.
     * @param coverageFactory
     *                a {@code GridCoverageFactory} to produce a
     *                {@code GridCoverage} when calling the {@link #compute()}
     *                method.
     * @param readerSpi
     *                the Image Reader Service provider interface.
     */
    public RasterLayerResponse(RasterLayerRequest request,
            GridCoverageFactory coverageFactory, ImageReaderSpi readerSpi) {
        originatingCoverageRequest = request;
        hints = request.getHints();
        coverageEnvelope = request.getCoverageEnvelope();
        coverageCRS = request.getCoverageCRS();
        raster2Model = request.getRaster2Model();
        this.coverageName = request.getCoverageName();
        this.coverageFactory = coverageFactory;
        this.readerSpi = readerSpi;
    }

    /**
     * @return the {@link GridCoverage} produced as computation of this response
     *         using the {@link #compute()} method.
     * @uml.property name="gridCoverage"
     */
    public GridCoverage getGridCoverage() {
        return gridCoverage;
    }

    /**
     * @return the {@link RasterLayerRequest} originating this response.
     *
     * @uml.property name="originatingCoverageRequest"
     */
    public RasterLayerRequest getOriginatingCoverageRequest() {
        return originatingCoverageRequest;
    }

    /**
     * Compute the coverage request and produce a grid coverage which will be
     * returned by {@link #getGridCoverage()}. The produced grid coverage may
     * be {@code null} in case of empty request.
     *
     * @throws IOException
     */
    public void compute() throws IOException {
        originatingCoverageRequest.prepare();
        if (originatingCoverageRequest.isEmptyRequest())
          //something bad happened
            gridCoverage = null;
        else {
            final ImageReadParam imageReadParam = originatingCoverageRequest.getImageReadParam();
            final File input = originatingCoverageRequest.getInput();
            final boolean useMultithreading = originatingCoverageRequest.useMultithreading();
            final boolean newTransform = originatingCoverageRequest.isAdjustGridToWorldSet();
            final boolean useJAI = originatingCoverageRequest.useJAI();
            gridCoverage = createCoverage(input, imageReadParam, useJAI,useMultithreading, newTransform);
        }
    }

    /**
     * This method creates the GridCoverage2D from the underlying file given a
     * specified envelope, and a requested dimension.
     *
     * @param iUseJAI
     *                specify if the underlying read process should leverage on
     *                a JAI ImageRead operation or a simple direct call to the
     *                {@code read} method of a proper {@code ImageReader}.
     * @param useMultithreading
     *                specify if the underlying read process should use
     *                multithreading when a JAI ImageRead operation is requested
     * @param overviewPolicy
     *                the overview policy which need to be adopted
     * @return a {@code GridCoverage}
     *
     * @throws java.io.IOException
     */
    private GridCoverage createCoverage(File input,
            ImageReadParam imageReadParam, final boolean useJAI,
            final boolean useMultithreading, final boolean adjustGridToWorld)
            throws IOException {
        // ////////////////////////////////////////////////////////////////////
        //
        // Doing an image read for reading the coverage.
        //
        // ////////////////////////////////////////////////////////////////////
        final PlanarImage image = readRaster(input, useJAI, imageReadParam,
                useMultithreading);

        // /////////////////////////////////////////////////////////////////////
        //
        // Creating the coverage
        //
        // /////////////////////////////////////////////////////////////////////
        if (adjustGridToWorld) {
            // I need to calculate a new transformation (raster2Model)
            // between the cropped image and the required envelope
            final int ssWidth = image.getWidth();
            final int ssHeight = image.getHeight();
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "Coverage read: width = " + ssWidth
                        + " height = " + ssHeight);
            }

            // //
            //
            // setting new coefficients to define a new affineTransformation
            // to be applied to the grid to world transformation
            // ------------------------------------------------------
            //
            // With respect to the original envelope, the obtained
            // planarImage needs to be rescaled and translated. The scaling
            // factors are computed as the ratio between the cropped source
            // region sizes and the read image sizes. The translate
            // settings are represented by the offsets of the source region.
            //
            // //
            final Rectangle sourceRegion = imageReadParam.getSourceRegion();
            final double scaleX = sourceRegion.width / (1.0 * ssWidth);
            final double scaleY = sourceRegion.height / (1.0 * ssHeight);
            final double translateX = sourceRegion.x;
            final double translateY = sourceRegion.y;
            return createCoverageFromImage(image, ConcatenatedTransform.create(
                    ProjectiveTransform.create(new AffineTransform(scaleX, 0,
                            0, scaleY, translateX, translateY)), raster2Model));
        } else {
            // In case of no transformation is required (As an instance,
            // when reading the whole image)
            return createCoverageFromImage(image);
        }
    }

    /**
     * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using
     * the {@link #raster2Model} that was provided for this coverage.
     *
     * <p>
     * This method is vital when working with coverages that have a raster to
     * model transformation that is not a simple scale and translate.
     *
     * @param image
     *                contains the data for the coverage to create.
     * @param raster2Model
     *                is the {@link MathTransform} that maps from the raster
     *                space to the model space.
     * @return a {@link GridCoverage}
     * @throws IOException
     */
    protected GridCoverage createCoverageFromImage(PlanarImage image,
            MathTransform raster2Model) throws IOException {
    // creating bands
        final SampleModel sm=image.getSampleModel();
        final ColorModel cm=image.getColorModel();
    final int numBands = sm.getNumBands();
    final GridSampleDimension[] bands = new GridSampleDimension[numBands];
        // setting bands names.
    Set<String> bandNames = new HashSet<String>();
        for (int i = 0; i < numBands; i++) {
            final ColorInterpretation colorInterpretation = TypeMap.getColorInterpretation(cm, i);
            // make sure we create no duplicate band names
            String bandName;
            if(colorInterpretation == null || colorInterpretation == ColorInterpretation.UNDEFINED
                    || bandNames.contains(colorInterpretation.name())) {
                bandName = "Band" + (i + 1);
            else {
                bandName = colorInterpretation.name();
            }
            bands[i] = new GridSampleDimension(bandName).geophysics(true);
        }

        // creating coverage
        if (raster2Model != null) {
            return coverageFactory.create(coverageName, image, coverageCRS,
                    raster2Model, bands, null, null);
        }

        return coverageFactory.create(coverageName, image, new GeneralEnvelope(
                coverageEnvelope), bands, null, null);
    }

    /**
     * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using
     * the {@link #coverageEnvelope} that was provided for this coverage.
     *
     * @param image
     *                contains the data for the coverage to create.
     * @return a {@link GridCoverage}
     * @throws IOException
     */
    protected GridCoverage createCoverageFromImage(PlanarImage image)
            throws IOException {
        return createCoverageFromImage(image, null);
    }

    /**
     * Returns a {@code PlanarImage} given a set of parameter specifying the
     * type of read operation to be performed.
     *
     * @param input
     *                a File input to be used for reading the image.
     * @param useJAI
     *                {@code true} if we need to use a JAI ImageRead operation,
     *                {@code false} if we need a simple direct
     *                {@code ImageReader.read(...)} call.
     * @param imageReadParam
     *                an {@code ImageReadParam} specifying the read parameters
     * @param useMultithreading
     *                {@code true} if a JAI ImageRead operation is requested
     *                with support for multithreading. This parameter will be
     *                ignored if requesting a direct read operation.
     * @return the read {@code PlanarImage}
     * @throws IOException
     */
    protected PlanarImage readRaster(final File input, final boolean useJAI,
            final ImageReadParam imageReadParam, final boolean useMultithreading)
            throws IOException {
        PlanarImage raster;
        final ImageReader reader;
        FileImageInputStreamExtImpl fiis = null;
        if (useJAI) {
            fiis = new FileImageInputStreamExtImpl(input);
            reader = readerSpi.createReaderInstance();

            final ParameterBlock pbjImageRead = new ParameterBlock();
            pbjImageRead.add(fiis);
            pbjImageRead.add(0);
            pbjImageRead.add(Boolean.FALSE);
            pbjImageRead.add(Boolean.FALSE);
            pbjImageRead.add(Boolean.FALSE);
            pbjImageRead.add(null);
            pbjImageRead.add(null);
            pbjImageRead.add(imageReadParam);
            pbjImageRead.add(reader);

            // Check if to use a simple JAI ImageRead operation or a
            // multithreaded one
            final String jaiOperation = useMultithreading ? GridCoverageUtilities.IMAGEREADMT: GridCoverageUtilities.IMAGEREAD;
            raster = JAI.create(jaiOperation, pbjImageRead, hints);
        } else {
            reader = readerSpi.createReaderInstance();
            fiis = new FileImageInputStreamExtImpl(input);
            try {
                reader.setInput(fiis, true, true);
                raster = PlanarImage.wrapRenderedImage(reader.read(0,imageReadParam));
            }
            finally {
               
                if (fiis != null) {
                    try {
                        fiis.close();
                    } catch (Exception e) {
                        if (LOGGER.isLoggable(Level.FINE)){
                            LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
                        }
                    }
                }

                if (reader != null)
                    try {
                        reader.dispose();
                    } catch (Exception e) {
                        if (LOGGER.isLoggable(Level.FINE)){
                            LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
                        }
                    }
            }
           
        }
        return raster;
    }
}
TOP

Related Classes of org.geotools.coverageio.RasterLayerResponse

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.