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 + -
显示快捷键?