use of nitf.DownSampler 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);
}
}
use of nitf.DownSampler 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);
}
}
Aggregations