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