All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.data.RPFRasterReader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.data;

import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.formats.nitfs.*;
import gov.nasa.worldwind.formats.rpf.*;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.util.*;

/**
 * @author dcollins
 * @version $Id: RPFRasterReader.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class RPFRasterReader extends AbstractDataRasterReader
{
    public RPFRasterReader()
    {
        super("RPF Imagery");
    }

    public boolean canRead(Object source, AVList params)
    {
        if (source == null)
            return false;

        // RPF imagery cannot be identified by a small set of suffixes or mime types, so we override the standard
        // suffix comparison behavior here.

        return this.doCanRead(source, params);
    }

    protected boolean doCanRead(Object source, AVList params)
    {
        if (!(source instanceof java.io.File))
            return false;

        java.io.File file = (java.io.File) source;
        String filename = file.getName().toUpperCase();

        boolean canRead = RPFFrameFilename.isFilename(filename);

        if (canRead && null != params && !params.hasKey(AVKey.PIXEL_FORMAT))
            params.setValue(AVKey.PIXEL_FORMAT, AVKey.IMAGE);

        return canRead;
    }

    protected DataRaster[] doRead(Object source, AVList params) throws java.io.IOException
    {
        if (!(source instanceof java.io.File))
        {
            String message = Logging.getMessage("DataRaster.CannotRead", source);
            Logging.logger().severe(message);
            throw new java.io.IOException(message);
        }

        java.io.File file = (java.io.File) source;
        RPFFrameFilename filename = RPFFrameFilename.parseFilename(file.getName().toUpperCase());
        if (filename.getZoneCode() == '9' || filename.getZoneCode() == 'J')
        {
            return this.readPolarImage(source, filename);
        }
        else
        {
            return this.readNonPolarImage(source, params);
        }
    }

    protected void doReadMetadata(Object source, AVList params) throws java.io.IOException
    {
        if (!(source instanceof java.io.File))
        {
            String message = Logging.getMessage("DataRaster.CannotRead", source);
            Logging.logger().severe(message);
            throw new java.io.IOException(message);
        }

        java.io.File file = (java.io.File) source;
        RPFImageFile rpfFile = null;

        Object width = params.getValue(AVKey.WIDTH);
        Object height = params.getValue(AVKey.HEIGHT);
        if (width == null || height == null || !(width instanceof Integer) || !(height instanceof Integer))
        {
            rpfFile = RPFImageFile.load(file);
            this.readFileSize(rpfFile, params);
        }

        Object sector = params.getValue(AVKey.SECTOR);
        if (sector == null || !(sector instanceof Sector))
            this.readFileSector(file, rpfFile, params);

        if (!params.hasKey(AVKey.PIXEL_FORMAT))
            params.setValue(AVKey.PIXEL_FORMAT, AVKey.IMAGE);
    }

    private DataRaster[] readNonPolarImage(Object source, AVList params) throws java.io.IOException
    {
        // TODO: break the raster along the international dateline, if necessary
        // Nonpolar images need no special processing. We convert it to a compatible image type to improve performance.

        java.io.File file = (java.io.File) source;
        RPFImageFile rpfFile = RPFImageFile.load(file);

        java.awt.image.BufferedImage image = rpfFile.getBufferedImage();
        image = ImageUtil.toCompatibleImage(image);

        // If the data source doesn't already have all the necessary metadata, then we attempt to read the metadata.
        Object o = (params != null) ? params.getValue(AVKey.SECTOR) : null;
        if (o == null || !(o instanceof Sector))
        {
            AVList values = new AVListImpl();
            this.readFileSector(file, rpfFile, values);
            o = values.getValue(AVKey.SECTOR);
        }

        DataRaster raster = new BufferedImageRaster((Sector) o, image);
        return new DataRaster[] {raster};
    }

    private DataRaster[] readPolarImage(Object source, RPFFrameFilename filename) throws java.io.IOException
    {
        java.io.File file = (java.io.File) source;
        RPFImageFile rpfFile = RPFImageFile.load(file);

        java.awt.image.BufferedImage image = rpfFile.getBufferedImage();

        // This is a polar image. We must project it's raster and bounding sector into Geographic/WGS84.
        RPFDataSeries ds = RPFDataSeries.dataSeriesFor(filename.getDataSeriesCode());
        RPFFrameTransform tx = RPFFrameTransform.createFrameTransform(filename.getZoneCode(),
            ds.rpfDataType, ds.scaleOrGSD);
        RPFFrameTransform.RPFImage[] images = tx.deproject(filename.getFrameNumber(), image);

        DataRaster[] rasters = new DataRaster[images.length];
        for (int i = 0; i < images.length; i++)
        {
            java.awt.image.BufferedImage compatibleImage = ImageUtil.toCompatibleImage(images[i].getImage());
            rasters[i] = new BufferedImageRaster(images[i].getSector(), compatibleImage);
        }
        return rasters;
    }

    private void readFileSize(RPFImageFile rpfFile, AVList values)
    {
        int width = rpfFile.getImageSegment().numSignificantCols;
        int height = rpfFile.getImageSegment().numSignificantRows;
        values.setValue(AVKey.WIDTH, width);
        values.setValue(AVKey.HEIGHT, height);
    }

    private void readFileSector(java.io.File file, RPFImageFile rpfFile, AVList values)
    {
        // We'll first attempt to compute the Sector, if possible, from the filename (if it exists) by using
        // the conventions for CADRG and CIB filenames. It has been observed that for polar frame files in
        // particular that coverage information in the file itself is sometimes unreliable.
        Sector sector = this.sectorFromFilename(file);
        // If the sector cannot be computed from the filename, then get it from the RPF file headers.
        if (sector == null)
            sector = this.sectorFromHeader(file, rpfFile);

        values.setValue(AVKey.SECTOR, sector);
    }

    private Sector sectorFromFilename(java.io.File file)
    {
        Sector sector = null;
        try
        {
            // Parse the filename, using the conventions for CADRG and CIB filenames.
            RPFFrameFilename rpfFilename = RPFFrameFilename.parseFilename(file.getName().toUpperCase());
            // Get the dataseries associated with that code.
            RPFDataSeries ds = RPFDataSeries.dataSeriesFor(rpfFilename.getDataSeriesCode());
            // If the scale or GSD associated with the dataseries is valid, then proceed computing the georeferencing
            // information from the filename. Otherwise return null.
            if (ds.scaleOrGSD > 0d)
            {
                // Create a transform to compute coverage information.
                RPFFrameTransform tx = RPFFrameTransform.createFrameTransform(
                    rpfFilename.getZoneCode(), ds.rpfDataType, ds.scaleOrGSD);
                // Get coverage information from the transform.
                sector = tx.computeFrameCoverage(rpfFilename.getFrameNumber());
            }
        }
        catch (Exception e)
        {
            // Computing the file's coverage failed. Log the condition and return null.
            // This at allows the coverage to be re-computed at a later time.
            String message = String.format("Exception while computing file sector: %s", file);
            Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
            sector = null;
        }
        return sector;
    }

    private Sector sectorFromHeader(java.io.File file, RPFFile rpfFile)
    {
        Sector sector;
        try
        {
            if (rpfFile == null)
                rpfFile = RPFImageFile.load(file);

            NITFSImageSegment imageSegment = (NITFSImageSegment) rpfFile.getNITFSSegment(
                NITFSSegmentType.IMAGE_SEGMENT);
            RPFFrameFileComponents comps = imageSegment.getUserDefinedImageSubheader().getRPFFrameFileComponents();
            Angle minLat = comps.swLowerleft.getLatitude();
            Angle maxLat = comps.neUpperRight.getLatitude();
            Angle minLon = comps.swLowerleft.getLongitude();
            Angle maxLon = comps.neUpperRight.getLongitude();
            // This sector spans the longitude boundary. In order to render this sector,
            // we must adjust the longitudes such that minLon 0)
                {
                    double degrees = 360 + maxLon.degrees;
                    maxLon = Angle.fromDegrees(degrees);
                }
            }
            sector = new Sector(minLat, maxLat, minLon, maxLon);
        }
        catch (Exception e)
        {
            // Computing the file's coverage failed. Log the condition and return null.
            // This at allows the coverage to be re-computed at a later time.
            String message = String.format("Exception while getting file sector: %s", file);
            Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
            sector = null;
        }
        return sector;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy