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

Use two version of loadVoxels.

Add second version of loadVoxels in BasicLoader. One version uses the
valueAt() function. Loaders using this version can access plane pixels
very fast.

Other loaders needs to load the whole plane first. This is the case of
RawDataLoader and maybe SCIFIOLoader, for those the plane access time is
higher, so they use the loadPlaneData() function.
parent ca78105e
No related branches found
No related tags found
No related merge requests found
package azgracompress.io.loader;
import azgracompress.data.V3i;
import azgracompress.data.Voxel;
import java.io.IOException;
......@@ -20,59 +21,78 @@ public abstract class BasicLoader {
*/
public abstract int[] loadPlaneData(final int plane) throws IOException;
/**
* Check whether the coordinates are inside voxel of dimension `dims`.
*
* @param x Zero based x coordinate.
* @param y Zero based y coordinate.
* @param z Zero based z coordinate.
* @return True if coordinates are inside this voxel.
*/
protected boolean isInsideVoxel(final int x, final int y, final int z) {
return (((x >= 0) && (x < dims.getX())) && (y >= 0) && (y < dims.getY()) && (z >= 0) && (z < dims.getZ()));
}
protected abstract int valueAt(final int plane, final int offset);
/**
* Calculate the index inside data array for this voxel.
*
* @param x Zero based x coordinate.
* @param y Zero based y coordinate.
* @param z Zero based z coordinate.
* @return Index inside data array.
*/
protected int voxelDataIndex(final int x, final int y, final int z) {
return voxelDataIndex(x, y, z, dims);
}
/**
* Calculate the index inside data array for voxel of given dimensions.
* Load dataset into voxel data.
*
* @param x Zero based x coordinate.
* @param y Zero based y coordinate.
* @param z Zero based z coordinate.
* @param voxelDims Chunk dimensions.
* @return Index inside chunk dimension data array.
* @param voxelDim Single voxel dimensions.
* @return Voxel data arranged in arrays.
* @throws IOException When fails to load plane data.
*/
protected int voxelDataIndex(final int x, final int y, final int z, final V3i voxelDims) {
assert (x >= 0 && x < voxelDims.getX()) : "Index X out of bounds.";
assert (y >= 0 && y < voxelDims.getY()) : "Index Y out of bounds.";
assert (z >= 0 && z < voxelDims.getZ()) : "Index Z out of bounds.";
protected int[][] loadVoxelsImplByLoadPlaneData(final V3i voxelDim) throws IOException {
final Voxel voxel = new Voxel(voxelDim);
final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDim.getX());
final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDim.getY());
return (z * (voxelDims.getX() * voxelDims.getY())) + (y * voxelDims.getX()) + x;
}
/**
* Calculate required voxel count, which are needed when dividing dataset to voxels of given size.
*
* @param datasetDims Dataset dimensions.
* @param voxelDims One voxel dimensions.
* @return Number of voxels needed to divide the dataset.
*/
public static int calculateRequiredVoxelCount(final V3i datasetDims, final V3i voxelDims) {
final int xChunkCount = (int) Math.ceil((double) datasetDims.getX() / (double) voxelDims.getX());
final int yChunkCount = (int) Math.ceil((double) datasetDims.getY() / (double) voxelDims.getY());
final int zChunkCount = (int) Math.ceil((double) datasetDims.getZ() / (double) voxelDims.getZ());
return (xChunkCount * yChunkCount * zChunkCount);
int[][] voxels = new int[Voxel.calculateRequiredVoxelCount(dims, voxelDim)][(int) voxelDim.multiplyTogether()];
final int workerCount = 4;
final int workSize = dims.getZ() / workerCount;
Thread[] workers = new Thread[workerCount];
final int dimX = dims.getX();
final int dimY = dims.getY();
final int voxelDimX = voxelDim.getX();
final int voxelDimY = voxelDim.getY();
final int voxelDimZ = voxelDim.getZ();
for (int wId = 0; wId < workerCount; wId++) {
final int fromZ = wId * workSize;
final int toZ = (wId == workerCount - 1) ? dims.getZ() : (workSize + (wId * workSize));
System.out.printf("%d-%d\n", fromZ, toZ);
workers[wId] = new Thread(() -> {
int dstZ, dstY, dstX, voxelX, voxelY, voxelZ, voxelIndex;
int[] planeData;
for (int srcZ = fromZ; srcZ < toZ; srcZ++) {
try {
planeData = loadPlaneData(srcZ);
} catch (IOException e) {
e.printStackTrace();
break;
}
dstZ = srcZ / voxelDimZ;
voxelZ = srcZ - (dstZ * voxelDimZ);
for (int srcY = 0; srcY < dimY; srcY++) {
dstY = srcY / voxelDimY;
voxelY = srcY - (dstY * voxelDimY);
for (int srcX = 0; srcX < dimX; srcX++) {
dstX = srcX / voxelDimX;
voxelX = srcX - (dstX * voxelDimX);
voxelIndex = (dstZ * (xVoxelCount * yVoxelCount)) + (dstY * xVoxelCount) + dstX;
voxels[voxelIndex][voxel.dataIndex(voxelX, voxelY, voxelZ, voxelDim)] = planeData[(srcY * dimX) + srcX];
}
}
}
});
workers[wId].start();
}
try {
for (int wId = 0; wId < workerCount; wId++) {
workers[wId].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return voxels;
}
/**
......@@ -82,35 +102,59 @@ public abstract class BasicLoader {
* @return Voxel data arranged in arrays.
* @throws IOException When fails to load plane data.
*/
protected int[][] loadVoxelsImplGray16(final V3i voxelDim) throws IOException {
protected int[][] loadVoxelsImplByValueAt(final V3i voxelDim) throws IOException {
final Voxel voxel = new Voxel(voxelDim);
final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDim.getX());
final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDim.getY());
int[][] voxels = new int[calculateRequiredVoxelCount(dims, voxelDim)][(int) voxelDim.multiplyTogether()];
int[][] voxels = new int[Voxel.calculateRequiredVoxelCount(dims, voxelDim)][(int) voxelDim.multiplyTogether()];
final int workerCount = 4;
final int workSize = dims.getZ() / workerCount;
Thread[] workers = new Thread[workerCount];
int dstZ, dstY, dstX, voxelX, voxelY, voxelZ, voxelIndex;
final int dimX = dims.getX();
final int dimY = dims.getY();
final int voxelDimX = voxelDim.getX();
final int voxelDimY = voxelDim.getY();
final int voxelDimZ = voxelDim.getZ();
for (int srcZ = 0; srcZ < dims.getZ(); srcZ++) {
// TODO(Moravec): Try to simplify the math inside, which is slowing the process.
final int[] srcPlaneBuffer = loadPlaneData(srcZ);
for (int wId = 0; wId < workerCount; wId++) {
final int fromZ = wId * workSize;
final int toZ = (wId == workerCount - 1) ? dims.getZ() : (workSize + (wId * workSize));
// System.out.printf("%d-%d\n", fromZ, toZ);
workers[wId] = new Thread(() -> {
int dstZ, dstY, dstX, voxelX, voxelY, voxelZ, voxelIndex;
dstZ = srcZ / voxelDim.getZ();
voxelZ = srcZ - (dstZ * voxelDim.getZ());
for (int srcZ = fromZ; srcZ < toZ; srcZ++) {
dstZ = srcZ / voxelDimZ;
voxelZ = srcZ - (dstZ * voxelDimZ);
for (int srcY = 0; srcY < dims.getY(); srcY++) {
dstY = srcY / voxelDim.getY();
voxelY = srcY - (dstY * voxelDim.getY());
for (int srcY = 0; srcY < dimY; srcY++) {
dstY = srcY / voxelDimY;
voxelY = srcY - (dstY * voxelDimY);
for (int srcX = 0; srcX < dims.getX(); srcX++) {
dstX = srcX / voxelDim.getX();
voxelX = srcX - (dstX * voxelDim.getX());
voxelIndex = (dstZ * (xVoxelCount * yVoxelCount)) + (dstY * xVoxelCount) + dstX;
for (int srcX = 0; srcX < dimX; srcX++) {
dstX = srcX / voxelDimX;
voxelX = srcX - (dstX * voxelDimX);
voxelIndex = (dstZ * (xVoxelCount * yVoxelCount)) + (dstY * xVoxelCount) + dstX;
voxels[voxelIndex][voxelDataIndex(voxelX, voxelY, voxelZ, voxelDim)] = srcPlaneBuffer[(srcY * dims.getX()) + srcX];
voxels[voxelIndex][voxel.dataIndex(voxelX, voxelY, voxelZ, voxelDim)] = valueAt(srcZ, (srcY * dimX) + srcX);
}
}
}
});
workers[wId].start();
}
try {
for (int wId = 0; wId < workerCount; wId++) {
workers[wId].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return voxels;
}
......
......@@ -30,6 +30,13 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
return TypeConverter.shortArrayToIntArray(srcBuffer);
}
@Override
protected int valueAt(int plane, int offset) {
final short value = ((short[]) bufferInputData.getPixelBuffer(plane))[offset];
return TypeConverter.shortToInt(value);
// return ((value & 0xFF00) | (value & 0x00FF));
}
@Override
public int[] loadPlanesU16Data(int[] planes) throws IOException {
if (planes.length < 1) {
......@@ -81,7 +88,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
@Override
public int[][] loadVoxels(final V3i voxelDim) throws IOException {
return loadVoxelsImplGray16(voxelDim);
return loadVoxelsImplByValueAt(voxelDim);
}
}
......@@ -46,6 +46,12 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
return TypeConverter.unsignedShortBytesToIntArray(buffer);
}
@Override
protected int valueAt(int plane, int offset) {
// TODO: Implement me!
return 0;
}
@Override
public int[] loadPlanesU16Data(int[] planes) throws IOException {
if (planes.length < 1) {
......@@ -117,6 +123,6 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
@Override
public int[][] loadVoxels(V3i voxelDim) throws IOException {
return loadVoxelsImplGray16(voxelDim);
return loadVoxelsImplByLoadPlaneData(voxelDim);
}
}
......@@ -39,6 +39,12 @@ public final class SCIFIOLoader extends BasicLoader implements IPlaneLoader {
return TypeConverter.unsignedShortBytesToIntArray(planeBytes);
}
@Override
protected int valueAt(int plane, int offset) {
// TODO: Implement me!
return 0;
}
@Override
public int[] loadPlanesU16Data(int[] planes) throws IOException {
if (planes.length < 1) {
......@@ -106,7 +112,7 @@ public final class SCIFIOLoader extends BasicLoader implements IPlaneLoader {
@Override
public int[][] loadVoxels(final V3i voxelDim) throws IOException {
return loadVoxelsImplGray16(voxelDim);
return loadVoxelsImplByLoadPlaneData(voxelDim);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment