Search in sources :

Example 1 with PixelSkipDownSampler

use of nitf.PixelSkipDownSampler 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 2 with PixelSkipDownSampler

use of nitf.PixelSkipDownSampler 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)

Aggregations

Point (java.awt.Point)2 IOException (java.io.IOException)2 ByteBuffer (java.nio.ByteBuffer)2 ArrayList (java.util.ArrayList)2 IIOException (javax.imageio.IIOException)2 DownSampler (nitf.DownSampler)2 ImageSubheader (nitf.ImageSubheader)2 NITFException (nitf.NITFException)2 PixelSkipDownSampler (nitf.PixelSkipDownSampler)2 SubWindow (nitf.SubWindow)2 DoubleBuffer (java.nio.DoubleBuffer)1 FloatBuffer (java.nio.FloatBuffer)1 ShortBuffer (java.nio.ShortBuffer)1