Search in sources :

Example 1 with ImageSubheader

use of nitf.ImageSubheader in project imageio-ext by geosolutions-it.

the class NITFReader method readRaster.

/*
     * Returns the ACTUAL data from the image. Note: for anything other than byte or int, this is NOT viewable. This is used for getting the actual
     * data. (non-Javadoc)
     * 
     * @see javax.imageio.ImageReader#readRaster(int, javax.imageio.ImageReadParam)
     */
@Override
public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException {
    checkIndex(imageIndex);
    Rectangle sourceRegion = new Rectangle();
    Rectangle destRegion = new Rectangle();
    computeRegions(param, getWidth(imageIndex), getHeight(imageIndex), null, sourceRegion, destRegion);
    // Set everything to default values
    int sourceXSubsampling = param != null ? param.getSourceXSubsampling() : 1;
    int sourceYSubsampling = param != null ? param.getSourceYSubsampling() : 1;
    Point destinationOffset = param != null ? param.getDestinationOffset() : new Point(0, 0);
    ImageSubheader subheader;
    try {
        subheader = record.getImages()[imageIndex].getSubheader();
    } catch (NITFException e) {
        throw new IOException(e);
    }
    String irep = subheader.getImageRepresentation().getStringData().trim();
    String pvType = subheader.getPixelValueType().getStringData().trim();
    int nbpp = subheader.getNumBitsPerPixel().getIntData();
    int bandCount = subheader.getBandCount();
    // make the band offsets array, for the output
    int[] bandOffsets = null;
    int[] sourceBands = param != null ? param.getSourceBands() : null;
    if (param != null && param.getDestinationBands() != null) {
        bandOffsets = param.getDestinationBands();
    } else if (param != null && sourceBands != null) {
        bandOffsets = new int[sourceBands.length];
        for (int i = 0; i < bandOffsets.length; i++) {
            bandOffsets[i] = sourceBands[i];
        }
    } else {
        // Setup band offsets -- TODO should we really read ALL bands by
        // default?
        bandOffsets = new int[bandCount];
        for (int i = 0; i < bandOffsets.length; i++) bandOffsets[i] = i;
    }
    int nBytes = ((nbpp - 1) / 8) + 1;
    int bufType = -1;
    // byte
    if (nBytes == 1) {
        bufType = DataBuffer.TYPE_BYTE;
    } else // short
    if (nBytes == 2) {
        bufType = DataBuffer.TYPE_USHORT;
    } else // float
    if (nBytes == 4 && pvType.equals("R")) {
        bufType = DataBuffer.TYPE_FLOAT;
    } else // double
    if (nBytes == 8 && pvType.equals("R")) {
        bufType = DataBuffer.TYPE_DOUBLE;
    } else {
        throw new UnsupportedOperationException("not yet implemented");
    }
    WritableRaster ras = ImageIOUtils.makeGenericPixelInterleavedWritableRaster(destRegion.width, destRegion.height, bandOffsets.length, bufType);
    checkReadParamBandSettings(param, bandCount, ras.getSampleModel().getNumBands());
    readRaster(imageIndex, sourceRegion, destRegion, sourceXSubsampling, sourceYSubsampling, bandOffsets, nBytes, destinationOffset, ras);
    return ras;
}
Also used : ImageSubheader(nitf.ImageSubheader) WritableRaster(java.awt.image.WritableRaster) NITFException(nitf.NITFException) Rectangle(java.awt.Rectangle) Point(java.awt.Point) IIOException(javax.imageio.IIOException) IOException(java.io.IOException) Point(java.awt.Point)

Example 2 with ImageSubheader

use of nitf.ImageSubheader in project imageio-ext by geosolutions-it.

the class NITFReader method readFullImage.

/**
 * Optimization to read the entire image in one fell swoop... This is most likely the common use case for this codec, so we hope this optimization
 * will be helpful.
 *
 * @param imageIndex
 * @param sourceXSubsampling
 * @param sourceYSubsampling
 * @param bandOffsets
 * @param pixelSize
 * @param imRas
 * @throws IOException
 */
protected void readFullImage(int imageIndex, Rectangle destRegion, int sourceXSubsampling, int sourceYSubsampling, int[] bandOffsets, int pixelSize, WritableRaster imRas) throws IOException {
    try {
        ImageSubheader subheader = record.getImages()[imageIndex].getSubheader();
        int numCols = destRegion.width;
        int numRows = destRegion.height;
        int nBands = subheader.getBandCount();
        /*
             * NOTE: This is a "fix" that will be removed once the underlying NITRO library gets patched. Currently, if you make a request of a single
             * band, it doesn't matter which band you request - the data from the first band will be returned regardless. This is obviously wrong. To
             * thwart this, we will read all bands, then scale down what we return to the user based on their actual request.
             */
        int[] requestBands = bandOffsets;
        /*
             * if (nBands != bandOffsets.length && bandOffsets.length == 1 && bandOffsets[0] != 0) { requestBands = new int[nBands]; for (int i = 0; i
             * < nBands; ++i) requestBands[i] = i; }
             */
        int bufSize = numCols * numRows * pixelSize;
        byte[][] imageBuf = new byte[requestBands.length][bufSize];
        // make a SubWindow from the params
        // TODO may want to read by blocks or rows to make faster and more
        // memory efficient
        SubWindow window;
        window = new SubWindow();
        window.setNumBands(requestBands.length);
        window.setBandList(requestBands);
        window.setNumCols(numCols);
        window.setNumRows(numRows);
        window.setStartCol(0);
        window.setStartRow(0);
        // the NITRO library can do the subsampling for us
        if (sourceYSubsampling != 1 || sourceXSubsampling != 1) {
            DownSampler downSampler = new PixelSkipDownSampler(sourceYSubsampling, sourceXSubsampling);
            window.setDownSampler(downSampler);
        }
        // String pixelJustification = subheader.getPixelJustification()
        // .getStringData().trim();
        // boolean shouldSwap = pixelJustification.equals("R");
        // since this is Java, we need the data in big-endian format
        // boolean shouldSwap = ByteOrder.nativeOrder() !=
        // ByteOrder.BIG_ENDIAN;
        nitf.ImageReader imageReader = getImageReader(imageIndex);
        imageReader.read(window, imageBuf);
        List<ByteBuffer> bandBufs = new ArrayList<ByteBuffer>();
        for (int i = 0; i < bandOffsets.length; ++i) {
            ByteBuffer bandBuf = null;
            // the special "fix" we added needs to do this
            if (bandOffsets.length != requestBands.length) {
                bandBuf = ByteBuffer.wrap(imageBuf[bandOffsets[i]]);
            } else {
                bandBuf = ByteBuffer.wrap(imageBuf[i]);
            }
            // ban dBuf.order(ByteOrder.nativeOrder());
            // shouldSwap ? ByteOrder.LITTLE_ENDIAN
            // : ByteOrder.BIG_ENDIAN);
            bandBufs.add(bandBuf);
        }
        // optimization for 1 band case... just dump the whole thing
        if (bandOffsets.length == 1) {
            ByteBuffer bandBuf = bandBufs.get(0);
            switch(pixelSize) {
                case 1:
                    ByteBuffer rasterByteBuf = ByteBuffer.wrap(((DataBufferByte) imRas.getDataBuffer()).getData());
                    rasterByteBuf.put(bandBuf);
                    break;
                case 2:
                    ShortBuffer rasterShortBuf = ShortBuffer.wrap(((DataBufferUShort) imRas.getDataBuffer()).getData());
                    rasterShortBuf.put(bandBuf.asShortBuffer());
                    break;
                case 4:
                    FloatBuffer rasterFloatBuf = FloatBuffer.wrap(((DataBufferFloat) imRas.getDataBuffer()).getData());
                    rasterFloatBuf.put(bandBuf.asFloatBuffer());
                    break;
                case 8:
                    DoubleBuffer rasterDoubleBuf = DoubleBuffer.wrap(((DataBufferDouble) imRas.getDataBuffer()).getData());
                    rasterDoubleBuf.put(bandBuf.asDoubleBuffer());
                    break;
            }
        } else {
            for (int srcY = 0, srcX = 0; srcY < numRows; srcY++) {
                // Copy each (subsampled) source pixel into imRas
                for (int dstX = 0; dstX < numCols; srcX += pixelSize, dstX++) {
                    for (int i = 0; i < bandOffsets.length; ++i) {
                        ByteBuffer bandBuf = bandBufs.get(i);
                        switch(pixelSize) {
                            case 1:
                                imRas.setSample(dstX, srcY, i, bandBuf.get(srcX));
                                break;
                            case 2:
                                imRas.setSample(dstX, srcY, i, bandBuf.getShort(srcX));
                                break;
                            case 4:
                                imRas.setSample(dstX, srcY, i, bandBuf.getFloat(srcX));
                                break;
                            case 8:
                                imRas.setSample(dstX, srcY, i, bandBuf.getDouble(srcX));
                                break;
                        }
                    }
                }
            }
        }
    } catch (NITFException e1) {
        throw new IOException(e1);
    }
}
Also used : DoubleBuffer(java.nio.DoubleBuffer) ArrayList(java.util.ArrayList) FloatBuffer(java.nio.FloatBuffer) IIOException(javax.imageio.IIOException) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) Point(java.awt.Point) DownSampler(nitf.DownSampler) PixelSkipDownSampler(nitf.PixelSkipDownSampler) ImageSubheader(nitf.ImageSubheader) NITFException(nitf.NITFException) PixelSkipDownSampler(nitf.PixelSkipDownSampler) SubWindow(nitf.SubWindow) ShortBuffer(java.nio.ShortBuffer)

Example 3 with ImageSubheader

use of nitf.ImageSubheader in project imageio-ext by geosolutions-it.

the class NITFReader method readRaster.

/**
 * Reads image data as bytes for the given region, and writes it to the given writable raster
 *
 * @param sourceRegion
 * @param sourceXSubsampling
 * @param sourceYSubsampling
 * @param bandOffsets
 * @param destinationOffset
 * @param imRas
 * @return Raster
 * @throws IOException
 */
protected void readRaster(int imageIndex, Rectangle sourceRegion, Rectangle destRegion, int sourceXSubsampling, int sourceYSubsampling, int[] bandOffsets, int pixelSize, Point destinationOffset, WritableRaster imRas) throws IOException {
    checkIndex(imageIndex);
    try {
        ImageSubheader subheader = record.getImages()[imageIndex].getSubheader();
        int numCols = subheader.getNumCols().getIntData();
        int numRows = subheader.getNumRows().getIntData();
        // image at once
        if ((destRegion.height * sourceYSubsampling) == numRows && (destRegion.width * sourceXSubsampling) == numCols) {
            readFullImage(imageIndex, destRegion, sourceXSubsampling, sourceYSubsampling, bandOffsets, pixelSize, imRas);
            return;
        } else // the general purpose case
        {
            int colBytes = destRegion.width * pixelSize;
            int dstMinX = imRas.getMinX();
            int dstMaxX = dstMinX + imRas.getWidth() - 1;
            int dstMinY = imRas.getMinY();
            int dstMaxY = dstMinY + imRas.getHeight() - 1;
            // int swap = 0;
            int nBands = subheader.getBandCount();
            /*
                 * NOTE: This is a "fix" that will be removed once the underlying NITRO library gets patched. Currently, if you make a request of a
                 * single band, it doesn't matter which band you request - the data from the first band will be returned regardless. This is obviously
                 * wrong. To thwart this, we will read all bands, then scale down what we return to the user based on their actual request.
                 */
            int[] requestBands = new int[nBands];
            for (int i = 0; i < nBands; ++i) requestBands[i] = i;
            byte[][] rowBuf = new byte[requestBands.length][colBytes];
            // make a SubWindow from the params
            // TODO may want to read by blocks or rows to make faster and
            // more
            // memory efficient
            SubWindow window;
            window = new SubWindow();
            window.setNumBands(requestBands.length);
            window.setBandList(requestBands);
            window.setNumCols(destRegion.width);
            window.setNumRows(1);
            window.setStartCol(sourceRegion.x);
            window.setStartRow(sourceRegion.y);
            // the NITRO library can do the subsampling for us
            if (sourceYSubsampling != 1 || sourceXSubsampling != 1) {
                DownSampler downSampler = new PixelSkipDownSampler(sourceYSubsampling, sourceXSubsampling);
                window.setDownSampler(downSampler);
            }
            // String pixelJustification = record.getImages()[imageIndex]
            // .getSubheader().getPixelJustification().getStringData()
            // .trim();
            // swap = pixelJustification.equals("R") ? 1 : 0;
            List<ByteBuffer> bandBufs = new ArrayList<ByteBuffer>();
            for (int i = 0; i < requestBands.length; ++i) {
                ByteBuffer bandBuf = null;
                bandBuf = ByteBuffer.wrap(rowBuf[i]);
                // bandBuf.order(ByteOrder.nativeOrder());
                // bandBuf.order(swap == 0 ? ByteOrder.BIG_ENDIAN
                // : ByteOrder.LITTLE_ENDIAN);
                bandBufs.add(bandBuf);
            }
            nitf.ImageReader imageReader = getImageReader(imageIndex);
            for (int srcY = 0; srcY < sourceRegion.height; srcY++) {
                if (sourceYSubsampling != 1 && (srcY % sourceYSubsampling) != 0)
                    continue;
                window.setStartRow(sourceRegion.y + srcY);
                // Read the row
                try {
                    imageReader.read(window, rowBuf);
                } catch (NITFException e) {
                    throw new IIOException("Error reading line " + srcY, e);
                }
                // Determine where the row will go in the destination
                int dstY = destinationOffset.y + srcY / sourceYSubsampling;
                if (dstY < dstMinY) {
                    // The row is above imRas
                    continue;
                }
                if (dstY > dstMaxY) {
                    // We're done with the image
                    break;
                }
                // Copy each (subsampled) source pixel into imRas
                for (int srcX = 0, dstX = destinationOffset.x; srcX < colBytes; srcX += pixelSize, dstX++) {
                    if (dstX < dstMinX) {
                        continue;
                    }
                    if (dstX > dstMaxX) {
                        break;
                    }
                    for (int i = 0; i < bandOffsets.length; ++i) {
                        ByteBuffer bandBuf = bandBufs.get(bandOffsets[i]);
                        switch(pixelSize) {
                            case 1:
                                imRas.setSample(dstX, dstY, i, bandBuf.get(srcX));
                                break;
                            case 2:
                                imRas.setSample(dstX, dstY, i, bandBuf.getShort(srcX));
                                break;
                            case 4:
                                imRas.setSample(dstX, dstY, i, bandBuf.getFloat(srcX));
                                break;
                            case 8:
                                imRas.setSample(dstX, dstY, i, bandBuf.getDouble(srcX));
                                break;
                        }
                    }
                }
            }
        }
    } catch (NITFException e1) {
        throw new IOException(e1);
    }
}
Also used : ArrayList(java.util.ArrayList) IIOException(javax.imageio.IIOException) IIOException(javax.imageio.IIOException) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) Point(java.awt.Point) DownSampler(nitf.DownSampler) PixelSkipDownSampler(nitf.PixelSkipDownSampler) ImageSubheader(nitf.ImageSubheader) NITFException(nitf.NITFException) PixelSkipDownSampler(nitf.PixelSkipDownSampler) SubWindow(nitf.SubWindow)

Example 4 with ImageSubheader

use of nitf.ImageSubheader in project imageio-ext by geosolutions-it.

the class NITFImageWriter method addImageSegment.

/**
 * Setup the ImageSegment
 *
 * @param record
 * @param images
 * @param fis
 * @param compression
 * @return
 * @throws NITFException
 * @throws IOException
 */
private static void addImageSegment(final Record record, final List<ImageWrapper> images, final FileImageInputStreamExt fis, final WriteCompression compression) throws NITFException, IOException {
    ImageSegment segment = null;
    ImageSubheader subheader = null;
    int img = 0;
    // Using a loop for future usage of the cloudCover image
    for (ImageWrapper image : images) {
        // Getting compression parameter and imageProperties
        WriteCompression writeCompression = img == 0 ? compression : WriteCompression.UNCOMPRESSED;
        segment = record.newImageSegment();
        // Setting up the image Sub Header
        subheader = segment.getSubheader();
        double bpppb = initImageSubHeader(image, subheader, writeCompression, fis);
        if (img == 0) {
            initTREs(subheader, image, writeCompression, bpppb);
        }
        img++;
    }
}
Also used : ImageSegment(nitf.ImageSegment) ImageSubheader(nitf.ImageSubheader) ImageWrapper(it.geosolutions.imageio.plugins.nitronitf.wrapper.ImageWrapper) WriteCompression(it.geosolutions.imageio.plugins.nitronitf.NITFUtilities.WriteCompression)

Example 5 with ImageSubheader

use of nitf.ImageSubheader in project imageio-ext by geosolutions-it.

the class NITFReader method read.

@Override
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
    readHeader();
    Raster raster = readRaster(imageIndex, param);
    // get the requested number of destination bands (or 0 for all)
    int numDestBands = param != null ? (param.getDestinationBands() != null ? param.getDestinationBands().length : param.getSourceBands() != null ? param.getSourceBands().length : 0) : 0;
    // try to find a good match for the specifier
    ImageTypeSpecifier imageType = null, firstType = null;
    Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
    while (imageTypes.hasNext() && imageType == null) {
        ImageTypeSpecifier currentImageType = imageTypes.next();
        if (firstType == null)
            firstType = currentImageType;
        if (currentImageType.getNumBands() == numDestBands)
            imageType = currentImageType;
    }
    if (imageType == null) {
        if (firstType == null)
            throw new IOException("Unable to determine the ImageTypeSpecifier");
        else
            imageType = firstType;
    }
    try {
        ImageSubheader subheader = record.getImages()[imageIndex].getSubheader();
        String pvType = subheader.getPixelValueType().getStringData().trim();
        int nbpp = subheader.getNumBitsPerPixel().getIntData();
        int nBytes = ((nbpp - 1) / 8) + 1;
        if (nBytes == 1 || nBytes == 2 || (nBytes == 4 && pvType.equals("R")) || (nBytes == 8 && pvType.equals("R"))) {
            return ImageIOUtils.rasterToBufferedImage(raster, imageType);
        }
    } catch (NITFException e) {
        throw new IOException(e);
    }
    throw new UnsupportedOperationException("Image pixel type or bits per pixel not yet supported");
}
Also used : ImageSubheader(nitf.ImageSubheader) Raster(java.awt.image.Raster) WritableRaster(java.awt.image.WritableRaster) NITFException(nitf.NITFException) IIOException(javax.imageio.IIOException) IOException(java.io.IOException) Point(java.awt.Point) ImageTypeSpecifier(javax.imageio.ImageTypeSpecifier)

Aggregations

ImageSubheader (nitf.ImageSubheader)6 Point (java.awt.Point)5 NITFException (nitf.NITFException)5 IOException (java.io.IOException)4 IIOException (javax.imageio.IIOException)4 ArrayList (java.util.ArrayList)3 WritableRaster (java.awt.image.WritableRaster)2 ByteBuffer (java.nio.ByteBuffer)2 ImageTypeSpecifier (javax.imageio.ImageTypeSpecifier)2 DownSampler (nitf.DownSampler)2 PixelSkipDownSampler (nitf.PixelSkipDownSampler)2 SubWindow (nitf.SubWindow)2 WriteCompression (it.geosolutions.imageio.plugins.nitronitf.NITFUtilities.WriteCompression)1 ImageWrapper (it.geosolutions.imageio.plugins.nitronitf.wrapper.ImageWrapper)1 Rectangle (java.awt.Rectangle)1 ColorSpace (java.awt.color.ColorSpace)1 Raster (java.awt.image.Raster)1 DoubleBuffer (java.nio.DoubleBuffer)1 FloatBuffer (java.nio.FloatBuffer)1 ShortBuffer (java.nio.ShortBuffer)1