Skip to content
Snippets Groups Projects
Commit 1cd3087b authored by Vojtech Moravec's avatar Vojtech Moravec
Browse files

Add new loader type, FlatBufferLoader.

This loader is quite similiar to ImageJBufferLoader, except that
different plane data are stored in a single flat array.

To handle this situation with different loader help us prevent future
IndexOutOfBounds exceptions.
parent e9b22de2
No related branches found
No related tags found
No related merge requests found
package azgracompress.io;
import azgracompress.data.V3i;
/**
* Input data backed by the single buffer object.
* In this buffer all the dataset pixels are stored.
*/
public class FlatBufferInputData extends InputData {
/**
* Reference to the buffer.
*/
private final Object imageBuffer;
/**
* Name of the image used in caching.
*/
private final String cacheHint;
/**
* Create input data backed by buffer object.
*
* @param imageBuffer Image buffer reference.
* @param imageDimensions Image dimensions.
* @param pixelType Image pixel type.
* @param cacheHint Name of the image used in caching.
*/
public FlatBufferInputData(final Object imageBuffer,
final V3i imageDimensions,
final PixelType pixelType,
final String cacheHint) {
this.imageBuffer = imageBuffer;
setDataLoaderType(DataLoaderType.ImageJBufferLoader);
setDimension(imageDimensions);
setPixelType(pixelType);
this.cacheHint = cacheHint;
}
/**
* Get buffer with the image plane data.
*
* @return Pointer to pixel buffer.
*/
public Object getPixelBuffer() {
return imageBuffer;
}
@Override
public String getCacheFileName() {
return cacheHint;
}
}
package azgracompress.io.loader;
import azgracompress.data.Range;
import azgracompress.data.V2i;
import azgracompress.data.V3i;
import azgracompress.io.FlatBufferInputData;
import azgracompress.utilities.TypeConverter;
import java.io.IOException;
import java.util.Arrays;
/**
* This loader is used when the entire dataset is stored in single buffer (array).
*/
public class FlatBufferLoader extends BasicLoader implements IPlaneLoader {
/**
* Flat buffer information.
*/
private final FlatBufferInputData bufferInputData;
/**
* Pixel count in single plane.
*/
private final int planePixelCount;
public FlatBufferLoader(final FlatBufferInputData bufferDataInfo) {
super(bufferDataInfo.getDimensions());
this.bufferInputData = bufferDataInfo;
planePixelCount = dims.getX() * dims.getY();
}
@Override
public boolean supportParallelLoading() {
return true;
}
private void copyShortArrayIntoBuffer(short[] srcArray,
final int srcOffset,
int[] destBuffer,
final int destOffset,
final int copyLen) {
for (int i = 0; i < copyLen; i++) {
destBuffer[destOffset + i] = TypeConverter.shortToInt(srcArray[srcOffset + i]);
}
}
@Override
protected int valueAt(final int plane, final int offset) {
return TypeConverter.shortToInt(((short[]) bufferInputData.getPixelBuffer())[(plane * planePixelCount) + offset]);
}
@Override
public int[] loadPlaneData(final int plane) throws IOException {
final short[] flatBuffer = ((short[]) bufferInputData.getPixelBuffer());
final int offset = plane * planePixelCount;
final int[] planeData = new int[planePixelCount];
for (int i = 0; i < planePixelCount; i++) {
planeData[i] = TypeConverter.shortToInt(flatBuffer[offset + i]);
}
return planeData;
}
@Override
public int[] loadPlanesU16Data(final int[] planes) throws IOException {
if (planes.length < 1) {
return new int[0];
} else if (planes.length == 1) {
return loadPlaneData(planes[0]);
} else if (planes.length == bufferInputData.getDimensions().getZ()) { // Maybe?
return loadAllPlanesU16Data();
}
final long totalValueCount = (long) planePixelCount * (long) planes.length;
if (totalValueCount > (long) Integer.MAX_VALUE) {
throw new IOException("Unable to load image data for planes, file size is too big.");
}
Arrays.sort(planes);
final short[] flatBuffer = (short[]) bufferInputData.getPixelBuffer();
int[] destBuffer = new int[(int) totalValueCount];
int destOffset = 0;
for (final int planeIndex : planes) {
final int planeOffset = planeIndex * planePixelCount;
copyShortArrayIntoBuffer(flatBuffer, planeOffset, destBuffer, destOffset, planePixelCount);
destOffset += planePixelCount;
}
return destBuffer;
}
@Override
public int[] loadAllPlanesU16Data() {
final short[] flatBuffer = (short[]) bufferInputData.getPixelBuffer();
return TypeConverter.shortArrayToIntArray(flatBuffer);
}
@Override
public int[][] loadRowVectors(final int vectorSize, final Range<Integer> planeRange) {
return loadRowVectorsImplByValueAt(vectorSize, planeRange);
}
@Override
public int[][] loadBlocks(final V2i blockDim, final Range<Integer> planeRange) {
return loadBlocksImplByValueAt(blockDim, planeRange);
}
@Override
public int[][] loadVoxels(final V3i voxelDim, final Range<Integer> planeRange) throws IOException {
return loadVoxelsImplByValueAt(voxelDim, planeRange);
}
}
......@@ -2,6 +2,7 @@ package azgracompress.io.loader;
import azgracompress.io.BufferInputData;
import azgracompress.io.FileInputData;
import azgracompress.io.FlatBufferInputData;
import azgracompress.io.InputData;
public final class PlaneLoaderFactory {
......@@ -21,6 +22,8 @@ public final class PlaneLoaderFactory {
return new SCIFIOLoader((FileInputData) inputDataInfo);
case ImageJBufferLoader:
return new ImageJBufferLoader((BufferInputData) inputDataInfo);
case FlatBufferLoader:
return new FlatBufferLoader((FlatBufferInputData) inputDataInfo);
default:
throw new Exception("Unsupported data loader.");
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment