Package org.geotiff.image.jai

Source Code of org.geotiff.image.jai.GeoTIFFDirectory

package org.geotiff.image.jai;

import java.util.Iterator;
import java.util.TreeMap;

import org.libtiff.jai.codec.XTIFF;
import org.libtiff.jai.codec.XTIFFDirectory;
import org.libtiff.jai.codec.XTIFFField;

import com.sun.media.jai.codec.SeekableStream;

/**
* An extension of the XTIFFDirectory that understands the structure of the
* GeoTIFF key set
*
* @author Niles D. Ritter
*/

public class GeoTIFFDirectory extends XTIFFDirectory implements
        java.io.Serializable {

    private TreeMap geoKeyIndex = new TreeMap();
    private int keyDirectoryVersion;
    private int majorRevision;
    private int minorRevision;
    private int numberOfKeys;
    private double[] tiepoints = null;
    private double[] scales = null;
    private double[] matrix = null;
    private boolean hasGeoKeys = false;

    /**
     * public constructor (for serializability)
     */
    public GeoTIFFDirectory() {}

    /**
     * Constructs a GeoTIFFDirectory by reading a SeekableStream. The ifd_offset
     * parameter specifies the stream offset from which to begin reading; this
     * mechanism is sometimes used to store private IFDs within a TIFF file that
     * are not part of the normal sequence of IFDs.
     */

    public GeoTIFFDirectory(SeekableStream stream, long ifd_offset)
            throws java.io.IOException {
        super(stream, ifd_offset);
        readGeoKeys();
        log("GeoTIFFDirectory constructor success.");
    }

    /**
     * Constructs a GeoTIFFDirectory from a SeekableStream. The directory
     * parameter specifies which directory to read from the linked list present
     * in the stream; directory 0 is normally read but it is possible to store
     * multiple images in a single TIFF file by maintaing multiple directories.
     */

    public GeoTIFFDirectory(SeekableStream stream, int directory)
            throws java.io.IOException {
        super(stream, directory);
        readGeoKeys();
        log("GeoTIFFDirectory constructor success.");
    }

    private void log(String msg) {}

    /**
     * Generates the TIFF fields from the GeoKey list
     */
    private void createGeoTags() {

        if (!hasGeoKeys)
            return;

        char numberOfKeys = (char) geoKeyIndex.size();
        char[] keys = new char[(numberOfKeys + 1) * 4];

        // Write the 4-entry header
        keys[0] = 1; // key version
        keys[1] = 1; // majorRevision
        keys[2] = 0; // minorRevision
        keys[3] = numberOfKeys;

        // Write the key directory out
        Iterator it = geoKeyIndex.values().iterator();
        double[] doubles = new double[numberOfKeys];
        String strings = "";
        int indx = 4;
        char numDoubles = 0;
        char tag = 0;
        char valueOrOffset = 0;
        while (it.hasNext()) {
            XTIFFField geoKey = (XTIFFField) it.next();
            switch (geoKey.getType()) {
            case XTIFFField.TIFF_SHORT:
                // short values are stored in the valueOrOffset
                tag = 0;
                valueOrOffset = (char) geoKey.getAsInt(0);
                break;
            case XTIFFField.TIFF_DOUBLE:
                tag = (char) XTIFF.TIFFTAG_GEO_DOUBLE_PARAMS;
                doubles[numDoubles] = geoKey.getAsDouble(0);
                valueOrOffset = numDoubles++;
                break;
            case XTIFFField.TIFF_ASCII:
                // strings are '|' pipe delimited
                tag = (char) XTIFF.TIFFTAG_GEO_ASCII_PARAMS;
                valueOrOffset = (char) strings.length();
                strings = strings + geoKey.getAsString(0) + "|";
                break;
            } // switch
            keys[indx++] = (char) geoKey.getTag();
            keys[indx++] = tag;
            keys[indx++] = (char) geoKey.getCount();
            keys[indx++] = valueOrOffset;
        } // while

        // Add the Directory tag
        addField(XTIFF.TIFFTAG_GEO_KEY_DIRECTORY,
                XTIFFField.TIFF_SHORT,
                keys.length,
                keys);

        // Add the Ascii tag if needed
        if (strings.length() > 0) {
            char zero = 0;
            strings = strings + zero;
            addField(XTIFF.TIFFTAG_GEO_ASCII_PARAMS,
                    XTIFFField.TIFF_ASCII,
                    strings.length(),
                    new String[] { strings });
        }

        // Add the double tag if needed
        if (numDoubles > 0) {
            double[] doubleVals = new double[numDoubles];
            for (int i = 0; i < numDoubles; i++)
                doubleVals = doubles;
            addField(XTIFF.TIFFTAG_GEO_DOUBLE_PARAMS,
                    XTIFFField.TIFF_DOUBLE,
                    numDoubles,
                    doubleVals);
        }

        // set up the other values stored in tags
        if (matrix != null)
            addField(XTIFF.TIFFTAG_GEO_TRANS_MATRIX,
                    XTIFFField.TIFF_DOUBLE,
                    matrix.length,
                    matrix);
        if (tiepoints != null)
            addField(XTIFF.TIFFTAG_GEO_TIEPOINTS,
                    XTIFFField.TIFF_DOUBLE,
                    tiepoints.length,
                    tiepoints);
        if (scales != null)
            addField(XTIFF.TIFFTAG_GEO_PIXEL_SCALE,
                    XTIFFField.TIFF_DOUBLE,
                    scales.length,
                    scales);
    }

    /**
     * stores a single geoKey in the index table, from the existing field
     * information
     */
    private void storeGeoKey(int keyID, int tiffTag, int valueCount,
                             int valueOrOffset) throws java.io.IOException {
        int type = XTIFFField.TIFF_SHORT;
        Object value = null;
        if (tiffTag > 0) {
            // Values are in another tag:
            XTIFFField values = getField(tiffTag);
            if (values != null) {
                type = values.getType();
                if (type == XTIFFField.TIFF_ASCII) {
                    String svalue = values.getAsString(0)
                            .substring(valueOrOffset,
                                    valueOrOffset + valueCount - 1);
                    value = new String[] { svalue };
                } else if (type == XTIFFField.TIFF_DOUBLE) {
                    // we shouldn't have valueCount != 1 here
                    double dvalue = values.getAsDouble(valueOrOffset);
                    value = new double[] { dvalue };
                }
            } else {
                throw new java.io.IOException("GeoTIFF tag not found");
            } // values tag found
        } else {
            // value is SHORT, stored in valueOrOffset
            type = XTIFFField.TIFF_SHORT;
            value = new char[] { (char) valueOrOffset };
        } // tiffTag
        addGeoKey(keyID, type, valueCount, value);
    }

    /**
     * Returns an array of XTIFFFields containing all the fields in this
     * directory. Prior to returning array, determine if there are any GeoKeys,
     * and if so, set up the corresponding GeoTIFF fields.
     */
    public XTIFFField[] getFields() {
        if (hasGeoKeys)
            createGeoTags();
        return super.getFields();
    }

    /**
     * populates the geoKeyIndex table from the values stored in the current
     * TIFF fields.
     */
    private void readGeoKeys() throws java.io.IOException {

        // read in the keys
        XTIFFField geoKeyTag = getField(XTIFF.TIFFTAG_GEO_KEY_DIRECTORY);
        if (geoKeyTag != null) {
            char[] keys = geoKeyTag.getAsChars();

            // Set up header info
            keyDirectoryVersion = keys[0]; // should be 1 forever.
            majorRevision = keys[1]; // currently 1
            minorRevision = keys[2]; // 0,1, or 2...
            numberOfKeys = keys[3];

            // Parse out keys and values
            for (int i = 4; i < keys.length; i += 4) {
                int keyID = keys[i];
                int tiffTag = keys[i + 1];
                int valueCount = keys[i + 2];
                int valueOrOffset = keys[i + 3];
                storeGeoKey(keyID, tiffTag, valueCount, valueOrOffset);
            }

        }

        // set up the values stored in tags
        // read in the data stored as real tags
        XTIFFField matrixTag = getField(XTIFF.TIFFTAG_GEO_TRANS_MATRIX);
        XTIFFField tiepointTag = getField(XTIFF.TIFFTAG_GEO_TIEPOINTS);
        XTIFFField scaleTag = getField(XTIFF.TIFFTAG_GEO_PIXEL_SCALE);
        if (tiepointTag != null) {
            tiepoints = tiepointTag.getAsDoubles();
        }
        if (scaleTag != null) {
            scales = scaleTag.getAsDoubles();
        }
        if (matrixTag != null) {
            matrix = matrixTag.getAsDoubles();
        }
    } // readGeoKeys

    /**
     * Add a geoKey to the directory
     */
    public void addGeoKey(int key, int type, int count, Object data) {
        XTIFFField geoKey = createField(key, type, count, data);
        addGeoKey(geoKey);
    }

    /**
     * Add an existing geoKey to the directory.
     */
    public void addGeoKey(XTIFFField geoKey) {
        geoKeyIndex.put(new Integer(geoKey.getTag()), geoKey);
        hasGeoKeys = true;
    }

    /**
     * Returns an array of XTIFFFields containing all the fields corresponding
     * to the GeoKeys.
     */
    public XTIFFField[] getGeoKeys() {
        XTIFFField[] keys = new XTIFFField[geoKeyIndex.size()];
        Iterator it = geoKeyIndex.values().iterator();
        int i = 0;
        while (it.hasNext()) {
            keys[i++] = (XTIFFField) it.next();
        }
        return keys;
    }

    /**
     * Indexed Accessor to the Geokeys,indexed by the key values.
     */
    public XTIFFField getGeoKey(int key) {
        return (XTIFFField) geoKeyIndex.get(new Integer(key));
    }

    /**
     * return the tiepoint tag values
     */
    public double[] getTiepoints() {
        return tiepoints;
    }

    /**
     * return the pixel scale tag values
     */
    public double[] getPixelScale() {
        return scales;
    }

    /**
     * return the transformation matrix tag values
     */
    public double[] getTransformationMatrix() {
        return matrix;
    }

    /**
     * set the tiepoint tag values
     */
    public void setTiepoints(double[] tiepoints) {
        this.tiepoints = tiepoints;
    }

    /**
     * return the pixel scale tag values
     */
    public void setPixelScale(double[] scales) {
        this.scales = scales;
    }

    /**
     * return the pixel scale tag values
     */
    public void setTransformationMatrix(double[] matrix) {
        this.matrix = matrix;
    }

    public int getKeyDirectoryVersion() {
        return keyDirectoryVersion;
    }

    public void setKeyDirectoryVersion(int keyDirectoryVersion) {
        this.keyDirectoryVersion = keyDirectoryVersion;
    }

    public int getMajorRevision() {
        return majorRevision;
    }

    public void setMajorRevision(int majorRevision) {
        this.majorRevision = majorRevision;
    }

    public int getMinorRevision() {
        return minorRevision;
    }

    public void setMinorRevision(int minorRevision) {
        this.minorRevision = minorRevision;
    }

    public int getNumberOfKeys() {
        return numberOfKeys;
    }

    public void setNumberOfKeys(int numberOfKeys) {
        this.numberOfKeys = numberOfKeys;
    }
}
TOP

Related Classes of org.geotiff.image.jai.GeoTIFFDirectory

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.