geotiffimagereader.java

来自「world wind java sdk 源码」· Java 代码 · 共 686 行 · 第 1/2 页

JAVA
686
字号
            if (ifh[0] == 0x4D && ifh[1] == 0x4D)            {                theStream.setByteOrder(ByteOrder.BIG_ENDIAN);            }            else if (ifh[0] == 0x49 && ifh[1] == 0x49)            {                theStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);            }            else            {                throw new IOException();            }        }        catch (IOException ex)        {            throw new IIOException(this.getClass().getName() + ": error reading signature");        }        // skip the magic number and get offset to first (and likely only) ImageFileDirectory...        theStream.readFully(ifh);        long ifdOffset = theStream.readUnsignedInt();        readIFD(ifdOffset);    }    /*    * Reads an ImageFileDirectory and places it in our list.  Calls itself recursively if additional    * IFDs are indicated.    *    */    private void readIFD(long offset) throws IIOException    {        try        {            theStream.seek(offset);            int numEntries = theStream.readUnsignedShort();            TiffIFDEntry[] ifd = new TiffIFDEntry[numEntries];            for (int i = 0; i < numEntries; i++)            {                int tag = theStream.readUnsignedShort();                int type = theStream.readUnsignedShort();                long count = theStream.readUnsignedInt();                long valoffset;                if (type == TiffTypes.SHORT && count == 1) {                    // these get packed left-justified in the bytes...                    int upper = theStream.readUnsignedShort();                    int lower = theStream.readUnsignedShort();                    valoffset = (0xffff & upper) << 16 | (0xffff & lower);                }                else                    valoffset = theStream.readUnsignedInt();                ifd[i] = new TiffIFDEntry(tag, type, count, valoffset);            }            ifds.add(ifd);            /****** TODO: UNCOMMENT;  IN GENERAL, THERE CAN BE MORE THAN ONE IFD IN A TIFF FILE             long nextIFDOffset = theStream.readUnsignedInt();             if (nextIFDOffset > 0)             readIFD(nextIFDOffset);             */        }        catch (Exception ex)        {            throw new IIOException("Error reading Tiff IFD: " + ex.getMessage());        }    }    /*    * Reads BYTE image data organized as a singular image plane (and pixel interleaved, in the case of color images).    *    */    private byte[][] readPixelInterleaved8(int width, int height, int samplesPerPixel,        long[] stripOffsets, long[] stripCounts) throws IOException    {        byte[][] data = new byte[1][width * height * samplesPerPixel];        int offset = 0;        for (int i = 0; i < stripOffsets.length; i++)        {            this.theStream.seek(stripOffsets[i]);            int len = (int) stripCounts[i];            if ((offset + len) >= data[0].length)                len = data[0].length - offset;            this.theStream.readFully(data[0], offset, len);            offset += stripCounts[i];        }        return data;    }    /*     * Reads BYTE image data organized as separate image planes.     *     */    private byte[][] readPlanar8(int width, int height, int samplesPerPixel,        long[] stripOffsets, long[] stripCounts, long rowsPerStrip) throws IOException    {        byte[][] data = new byte[samplesPerPixel][width * height];        int band = 0;        int offset = 0;        int numRows = 0;        for (int i = 0; i < stripOffsets.length; i++)        {            this.theStream.seek(stripOffsets[i]);            int len = (int) stripCounts[i];            if ((offset + len) >= data[band].length)                len = data[band].length - offset;            this.theStream.readFully(data[band], offset, len);            offset += stripCounts[i];            numRows += rowsPerStrip;            if (numRows >= height)            {                ++band;                numRows = 0;                offset = 0;            }        }        return data;    }    /*     * Reads SHORT image data organized as separate image planes.     *     */    private short[][] readPlanar16(int width, int height, int samplesPerPixel,        long[] stripOffsets, long[] stripCounts, long rowsPerStrip) throws IOException    {        short[][] data = new short[samplesPerPixel][width * height];        int band = 0;        int offset = 0;        int numRows = 0;        for (int i = 0; i < stripOffsets.length; i++)        {            this.theStream.seek(stripOffsets[i]);            int len = (int) stripCounts[i] / Short.SIZE;    // strip-counts are in bytes, we're reading shorts...            if ((offset + len) >= data[band].length)                len = data[band].length - offset;            this.theStream.readFully(data[band], offset, len);            offset += stripCounts[i] / Short.SIZE;            numRows += rowsPerStrip;            if (numRows >= height)            {                ++band;                numRows = 0;                offset = 0;            }        }        return data;    }    /*     * Reads FLOAT image data organized as separate image planes.     *     */    private float[][] readPlanarFloat32(int width, int height, int samplesPerPixel,        long[] stripOffsets, long[] stripCounts, long rowsPerStrip) throws IOException    {        float[][] data = new float[samplesPerPixel][width * height];        int band = 0;        int offset = 0;        int numRows = 0;        for (int i = 0; i < stripOffsets.length; i++)        {            this.theStream.seek(stripOffsets[i]);            int len = (int) stripCounts[i] / Float.SIZE;    // strip-counts are in bytes, we're reading floats...            if ((offset + len) >= data[band].length)                len = data[band].length - offset;            this.theStream.readFully(data[band], offset, len);            offset += stripCounts[i] / Float.SIZE;            numRows += rowsPerStrip;            if (numRows >= height)            {                ++band;                numRows = 0;                offset = 0;            }        }        return data;    }    /*     * Reads a ColorMap.     *     */    private byte[][] readColorMap(TiffIFDEntry colorMapEntry) throws IOException    {        // NOTE: TIFF gives total number of cmap values, which is 3 times the size of cmap table...        int numEntries = (int) colorMapEntry.count / 3;        short[][] tmp = new short[3][numEntries];        this.theStream.seek(colorMapEntry.asLong());        // Unroll the loop; the TIFF spec says "...3 is the number of the counting, and the counting shall be 3..."        // TIFF spec also says that all red values precede all green, which precede all blue.        this.theStream.readFully(tmp[0], 0, numEntries);        this.theStream.readFully(tmp[1], 0, numEntries);        this.theStream.readFully(tmp[2], 0, numEntries);        // TIFF gives a ColorMap composed of unsigned shorts. Java's IndexedColorModel wants unsigned bytes.        // Something's got to give somewhere...we'll do our best.        byte[][] cmap = new byte[3][numEntries];        for (int i = 0; i < 3; i++)        {            for (int j = 0; j < numEntries; j++)            {                cmap[i][j] = (byte) (0x00ff & tmp[i][j]);            }        }        return cmap;    }    /*     * Reads and returns an array of doubles from the file.     *     */    private double[] readDoubles(TiffIFDEntry entry) throws IOException    {        double[] doubles = new double[(int) entry.count];        this.theStream.seek(entry.asOffset());        this.theStream.readFully(doubles, 0, doubles.length);        return doubles;    }    private void readGeoKeys(TiffIFDEntry entry) throws IOException    {        short[] keyValRec = new short[4];        this.theStream.seek(entry.asLong());        // get the number of key-value pairs...        this.theStream.readFully(keyValRec, 0, keyValRec.length);        int numKeys = keyValRec[3];        geoKeys = new GeoKey[numKeys];        keyValRec = new short[numKeys * 4];        this.theStream.readFully(keyValRec, 0, numKeys * 4);        int j = 0;        for (int i = 0; i < numKeys * 4; i += 4)        {            GeoKey key = new GeoKey();            key.key = keyValRec[i];            if (keyValRec[i + 1] == 0)                key.value = new Integer(keyValRec[i + 3]);            else            {                // TODO: This isn't quite right....                key.value = getByTag(ifds.get(0),  (0x0000ffff & keyValRec[i + 1]));            }            geoKeys[j++] = key;        }    }    /*     * Returns the (first!) IFD-Entry with the given tag, or null if not found.     *      */    private TiffIFDEntry getByTag(TiffIFDEntry[] ifds, int tag)    {        for (TiffIFDEntry ifd : ifds)        {            if (ifd.tag == tag)            {                return ifd;            }        }        return null;    }    /*    * Utility method intended to read the array of StripOffsets or StripByteCounts.    */    private long[] getStripsArray(TiffIFDEntry stripsEntry) throws IOException    {        long[] offsets = new long[(int) stripsEntry.count];        if (stripsEntry.count == 1)        {            // this is a special case, and it *does* happen!            offsets[0] = stripsEntry.asLong();        }        else        {            long fileOffset = stripsEntry.asLong();            this.theStream.seek(fileOffset);            if (stripsEntry.type == TiffTypes.SHORT)                for (int i = 0; i < stripsEntry.count; i++)                {                    offsets[i] = this.theStream.readUnsignedShort();                }            else                for (int i = 0; i < stripsEntry.count; i++)                {                    offsets[i] = this.theStream.readUnsignedInt();                }        }        return offsets;    }    /*     * Utility to extract bitsPerSample info (if present). This is a bit tricky, because if the samples/pixel == 1,     * the bitsPerSample will fit in the offset/value field of the ImageFileDirectory element. In contrast, when      * samples/pixel == 3, the 3 shorts that make up bitsPerSample don't fit in the offset/value field, so we have     * to go track them down elsewhere in the file.  Finally, as bitsPerSample is optional for bilevel images,     * we'll return something sane if this tag is absent.     */    private int[] getBitsPerSample(TiffIFDEntry entry) throws IOException    {        if (entry == null)        {            return new int[]{1};        }  // the default according to the Tiff6.0 spec.        if (entry.count == 1)        {            return new int[]{(int) entry.asLong()};        }        long[] tmp = getStripsArray(entry);        int[] bits = new int[tmp.length];        for (int i = 0; i < tmp.length; i++)        {            bits[i] = (int) tmp[i];        }        return bits;    }    private class GeoKey    {        short key;        Object value;    }    private ImageInputStream theStream = null;    private ArrayList<TiffIFDEntry[]> ifds = new ArrayList<TiffIFDEntry[]>(1);    // Geotiff info...    private double[] geoPixelScale = null;    private double[] geoTiePoints = null;    private double[] geoMatrix = null;    private GeoKey[] geoKeys = null;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?