xtiffimageencoder.java
来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 816 行 · 第 1/2 页
JAVA
816 行
numTiles = (int) Math.ceil((double) length / (double) tileLength) * (int) Math.ceil((double) width / (double) tileWidth); stripTileByteCounts = new long[numTiles]; stripTileOffsets = new long[numTiles]; // Image Width directory.addField(XTIFF.TIFFTAG_IMAGE_WIDTH, TIFFField.TIFF_LONG, 1, (Object) (new long[] { width })); // Image Length directory.addField(XTIFF.TIFFTAG_IMAGE_LENGTH, TIFFField.TIFF_LONG, 1, new long[] { length }); directory.addField(XTIFF.TIFFTAG_BITS_PER_SAMPLE, TIFFField.TIFF_SHORT, numBands, convertToChars(sampleSize)); directory.addField(XTIFF.TIFFTAG_COMPRESSION, TIFFField.TIFF_SHORT, 1, new char[] { (char) compression }); directory.addField(XTIFF.TIFFTAG_PHOTOMETRIC_INTERPRETATION, TIFFField.TIFF_SHORT, 1, new char[] { (char) photometricInterpretation }); directory.addField(XTIFF.TIFFTAG_SAMPLES_PER_PIXEL, TIFFField.TIFF_SHORT, 1, new char[] { (char) numBands }); if (isTiled) { directory.addField(XTIFF.TIFFTAG_TILE_WIDTH, TIFFField.TIFF_LONG, 1, new long[] { tileWidth }); directory.addField(XTIFF.TIFFTAG_TILE_LENGTH, TIFFField.TIFF_LONG, 1, new long[] { tileLength }); directory.addField(XTIFF.TIFFTAG_TILE_OFFSETS, TIFFField.TIFF_LONG, numTiles, stripTileOffsets); directory.addField(XTIFF.TIFFTAG_TILE_BYTE_COUNTS, TIFFField.TIFF_LONG, numTiles, stripTileByteCounts); } else { directory.addField(XTIFF.TIFFTAG_STRIP_OFFSETS, TIFFField.TIFF_LONG, numTiles, stripTileOffsets); directory.addField(XTIFF.TIFFTAG_ROWS_PER_STRIP, TIFFField.TIFF_LONG, 1, new long[] { tileLength }); directory.addField(XTIFF.TIFFTAG_STRIP_BYTE_COUNTS, TIFFField.TIFF_LONG, numTiles, stripTileByteCounts); } addIfAbsent(XTIFF.TIFFTAG_X_RESOLUTION, TIFFField.TIFF_RATIONAL, 1, new long[][] { { 72, 1 } }); addIfAbsent(XTIFF.TIFFTAG_Y_RESOLUTION, TIFFField.TIFF_RATIONAL, 1, new long[][] { { 72, 1 } }); addIfAbsent(XTIFF.TIFFTAG_RESOLUTION_UNIT, TIFFField.TIFF_SHORT, 1, new char[] { (char) 2 }); if (colormap != null) { directory.addField(XTIFF.TIFFTAG_COLORMAP, TIFFField.TIFF_SHORT, sizeOfColormap, colormap); } // Data Sample Format Extension fields. if (dataTypeIsShort) { // SampleFormat int[] sampleFormat = new int[numBands]; sampleFormat[0] = dataType == DataBuffer.TYPE_USHORT ? 1 : 2; for (int b = 1; b < numBands; b++) { sampleFormat[b] = sampleFormat[0]; } directory.addField(XTIFF.TIFFTAG_SAMPLE_FORMAT, TIFFField.TIFF_SHORT, numBands, convertToChars(sampleFormat)); // SMinSampleValue: set to data type minimum. int[] minValue = new int[numBands]; minValue[0] = dataType == DataBuffer.TYPE_USHORT ? 0 : Short.MIN_VALUE; for (int b = 1; b < numBands; b++) { minValue[b] = minValue[0]; } directory.addField(XTIFF.TIFFTAG_S_MIN_SAMPLE_VALUE, TIFFField.TIFF_SHORT, numBands, convertToChars(minValue)); // SMaxSampleValue: set to data type maximum. int[] maxValue = new int[numBands]; maxValue[0] = dataType == DataBuffer.TYPE_USHORT ? 65535 : Short.MAX_VALUE; for (int b = 1; b < numBands; b++) { maxValue[b] = maxValue[0]; } directory.addField(XTIFF.TIFFTAG_S_MAX_SAMPLE_VALUE, TIFFField.TIFF_SHORT, numBands, convertToChars(maxValue)); } } private char[] convertToChars(int[] shorts) { char[] out = new char[shorts.length]; for (int i = 0; i < shorts.length; i++) out[i] = (char) shorts[i]; return out; } protected int getSampleSize() { if (dataType == DataBuffer.TYPE_BYTE) return 1; else if (dataTypeIsShort) return 2; return 1; // what should go here? } protected int getTileSize() { return (int) (tileLength * tileWidth * numBands); } private int writeImageData(RenderedImage im, OutputStream out) throws IOException { int total = 0; // Get the encoder XTIFFTileCodec codec = directory.createTileCodec(tparam); // Create a buffer to hold the data // to be written to the file, so we can use array writes. int tsize = codec.getCompressedTileSize(im); bpixels = new byte[tsize]; // Encode one tile at a time Rectangle rect = new Rectangle(); float minX = (float) im.getMinX(); float minY = (float) im.getMinY(); float rows = (float) tileLength; float cols = (float) tileWidth; int i = 0; for (int row = 0; row < length; row += tileLength) { for (int col = 0; col < width; col += tileWidth) { if (!isTiled) rows = Math.min(tileLength, length - row); rect.setRect(minX + col, minY + row, cols, rows); int tileSize = codec.encode(im, rect, bpixels); out.write(bpixels, 0, tileSize); stripTileOffsets[i] = currentOffset; stripTileByteCounts[i++] = tileSize; currentOffset += tileSize; total += tileSize; } } return total; } private void writeDirectory(XTIFFField fields[], int nextIFDOffset) throws IOException { if (currentOffset % 2 == 1) { output.write(0); currentOffset++; } // 2 byte count of number of directory entries (fields) int numEntries = fields.length; long offsetBeyondIFD = currentOffset + 12 * numEntries + 4 + 2; Vector tooBig = new Vector(); XTIFFField field; int tag; int type; int count; // Write number of fields in the IFD writeUnsignedShort(numEntries); for (int i = 0; i < numEntries; i++) { field = fields[i]; // 12 byte field entry TIFFField // byte 0-1 Tag that identifies a field tag = field.getTag(); writeUnsignedShort(tag); // byte 2-3 The field type type = field.getType(); writeUnsignedShort(type); // bytes 4-7 the number of values of the indicated type count = field.getCount(); writeLong(count); // bytes 8 - 11 the value offset if (count * sizeOfType[type] > 4) { // We need an offset as data won't fit into 4 bytes writeLong(offsetBeyondIFD); offsetBeyondIFD += (count * sizeOfType[type]); tooBig.add(new Integer(i)); } else { writeValuesAsFourBytes(field); } } // Address of next IFD writeLong(nextIFDOffset); int index; // Write the tag values that did not fit into 4 bytes for (int i = 0; i < tooBig.size(); i++) { index = ((Integer) tooBig.elementAt(i)).intValue(); writeValues(fields[index]); } } private static final int[] sizeOfType = { 0, // 0 = n/a 1, // 1 = byte 1, // 2 = ascii 2, // 3 = short 4, // 4 = long 8, // 5 = rational 1, // 6 = sbyte 1, // 7 = undefined 2, // 8 = sshort 4, // 9 = slong 8, // 10 = srational 4, // 11 = float 8 // 12 = double }; private void writeValuesAsFourBytes(XTIFFField field) throws IOException { int dataType = field.getType(); int count = field.getCount(); switch (dataType) { // unsigned 8 bits case TIFFField.TIFF_BYTE: byte bytes[] = field.getAsBytes(); for (int i = 0; i < count; i++) { output.write(bytes[i]); } for (int i = 0; i < (4 - count); i++) { output.write(0); } break; // unsigned 16 bits case TIFFField.TIFF_SHORT: char shorts[] = field.getAsChars(); for (int i = 0; i < count; i++) { writeUnsignedShort((int) shorts[i]); } for (int i = 0; i < (2 - count); i++) { writeUnsignedShort(0); } break; // unsigned 32 bits case TIFFField.TIFF_LONG: long longs[] = field.getAsLongs(); for (int i = 0; i < count; i++) { writeLong(longs[i]); } break; } } private void writeValues(XTIFFField field) throws IOException { int dataType = field.getType(); int count = field.getCount(); switch (dataType) { // character data with NULL termination case TIFFField.TIFF_ASCII: String strings[] = field.getAsStrings(); for (int i = 0; i < strings.length; i++) { byte bytes[] = strings[i].getBytes(); for (int j = 0; j < bytes.length; j++) { output.write(bytes[j]); } if ((i + 1) < count) output.write(0); } break; // unsigned 8 bits case TIFFField.TIFF_BYTE: byte bytes[] = field.getAsBytes(); for (int i = 0; i < count; i++) { output.write(bytes[i]); } break; // unsigned 16 bits case TIFFField.TIFF_SHORT: char shorts[] = field.getAsChars(); for (int i = 0; i < count; i++) { writeUnsignedShort((int) shorts[i]); } break; // unsigned 32 bits case TIFFField.TIFF_LONG: long longs[] = field.getAsLongs(); for (int i = 0; i < count; i++) { writeLong(longs[i]); } break; // IEEE 8-byte double case TIFFField.TIFF_DOUBLE: double doubles[] = field.getAsDoubles(); for (int i = 0; i < count; i++) { writeDouble(doubles[i]); } break; case TIFFField.TIFF_RATIONAL: long rationals[][] = field.getAsRationals(); for (int i = 0; i < count; i++) { writeLong(rationals[i][0]); writeLong(rationals[i][1]); } break; } } // Here s is never expected to have value greater than what can be // stored in 2 bytes. private void writeUnsignedShort(int s) throws IOException { output.write((s & 0xff00) >>> 8); output.write(s & 0x00ff); } private void writeLong(long l) throws IOException { output.write((int) ((l & 0xff000000) >>> 24)); output.write((int) ((l & 0x00ff0000) >>> 16)); output.write((int) ((l & 0x0000ff00) >>> 8)); output.write(((int) l & 0x000000ff)); } // write 8-byte IEEE double private void writeDouble(double d) throws IOException { long lval = Double.doubleToLongBits(d); writeLong(lval >>> 32); writeLong((lval & 0xffffffff)); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?