Package org.geotools.imageio.hdf4

Source Code of org.geotools.imageio.hdf4.HDF4ImageReader$HDF4DatasetWrapper

/*
*    ImageI/O-Ext - OpenSource Java Image translation Library
*    http://www.geo-solutions.it/
*    http://java.net/projects/imageio-ext/
*    (C) 2007 - 2009, GeoSolutions
*
*    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;
*    either version 3 of the License, or (at your option) any later version.
*
*    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.imageio.hdf4;

import it.geosolutions.imageio.utilities.ImageIOUtilities;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BandedSampleModel;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferDouble;
import java.awt.image.DataBufferFloat;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageReadParam;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;

import org.geotools.factory.GeoTools;
import org.geotools.imageio.SliceDescriptor;
import org.geotools.imageio.SpatioTemporalImageReader;
import org.geotools.imageio.metadataold.SpatioTemporalMetadata;
import org.geotools.imageio.netcdf.NetCDFUtilities;
import org.geotools.imageio.unidata.UnidataImageReader;
import org.geotools.imageio.unidata.VariableWrapper;
import org.geotools.referencing.factory.ReferencingFactoryContainer;
import org.geotools.util.SoftValueHashMap;

import ucar.ma2.Array;
import ucar.ma2.ArrayByte;
import ucar.ma2.ArrayDouble;
import ucar.ma2.ArrayFloat;
import ucar.ma2.ArrayInt;
import ucar.ma2.ArrayShort;
import ucar.ma2.InvalidRangeException;
import ucar.ma2.Range;
import ucar.ma2.Section;
import ucar.nc2.Variable;
import ucar.nc2.iosp.hdf4.H4iosp;

public abstract class HDF4ImageReader extends UnidataImageReader implements SpatioTemporalImageReader {

    protected SoftValueHashMap<Integer, IIOMetadata> metadataMap = new SoftValueHashMap<Integer, IIOMetadata>();

    /** Inner map to cache the SpatioTemporal metadata instances */
    protected SoftValueHashMap<Integer, SpatioTemporalMetadata> spatioTemporalMetadataMap = new SoftValueHashMap<Integer, SpatioTemporalMetadata>();

   
    protected class HDF4DatasetWrapper extends VariableWrapper {

        private int numAttributes;

        public int getNumAttributes() {
            return numAttributes;
        }

        protected HDF4DatasetWrapper( final Variable var ) {
            super(var);
            numAttributes = var.getAttributes().size();
            final int numBands = getNumBands();
            final int width = getWidth();
            final int height = getHeight();
            if (numBands == 3)
                setSampleModel(new PixelInterleavedSampleModel(NetCDFUtilities.getRawDataType(var), width, height, numBands,
                        width * numBands, new int[]{0, 1, 2}));
            else
                setSampleModel(new BandedSampleModel(NetCDFUtilities.getRawDataType(var), width, height, numBands));
        }
    }

    protected final static Logger LOGGER = Logger.getLogger("it.geosolutions.imageio.plugins.hdf4");

    /** set it to <code>true</code> when initialization has been performed */
    private boolean isInitialized = false;

    protected abstract HDF4DatasetWrapper getDatasetWrapper( final int imageIndex );

    /**
     * Additional initialization for a specific HDF "Profile". Depending on the
     * HDF data producer, the originating file has a proper data/metadata
     * structure. For this reason, a specific initialization should be
     * implemented for each different HDF "Profile". As an instance, the
     * Automated Processing System (APS) produces HDF files having a different
     * structure with respect to the HDF structure of a file produced by TIROS
     * Operational Vertical Sounder (TOVS).
     *
     * @throws Exception
     */
    protected abstract void initializeProfile() throws IOException;

    protected abstract org.geotools.imageio.hdf4.HDF4ImageReaderSpi.HDF4_TYPE getHDF4Type();
   
    protected abstract IIOMetadata getImageMetadata( int imageIndex, final String metadataFormat ) throws IOException ;
   
    protected HDF4ImageReader( ImageReaderSpi originatingProvider ) {
        super(originatingProvider);
    }

    /**
     * Simple initialization method
     */
    protected synchronized void initialize() throws IOException {
        if (!isInitialized) {
            // initialize information specific to this profile
            initializeProfile();
            isInitialized = true;
        }
    }

    /**
     * @see it.geosolutions.imageio.plugins.hdf4.HDF4ImageReader#dispose()
     */
    public void dispose() {
        super.dispose();
       
        metadataMap.clear();
        metadataMap = null;
        spatioTemporalMetadataMap.clear();
        spatioTemporalMetadataMap = null;

        try {
            if (dataset != null) {
                dataset.close();
            }
        } catch (IOException e) {
            if (LOGGER.isLoggable(Level.WARNING))
                LOGGER.warning("Errors closing NetCDF dataset." + e.getLocalizedMessage());
        } finally {
            dataset = null;
        }
       
        isInitialized = false;
    }

    @Override
    public void setInput( Object input, boolean seekForwardOnly, boolean ignoreMetadata ) {
        super.setInput(input, seekForwardOnly, ignoreMetadata);
        if (dataset != null) {
            if (!(dataset.getIosp() instanceof H4iosp))
                throw new IllegalArgumentException("Provided dataset is not an HDF4 file");
        } else
            throw new IllegalArgumentException("Provided dataset is not an HDF4 file");

        try {
            initialize();
        } catch (IOException e) {
            throw new IllegalArgumentException("Error occurred during NetCDF file parsing", e);
        }
    }

    /**
     * @see it.geosolutions.imageio.plugins.hdf4.HDF4ImageReader#getStreamMetadata()
     */
    public IIOMetadata getStreamMetadata() throws IOException {
        throw new UnsupportedOperationException(
                "Stream Metadata is not implemented for the base class, use corecommonstreammetadata");
    }

    protected BufferedImage read2DVariable( final int imageIndex, final ImageReadParam param ) throws IOException {
        BufferedImage image = null;
        final HDF4DatasetWrapper wrapper = getDatasetWrapper(imageIndex);
        final Variable variable = wrapper.getVariable();

        /*
         * Fetches the parameters that are not already processed by utility
         * methods like 'getDestination' or 'computeRegions' (invoked below).
         */
        final int strideX, strideY;
        // final int[] srcBands, dstBands;
        if (param != null) {
            strideX = param.getSourceXSubsampling();
            strideY = param.getSourceYSubsampling();
            // srcBands = param.getSourceBands();
            // dstBands = param.getDestinationBands();
        } else {
            strideX = 1;
            strideY = 1;
            // srcBands = null;
            // dstBands = null;
        }
        final int rank = variable.getRank();

        /*
         * Gets the destination image of appropriate size. We create it now
         * since it is a convenient way to get the number of destination bands.
         */
        final int width = wrapper.getWidth();
        final int height = wrapper.getHeight();
        final int numBands = wrapper.getNumBands();
        /*
         * Computes the source region (in the NetCDF file) and the destination
         * region (in the buffered image). Copies those informations into UCAR
         * Range structure.
         */
        final Rectangle srcRegion = new Rectangle();
        final Rectangle destRegion = new Rectangle();
        computeRegions(param, width, height, null, srcRegion, destRegion);
        // flipVertically(param, height, srcRegion);
        int destWidth = destRegion.x + destRegion.width;
        int destHeight = destRegion.y + destRegion.height;

        final List<Range> ranges = new LinkedList<Range>();
        for( int i = 0; i < rank; i++ ) {
            final int first, length, stride;
            switch( i ) {
            case 1: {
                first = srcRegion.x;
                length = srcRegion.width;
                stride = strideX;
                break;
            }
            case 0: {
                first = srcRegion.y;
                length = srcRegion.height;
                stride = strideY;
                break;
            }
            default: {
                first = 0;
                length = numBands;
                stride = 1;
                break;
            }
            }
            try {
                ranges.add(new Range(first, first + length - 1, stride));
            } catch (InvalidRangeException e) {
                // TODO LOGME
            }
        }
        final Section sections = new Section(ranges);

        /*
         * Setting SampleModel and ColorModel.
         */
        final SampleModel sampleModel = wrapper.getSampleModel().createCompatibleSampleModel(destWidth, destHeight);
        final ColorModel colorModel = ImageIOUtilities.createColorModel(sampleModel);

        /*
         * Reads the requested sub-region only.
         */
        final int size = destHeight * destWidth * numBands;
        Array array = null;
        try {
            array = variable.read(sections);
            DataBuffer dataBuffer = null;
            if (array instanceof ArrayByte) {
                dataBuffer = new DataBufferByte((byte[]) array.get1DJavaArray(byte.class), size);
            } else if (array instanceof ArrayShort) {
                dataBuffer = new DataBufferShort((short[]) array.get1DJavaArray(short.class), size);
            } else if (array instanceof ArrayInt) {
                dataBuffer = new DataBufferInt((int[]) array.get1DJavaArray(int.class), size);
            } else if (array instanceof ArrayFloat) {
                dataBuffer = new DataBufferFloat((float[]) array.get1DJavaArray(float.class), size);
            } else if (array instanceof ArrayDouble) {
                dataBuffer = new DataBufferDouble((double[]) array.get1DJavaArray(double.class), size);
            }

            WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, new Point(0, 0));
            image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
        } catch (InvalidRangeException e) {
            // TODO LOGME
        }
        return image;
    }

    /**
     * @see it.geosolutions.imageio.plugins.hdf4.HDF4ImageReader#read(int, javax.imageio.ImageReadParam)
     */
    @Override
    public BufferedImage read( final int imageIndex, final ImageReadParam param ) throws IOException {
        return read2DVariable(imageIndex, param);
    }

    /**
     * Returns a {@link SliceDescriptor} instance for the specified imageIndex.
     *
     * @param imageIndex
     *                the index of the specified 2D raster.
     * @see SpatioTemporalImageReader#getSliceDescriptor(int)
     */
    public SliceDescriptor getSliceDescriptor(int imageIndex)
            throws IOException {
        return new SliceDescriptor(getSpatioTemporalMetadata(imageIndex),ReferencingFactoryContainer.instance(GeoTools.getDefaultHints()));
    }

    /**
     * Returns a {@link SpatioTemporalMetadata} instance for the specified
     * imageIndex.
     *
     * @param imageIndex
     *                the index of the specified 2D raster.
     * @see SpatioTemporalImageReader#getSpatioTemporalMetadata(int)
     */
    public SpatioTemporalMetadata getSpatioTemporalMetadata(int imageIndex) {
        SpatioTemporalMetadata metadata;
        synchronized (spatioTemporalMetadataMap) {
            if (!spatioTemporalMetadataMap.containsKey(imageIndex)) {
                metadata = new HDF4SpatioTemporalMetadata(this, imageIndex);
                spatioTemporalMetadataMap.put(imageIndex, metadata);
            } else {
                metadata = spatioTemporalMetadataMap.get(imageIndex);
                if (metadata == null) {
                    metadata = new HDF4SpatioTemporalMetadata(this, imageIndex);
                    spatioTemporalMetadataMap.put(imageIndex, metadata);
                }
            }
        }
        return metadata;
    }

}
TOP

Related Classes of org.geotools.imageio.hdf4.HDF4ImageReader$HDF4DatasetWrapper

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.