geotiffimagereader.java

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

JAVA
686
字号
/* Copyright (C) 2001, 2008 United States Government as represented by   the Administrator of the National Aeronautics and Space Administration.   All Rights Reserved. */package gov.nasa.worldwind.formats.tiff;import javax.imageio.*;import javax.imageio.metadata.*;import javax.imageio.spi.*;import javax.imageio.stream.*;import java.awt.*;import java.awt.color.*;import java.awt.image.*;import java.io.*;import java.nio.*;import java.util.*;/** * @author brownrigg * @version $Id: GeotiffImageReader.java 7290 2008-10-29 20:50:12Z dcollins $ */public class GeotiffImageReader extends ImageReader{    public GeotiffImageReader(ImageReaderSpi provider)    {        super(provider);    }    @Override    public int getNumImages(boolean allowSearch) throws IOException    {        // TODO:  This should allow for multiple images that may be present. For now, we'll ignore all but first.        return 1;    }    @Override    public int getWidth(int imageIndex) throws IOException    {        if (imageIndex < 0 || imageIndex >= getNumImages(true))            throw new IllegalArgumentException(                this.getClass().getName() + ".getWidth(): illegal imageIndex: " + imageIndex);        if (ifds.size() == 0)            readIFDs();                TiffIFDEntry widthEntry = getByTag(ifds.get(imageIndex), TiffTags.IMAGE_WIDTH);        return (int) widthEntry.asLong();    }    @Override    public int getHeight(int imageIndex) throws IOException    {        if (imageIndex < 0 || imageIndex >= getNumImages(true))            throw new IllegalArgumentException(                this.getClass().getName() + ".getHeight(): illegal imageIndex: " + imageIndex);        if (ifds.size() == 0)            readIFDs();        TiffIFDEntry heightEntry = getByTag(ifds.get(imageIndex), TiffTags.IMAGE_LENGTH);        return (int) heightEntry.asLong();    }    @Override    public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException    {        throw new UnsupportedOperationException("Not supported yet.");    }    @Override    public IIOMetadata getStreamMetadata() throws IOException    {        throw new UnsupportedOperationException("Not supported yet.");    }    @Override    public IIOMetadata getImageMetadata(int imageIndex) throws IOException    {        throw new UnsupportedOperationException("Not supported yet.");    }    @Override    public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException    {        // TODO: For this first implementation, we are completely ignoring the ImageReadParam given to us.        //       Our target functionality is not the entire ImageIO, but only that needed to support the static        //       read method ImageIO.read("myImage.tif").        // TODO: more generally, the following test should reflect that more than one image is possible in a Tiff.        if (imageIndex != 0)            throw new IllegalArgumentException(                this.getClass().getName() + ".read(): illegal imageIndex: " + imageIndex);        readIFDs();        // Extract the various IFD tags we need to read this image...        TiffIFDEntry widthEntry = null;        TiffIFDEntry lengthEntry = null;        TiffIFDEntry bitsPerSampleEntry = null;        TiffIFDEntry samplesPerPixelEntry = null;        TiffIFDEntry photoInterpEntry = null;        TiffIFDEntry stripOffsetsEntry = null;        TiffIFDEntry stripCountsEntry = null;        TiffIFDEntry rowsPerStripEntry = null;        TiffIFDEntry planarConfigEntry = null;        TiffIFDEntry colorMapEntry = null;        TiffIFDEntry sampleFormatEntry = null;        TiffIFDEntry[] ifd = ifds.get(imageIndex);        for (TiffIFDEntry entry : ifd)        {            switch (entry.tag)            {                case TiffTags.IMAGE_WIDTH:                    widthEntry = entry;                    break;                case TiffTags.IMAGE_LENGTH:                    lengthEntry = entry;                    break;                case TiffTags.BITS_PER_SAMPLE:                    bitsPerSampleEntry = entry;                    break;                case TiffTags.SAMPLES_PER_PIXEL:                    samplesPerPixelEntry = entry;                    break;                case TiffTags.PHOTO_INTERPRETATION:                    photoInterpEntry = entry;                    break;                case TiffTags.STRIP_OFFSETS:                    stripOffsetsEntry = entry;                    break;                case TiffTags.STRIP_BYTE_COUNTS:                    stripCountsEntry = entry;                    break;                case TiffTags.ROWS_PER_STRIP:                    rowsPerStripEntry = entry;                    break;                case TiffTags.PLANAR_CONFIGURATION:                    planarConfigEntry = entry;                    break;                case TiffTags.COLORMAP:                    colorMapEntry = entry;                    break;                case TiffTags.SAMPLE_FORMAT:                    sampleFormatEntry = entry;                    break;            }        }        // Check that we have the mandatory tags present...        if (widthEntry == null || lengthEntry == null || samplesPerPixelEntry == null || photoInterpEntry == null ||            stripOffsetsEntry == null || stripCountsEntry == null || rowsPerStripEntry == null            || planarConfigEntry == null)            throw new IIOException(this.getClass().getName() + ".read(): unable to decipher image organization");        int width = (int) widthEntry.asLong();        int height = (int) lengthEntry.asLong();        int samplesPerPixel = (int) samplesPerPixelEntry.asLong();        long photoInterp = photoInterpEntry.asLong();        long rowsPerStrip = rowsPerStripEntry.asLong();        long planarConfig = planarConfigEntry.asLong();        int[] bitsPerSample = getBitsPerSample(bitsPerSampleEntry);        long[] stripOffsets = getStripsArray(stripOffsetsEntry);        long[] stripCounts = getStripsArray(stripCountsEntry);        ColorModel colorModel;        WritableRaster raster;        //        // TODO: This isn't terribly robust; we know how to deal with a few specific types...        //        if (samplesPerPixel == 1 && bitsPerSample.length == 1 && bitsPerSample[0] == 16)        {            // 16-bit grayscale (typical of elevation data, for example)...            long sampleFormat =                (sampleFormatEntry != null) ? sampleFormatEntry.asLong() : TiffConstants.SAMPLEFORMAT_UNSIGNED;            int dataBuffType =                (sampleFormat == TiffConstants.SAMPLEFORMAT_SIGNED) ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;            colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), bitsPerSample, false,                false, Transparency.OPAQUE, dataBuffType);            int[] offsets = new int[]{0};            ComponentSampleModel sampleModel = new ComponentSampleModel(dataBuffType, width, height, 1, width, offsets);            short[][] imageData = readPlanar16(width, height, samplesPerPixel, stripOffsets, stripCounts, rowsPerStrip);            DataBuffer dataBuff = (dataBuffType == DataBuffer.TYPE_SHORT) ?                new DataBufferShort(imageData, width * height, offsets) :                new DataBufferUShort(imageData, width * height, offsets);            raster = Raster.createWritableRaster(sampleModel, dataBuff, new Point(0, 0));        }        else if (samplesPerPixel == 1 && bitsPerSample.length == 1 && bitsPerSample[0] == 32 &&            sampleFormatEntry != null && sampleFormatEntry.asLong() == TiffConstants.SAMPLEFORMAT_IEEEFLOAT)        {            // 32-bit grayscale (typical of elevation data, for example)...            colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), bitsPerSample, false,                false, Transparency.OPAQUE, DataBuffer.TYPE_FLOAT);            int[] offsets = new int[]{0};            ComponentSampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_FLOAT, width, height, 1, width,                offsets);            float[][] imageData = readPlanarFloat32(width, height, samplesPerPixel, stripOffsets, stripCounts,                rowsPerStrip);            DataBuffer dataBuff = new DataBufferFloat(imageData, width * height, offsets);            raster = Raster.createWritableRaster(sampleModel, dataBuff, new Point(0, 0));        }        else        {            // make sure a DataBufferByte is going to do the trick            for (int bits : bitsPerSample)            {                if (bits != 8)                    throw new IIOException(this.getClass().getName() + ".read(): only expecting 8 bits/sample; found " +                        bits);            }            // byte image data; could be RGB-component, grayscale, or indexed-color.            // Set up an appropriate ColorModel...            colorModel = null;            if (samplesPerPixel > 1)            {                int transparency = Transparency.OPAQUE;                boolean hasAlpha = false;                if (samplesPerPixel == 4)                {                    transparency = Transparency.TRANSLUCENT;                    hasAlpha = true;                }                colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), bitsPerSample,                    hasAlpha,                    false, transparency, DataBuffer.TYPE_BYTE);            }            else            {                // grayscale or indexed-color?                if (photoInterp == TiffConstants.PHOTOINTERP_PALETTE)                {                    // indexed...                    if (colorMapEntry == null)                        throw new IIOException(                            this.getClass().getName() + ".read(): no ColorMap found for indexed image type");                    byte[][] cmap = readColorMap(colorMapEntry);                    colorModel = new IndexColorModel(bitsPerSample[0], (int) colorMapEntry.count / 3, cmap[0], cmap[1],                        cmap[2]);                }                else                {                    // grayscale...                    colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), bitsPerSample,                        false,                        false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);                }            }            int[] bankOffsets = new int[samplesPerPixel];            for (int i = 0; i < samplesPerPixel; i++)            {                bankOffsets[i] = i;            }            int[] offsets = new int[(planarConfig == TiffConstants.PLANARCONFIG_CHUNKY) ? 1 : samplesPerPixel];            for (int i = 0; i < offsets.length; i++)            {                offsets[i] = 0;            }            // construct the right SampleModel...            ComponentSampleModel sampleModel;            if (samplesPerPixel == 1)                sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, bankOffsets);            else                sampleModel = (planarConfig == TiffConstants.PLANARCONFIG_CHUNKY) ?                    new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height, samplesPerPixel,                        width * samplesPerPixel, bankOffsets) :                    new BandedSampleModel(DataBuffer.TYPE_BYTE, width, height, width, bankOffsets, offsets);            // Get the image data and make our Raster...            byte[][] imageData;            if (planarConfig == TiffConstants.PLANARCONFIG_CHUNKY)                imageData = readPixelInterleaved8(width, height, samplesPerPixel, stripOffsets, stripCounts);            else                imageData = readPlanar8(width, height, samplesPerPixel, stripOffsets, stripCounts, rowsPerStrip);            DataBufferByte dataBuff = new DataBufferByte(imageData, width * height, offsets);            raster = Raster.createWritableRaster(sampleModel, dataBuff, new Point(0, 0));        }        /**************************************/        decodeGeotiffInfo();        /**************************************/        // Finally, put it all together to get our BufferedImage...        return new BufferedImage(colorModel, raster, false, null);    }    private void decodeGeotiffInfo() throws IOException    {        readIFDs();        TiffIFDEntry[] ifd = ifds.get(0);        for (TiffIFDEntry entry : ifd)        {            switch (entry.tag)            {                case TiffTags.MODEL_PIXELSCALE:                    geoPixelScale = readDoubles(entry);                    break;                case TiffTags.MODEL_TIEPOINT:                    geoTiePoints = readDoubles(entry);                    break;                case TiffTags.MODEL_TRANSFORMATION:                    geoMatrix = readDoubles(entry);                    break;                case TiffTags.GEO_KEY_DIRECTORY:                    readGeoKeys(entry);                    break;                case TiffTags.GEO_DOUBLE_PARAMS:                    break;                case TiffTags.GEO_ASCII_PARAMS:                    break;            }        }    }    /*     * Coordinates reading all the ImageFileDirectories in a Tiff file (there's typically only one).     *      */    private void readIFDs() throws IOException    {        if (this.theStream != null)            return;        if (super.input == null || !(super.input instanceof ImageInputStream))        {            throw new IIOException(this.getClass().getName() + ": null/invalid ImageInputStream");        }        this.theStream = (ImageInputStream) super.input;        // determine byte ordering...        byte[] ifh = new byte[2];  // Tiff image-file header        try        {            theStream.readFully(ifh);

⌨️ 快捷键说明

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