diff --git a/src/main/java/cz/it4i/qcmp/benchmark/Benchmark.java b/src/main/java/cz/it4i/qcmp/benchmark/Benchmark.java
index 117259ddf6704a5c36f96730554c1a056aefee88..4012de9f9e49f7e5ddf274510fb8dcfd44d7e031 100644
--- a/src/main/java/cz/it4i/qcmp/benchmark/Benchmark.java
+++ b/src/main/java/cz/it4i/qcmp/benchmark/Benchmark.java
@@ -51,7 +51,7 @@ public class Benchmark extends BenchmarkBase {
return;
}
- decompressOps.setInputDataInfo(new FileInputData(qcmpFilePath));
+ decompressOps.setInputDataInfo(new FileInputData(qcmpFilePath, null));
final String decompressedFile = getFileNamePathIntoOutDir(String.format(QUANTIZED_FILE_TEMPLATE,
options.getInputDataInfo().getPlaneIndex(),
diff --git a/src/main/java/cz/it4i/qcmp/benchmark/BenchmarkBase.java b/src/main/java/cz/it4i/qcmp/benchmark/BenchmarkBase.java
index 2e7cf835fcae750b43316e80823a8d43c33cfbc1..6fc7dabf844b60c0573eb749496efd8d2633020d 100644
--- a/src/main/java/cz/it4i/qcmp/benchmark/BenchmarkBase.java
+++ b/src/main/java/cz/it4i/qcmp/benchmark/BenchmarkBase.java
@@ -2,8 +2,8 @@ package cz.it4i.qcmp.benchmark;
import cz.it4i.qcmp.cli.CompressionOptionsCLIParser;
import cz.it4i.qcmp.compression.CompressionOptions;
+import cz.it4i.qcmp.data.HyperStackDimensions;
import cz.it4i.qcmp.data.ImageU16;
-import cz.it4i.qcmp.data.V3i;
import cz.it4i.qcmp.io.InputData;
import cz.it4i.qcmp.io.RawDataIO;
import cz.it4i.qcmp.quantization.QTrainIteration;
@@ -26,7 +26,7 @@ abstract class BenchmarkBase {
protected final String inputFile;
protected final String outputDirectory;
protected final int[] planes;
- protected final V3i rawImageDims;
+ protected final HyperStackDimensions rawImageDims;
protected final int codebookSize;
protected final String cacheFolder;
@@ -60,9 +60,8 @@ abstract class BenchmarkBase {
this.planes[i] = from + i;
}
} else {
- final int planeCount = ifi.getDimensions().getZ();
- this.planes = new int[planeCount];
- for (int i = 0; i < planeCount; i++) {
+ this.planes = new int[ifi.getDimensions().getPlaneCount()];
+ for (int i = 0; i < ifi.getDimensions().getPlaneCount(); i++) {
this.planes[i] = i;
}
}
@@ -118,11 +117,11 @@ abstract class BenchmarkBase {
* @return True if file was saved.
*/
protected boolean saveQuantizedPlaneData(final int[] data, final String filename) {
- final ImageU16 img = new ImageU16(rawImageDims.getX(), rawImageDims.getY(), data);
+ final ImageU16 img = new ImageU16(rawImageDims.getWidth(), rawImageDims.getHeight(), data);
try {
// NOTE(Moravec): Use big endian so that FIJI can read the image.
RawDataIO.writeImageU16(getFileNamePathIntoOutDir(filename), img, false);
- System.out.println(String.format("Saved %s", filename));
+ System.out.printf("Saved %s\n", filename);
} catch (final Exception e) {
e.printStackTrace();
return false;
@@ -146,8 +145,8 @@ abstract class BenchmarkBase {
final String diffFilePath = getFileNamePathIntoOutDir(diffFile);
final String absDiffFilePath = getFileNamePathIntoOutDir(absDiffFile);
- final ImageU16 img = new ImageU16(rawImageDims.getX(),
- rawImageDims.getY(),
+ final ImageU16 img = new ImageU16(rawImageDims.getWidth(),
+ rawImageDims.getHeight(),
absDifferenceData);
try {
// NOTE(Moravec): Use little endian so that gnuplot can read the array.
diff --git a/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java b/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java
index a90c39df9e4534578e3a5e16539ca96818c702b5..5d99107ca84674d8bf564c85f938b06287cf58eb 100644
--- a/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java
+++ b/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java
@@ -54,7 +54,7 @@ public class SQBenchmark extends BenchmarkBase {
quantizer = new ScalarQuantizer(codebook);
System.out.println("Created quantizer from cache");
} else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
- final int middlePlaneIndex = rawImageDims.getZ() / 2;
+ final int middlePlaneIndex = rawImageDims.getPlaneCount() / 2;
final int[] middlePlaneData;
try {
diff --git a/src/main/java/cz/it4i/qcmp/benchmark/VQBenchmark.java b/src/main/java/cz/it4i/qcmp/benchmark/VQBenchmark.java
index 33e0a361be7dc68fc882ad89624fde17234caf5f..f595914ff789e54adea975a46a85b6b0d2c7e340 100644
--- a/src/main/java/cz/it4i/qcmp/benchmark/VQBenchmark.java
+++ b/src/main/java/cz/it4i/qcmp/benchmark/VQBenchmark.java
@@ -19,7 +19,7 @@ public class VQBenchmark extends BenchmarkBase {
private ImageU16 reconstructImageFromQuantizedVectors(final int[][] vectors,
final V2i qVector) {
- final Block reconstructedChunk = new Block(new V2i(rawImageDims.getX(), rawImageDims.getY()));
+ final Block reconstructedChunk = new Block(rawImageDims.getPlaneDimensions());
if (qVector.getY() > 1) {
reconstructedChunk.reconstructFrom2DVectors(vectors, qVector);
} else {
diff --git a/src/main/java/cz/it4i/qcmp/cli/functions/EntropyCalculation.java b/src/main/java/cz/it4i/qcmp/cli/functions/EntropyCalculation.java
index d58a61e5ed7d53a13972f2f767fb1bbb8213dd95..b01629a950fd026ef984ee28190c6f13e75f6742 100644
--- a/src/main/java/cz/it4i/qcmp/cli/functions/EntropyCalculation.java
+++ b/src/main/java/cz/it4i/qcmp/cli/functions/EntropyCalculation.java
@@ -36,7 +36,7 @@ public class EntropyCalculation extends CustomFunctionBase {
reportWriter.write("Plane;Entropy\n");
- for (int planeIndex = 0; planeIndex < options.getInputDataInfo().getDimensions().getZ(); planeIndex++) {
+ for (int planeIndex = 0; planeIndex < options.getInputDataInfo().getDimensions().getPlaneCount(); planeIndex++) {
final int[] planeData = loader.loadPlaneData(planeIndex);
final double planeEntropy = Utils.calculateEntropy(planeData);
diff --git a/src/main/java/cz/it4i/qcmp/cli/functions/MeasurePlaneErrorFunction.java b/src/main/java/cz/it4i/qcmp/cli/functions/MeasurePlaneErrorFunction.java
index b3db0bca79bc5b2932a739b4d1599346ef41858b..9c6772a2a779a133419b54b0471c88982657f6cf 100644
--- a/src/main/java/cz/it4i/qcmp/cli/functions/MeasurePlaneErrorFunction.java
+++ b/src/main/java/cz/it4i/qcmp/cli/functions/MeasurePlaneErrorFunction.java
@@ -2,7 +2,7 @@ package cz.it4i.qcmp.cli.functions;
import cz.it4i.qcmp.cli.CompressionOptionsCLIParser;
import cz.it4i.qcmp.cli.CustomFunctionBase;
-import cz.it4i.qcmp.data.V3i;
+import cz.it4i.qcmp.data.HyperStackDimensions;
import cz.it4i.qcmp.io.FileInputData;
import cz.it4i.qcmp.io.loader.RawDataLoader;
import cz.it4i.qcmp.utilities.Stopwatch;
@@ -20,12 +20,10 @@ public class MeasurePlaneErrorFunction extends CustomFunctionBase {
private final String OriginalFileForChannel0 = "D:\\biology\\tiff_data\\fused_tp_10_ch_0_16bit.raw";
private final String OriginalFileForChannel1 = "D:\\biology\\tiff_data\\fused_tp_10_ch_1_16bit.raw";
- private final V3i ReferenceFileDimensions = new V3i(1041, 996, 946);
+ private final HyperStackDimensions ReferenceFileDimensions = new HyperStackDimensions(1041, 996, 946);
- private int[][] loadPlanes(final String srcFile, final V3i imageDims) throws IOException {
- final FileInputData inputDataInfo = new FileInputData(srcFile);
- inputDataInfo.setDimension(imageDims);
- final RawDataLoader loader = new RawDataLoader(inputDataInfo);
+ private int[][] loadPlanes(final String srcFile, final HyperStackDimensions imageDims) throws IOException {
+ final RawDataLoader loader = new RawDataLoader(new FileInputData(srcFile, imageDims));
return loader.loadAllPlanesTo2DArray();
}
@@ -132,10 +130,10 @@ public class MeasurePlaneErrorFunction extends CustomFunctionBase {
reportWriter.write("=========================================\n");
reportWriter.write("PlaneIndex;ErrorSum;MeanError\n");
- final int planePixelCount = ReferenceFileDimensions.toV2i().multiplyTogether();
+ final int planePixelCount = ReferenceFileDimensions.getNumberOfElementsInDimension(2);
final int[] diffData = new int[planePixelCount];
- for (int plane = 0; plane < ReferenceFileDimensions.getZ(); plane++) {
+ for (int plane = 0; plane < ReferenceFileDimensions.getPlaneCount(); plane++) {
Utils.differenceToArray(referenceData[plane], testData[plane], diffData);
Utils.applyAbsFunction(diffData);
diff --git a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
index 2df7a95306a9114e5c99b6c0d0cf2fe3ca6eabf8..22b328d64310d8764bcc1b61f1cfa15909aecc02 100644
--- a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
+++ b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
@@ -119,7 +119,7 @@ public abstract class CompressorDecompressorBase {
}
return indices;
} else {
- return generateAllPlaneIndices(inputData.getDimensions().getZ());
+ return generateAllPlaneIndices(inputData.getDimensions().getPlaneCount());
}
}
@@ -144,7 +144,7 @@ public abstract class CompressorDecompressorBase {
* @return Index of the middle plane.
*/
protected int getMiddlePlaneIndex() {
- return (options.getInputDataInfo().getDimensions().getZ() / 2);
+ return (options.getInputDataInfo().getDimensions().getPlaneCount() / 2);
}
/**
diff --git a/src/main/java/cz/it4i/qcmp/compression/ImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/ImageCompressor.java
index 61d5d45b5fdcd5e83f04004589f818736156d911..a7cd2ddac5a717c6007d7f0fe1e00ce166035544 100644
--- a/src/main/java/cz/it4i/qcmp/compression/ImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/ImageCompressor.java
@@ -131,7 +131,7 @@ public class ImageCompressor extends CompressorDecompressorBase {
}
duplicateAllListeners(imageCompressor);
- long[] planeDataSizes = null;
+ final long[] planeDataSizes;
try (final FileOutputStream fos = new FileOutputStream(options.getOutputFilePath(), false);
final DataOutputStream compressStream = new DataOutputStream(new BufferedOutputStream(fos, 8192))) {
@@ -193,7 +193,7 @@ public class ImageCompressor extends CompressorDecompressorBase {
final Range<Integer> planeRange = options.getInputDataInfo().getPlaneRange();
return ((planeRange.getTo() + 1) - planeRange.getFrom());
} else {
- return options.getInputDataInfo().getDimensions().getZ();
+ return options.getInputDataInfo().getDimensions().getPlaneCount();
}
}
@@ -225,8 +225,8 @@ public class ImageCompressor extends CompressorDecompressorBase {
header.setCodebookPerPlane(options.getCodebookType() == CompressionOptions.CodebookType.Individual);
- header.setImageSizeX(options.getInputDataInfo().getDimensions().getX());
- header.setImageSizeY(options.getInputDataInfo().getDimensions().getY());
+ header.setImageSizeX(options.getInputDataInfo().getDimensions().getWidth());
+ header.setImageSizeY(options.getInputDataInfo().getDimensions().getHeight());
header.setImageSizeZ(getNumberOfPlanes());
header.setVectorDimension(options.getQuantizationVector());
diff --git a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
index 78f9cbe214b3c8b1bc7c7ddabef02742b0f5c4b9..00ac7628818a6dd0371f380cae8955cd3ed0842b 100644
--- a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
@@ -203,7 +203,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
int[] trainData = null;
if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
- final int middlePlaneIndex = inputDataInfo.getDimensions().getZ() / 2;
+ final int middlePlaneIndex = getMiddlePlaneIndex();
reportStatusToListeners("Loading single plane data.");
trainData = planeLoader.loadPlaneData(middlePlaneIndex);
} else if (inputDataInfo.isPlaneIndexSet()) {
diff --git a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
index 60182aabc588020639bb3d3b39a1029d1a7813af..2a064ebc40c98e83d14630b7feac63803c34bbae 100644
--- a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
@@ -185,9 +185,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
if (streamMode) {
try {
// Image dimensions
- compressStream.writeShort(inputData.getDimensions().getX());
- compressStream.writeShort(inputData.getDimensions().getY());
- compressStream.writeShort(inputData.getDimensions().getZ());
+ compressStream.writeShort(inputData.getDimensions().getWidth());
+ compressStream.writeShort(inputData.getDimensions().getHeight());
+ compressStream.writeShort(inputData.getDimensions().getPlaneCount());
// Write voxel layer in stream mode.
compressStream.writeShort(planeIndices.length);
@@ -266,13 +266,13 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
}
final int voxelLayerDepth = options.getQuantizationVector().getZ();
- final int voxelLayerCount = calculateVoxelLayerCount(inputData.getDimensions().getZ(), voxelLayerDepth);
+ final int voxelLayerCount = calculateVoxelLayerCount(inputData.getDimensions().getPlaneCount(), voxelLayerDepth);
if (streamMode) {
try {
// Image dimensions
- compressStream.writeShort(inputData.getDimensions().getX());
- compressStream.writeShort(inputData.getDimensions().getY());
- compressStream.writeShort(inputData.getDimensions().getZ());
+ compressStream.writeShort(inputData.getDimensions().getWidth());
+ compressStream.writeShort(inputData.getDimensions().getHeight());
+ compressStream.writeShort(inputData.getDimensions().getPlaneCount());
// Write voxel layer in stream mode.
compressStream.writeShort(voxelLayerCount);
@@ -294,7 +294,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final int fromZ = (voxelLayerIndex * voxelLayerDepth);
final int toZ = (voxelLayerIndex == voxelLayerCount - 1)
- ? inputData.getDimensions().getZ()
+ ? inputData.getDimensions().getPlaneCount()
: (voxelLayerDepth + (voxelLayerIndex * voxelLayerDepth));
assert (toZ >= fromZ);
@@ -407,7 +407,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
int[][] loadDataForCodebookTraining(final IPlaneLoader planeLoader) throws ImageCompressionException {
final int[][] trainingData;
if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
- final int middlePlaneIndex = (options.getInputDataInfo().getDimensions().getZ() / 2);
+ final int middlePlaneIndex = getMiddlePlaneIndex();
trainingData = planeLoader.loadVectorsFromPlaneRange(options, new Range<>(middlePlaneIndex, middlePlaneIndex + 1));
} else if (options.getInputDataInfo().isPlaneIndexSet()) {
reportStatusToListeners("VQ: Loading single plane data.");
@@ -419,7 +419,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
} else {
reportStatusToListeners("VQ: Loading all planes data.");
trainingData = planeLoader.loadVectorsFromPlaneRange(options,
- new Range<>(0, options.getInputDataInfo().getDimensions().getZ()));
+ new Range<>(0,
+ options.getInputDataInfo().getDimensions().getPlaneCount()));
}
return trainingData;
}
diff --git a/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java b/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java
index 78a71be436c958544f02845ac3b66561f7581b29..101a5f5d2099fdc3a62a00558f22d7be5127296c 100644
--- a/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java
+++ b/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java
@@ -9,72 +9,107 @@ import java.util.Objects;
public class HyperStackDimensions {
private final int width;
private final int height;
- private final int sliceCount;
+ private final int planeCount;
private final int numberOfTimepoints;
/**
* Create HyperStackDimensions.
*
- * @param width Width of the slice.
- * @param height Height of the slice.
- * @param sliceCount Slice count in the stack.
+ * @param width Width of the plane.
+ * @param height Height of the plane.
+ * @param planeCount Plane count in the stack.
* @param numberOfTimepoints Number of stack timepoints.
*/
- public HyperStackDimensions(final int width, final int height, final int sliceCount, final int numberOfTimepoints) {
+ public HyperStackDimensions(final int width, final int height, final int planeCount, final int numberOfTimepoints) {
this.width = width;
this.height = height;
- this.sliceCount = sliceCount;
+ this.planeCount = planeCount;
this.numberOfTimepoints = numberOfTimepoints;
}
+ /**
+ * Get number of elements in hyperstack with dimensionality = dimension.
+ * When calculating the element count, overflow is checked. This is because result of this
+ * function is usually used in places where we want to allocate memory.
+ *
+ * @param dimension Maximum dimension.
+ * @return Number of elements.
+ */
+ @SuppressWarnings("DuplicateExpressions")
+ public int getNumberOfElementsInDimension(final int dimension) {
+ switch (dimension) {
+ case 1:
+ return width;
+ case 2:
+ return Math.multiplyExact(width, height);
+ case 3:
+ return Math.multiplyExact(planeCount, Math.multiplyExact(width, height));
+ case 4:
+ return Math.multiplyExact(numberOfTimepoints, Math.multiplyExact(planeCount, Math.multiplyExact(width, height)));
+ default:
+ assert (false) : "Wrong dimension in getNumberOfElementsInDimension";
+ return -1;
+ }
+ }
+
/**
* Create HyperStackDimensions for single timepoint.
*
- * @param width Width of the slice.
- * @param height Height of the slice.
- * @param sliceCount Slice count in the stack.
+ * @param width Width of the plane.
+ * @param height Height of the plane.
+ * @param planeCount Plane count in the stack.
*/
- public HyperStackDimensions(final int width, final int height, final int sliceCount) {
- this(width, height, sliceCount, 1);
+ public HyperStackDimensions(final int width, final int height, final int planeCount) {
+ this(width, height, planeCount, 1);
}
/**
- * Create HyperStackDimensions for single slice and single timepoint.
+ * Create HyperStackDimensions for single plane and single timepoint.
*
- * @param width Width of the slice.
- * @param height Height of the slice.
+ * @param width Width of the plane.
+ * @param height Height of the plane.
*/
public HyperStackDimensions(final int width, final int height) {
this(width, height, 1, 1);
}
/**
- * Get single slice width. (X)
+ * Get single plane width. (X)
*
- * @return Slice width.
+ * @return Plane width.
*/
public final int getWidth() {
return width;
}
/**
- * Get single slice height. (Y)
+ * Get single plane height. (Y)
*
- * @return Slice height.
+ * @return Plane height.
*/
public final int getHeight() {
return height;
}
/**
- * Get slice count. (Z, Plane Count)
+ * Get plane count. (Z)
*
- * @return Slice count.
+ * @return Plane count.
*/
- public final int getSliceCount() {
- return sliceCount;
+ public final int getPlaneCount() {
+ return planeCount;
}
+ /**
+ * Get dimensions of the single plane.
+ *
+ * @return Plane dimensions.
+ */
+ public V2i getPlaneDimensions() {
+ return new V2i(width, height);
+ }
+
+
/**
* Get number of timepoints of the stack.
*
@@ -86,12 +121,12 @@ public class HyperStackDimensions {
@Override
public String toString() {
- return String.format("X=%d;Y=%d;Z=%d;T=%d", width, height, sliceCount, numberOfTimepoints);
+ return String.format("X=%d;Y=%d;Z=%d;T=%d", width, height, planeCount, numberOfTimepoints);
}
@Override
public int hashCode() {
- return Objects.hash(width, height, sliceCount, numberOfTimepoints);
+ return Objects.hash(width, height, planeCount, numberOfTimepoints);
}
@Override
@@ -99,7 +134,7 @@ public class HyperStackDimensions {
if (obj instanceof HyperStackDimensions) {
final HyperStackDimensions other = (HyperStackDimensions) obj;
return (width == other.width && height == other.height &&
- sliceCount == other.sliceCount && numberOfTimepoints == other.numberOfTimepoints);
+ planeCount == other.planeCount && numberOfTimepoints == other.numberOfTimepoints);
}
return super.equals(obj);
}
diff --git a/src/main/java/cz/it4i/qcmp/data/V2i.java b/src/main/java/cz/it4i/qcmp/data/V2i.java
index aca7fe528e3fe2be6e23cc62337c877f3afe5493..fa9a4862fbbd7e24d084f1ceb4cf438755a25b70 100644
--- a/src/main/java/cz/it4i/qcmp/data/V2i.java
+++ b/src/main/java/cz/it4i/qcmp/data/V2i.java
@@ -22,6 +22,6 @@ public final class V2i extends V2<Integer> {
}
public final int multiplyTogether() {
- return getX() * getY();
+ return Math.multiplyExact(getX(), getY());
}
}
diff --git a/src/main/java/cz/it4i/qcmp/data/V3i.java b/src/main/java/cz/it4i/qcmp/data/V3i.java
index b75767215a4a956d37e55f27d9ed01be0c33908d..50d760cb96bab8567d20a884abb2c1ef6d542f03 100644
--- a/src/main/java/cz/it4i/qcmp/data/V3i.java
+++ b/src/main/java/cz/it4i/qcmp/data/V3i.java
@@ -32,7 +32,7 @@ public final class V3i extends V3<Integer> {
return new V2i(getX(), getY());
}
- public final long multiplyTogether() {
- return ((long) getX() * (long) getY() * (long) getZ());
+ public final int multiplyTogether() {
+ return Math.multiplyExact(getZ(), Math.multiplyExact(getX(), getY()));
}
}
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/CallbackLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/CallbackLoader.java
index 629ac238110453a8e7aacbf0ff7f34432fa3df1f..a6b370b8154b6997032504350a88101a49060e69 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/CallbackLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/CallbackLoader.java
@@ -8,7 +8,7 @@ import cz.it4i.qcmp.io.CallbackInputData;
import java.io.IOException;
import java.util.Arrays;
-public class CallbackLoader extends BasicLoader implements IPlaneLoader {
+public class CallbackLoader extends GenericLoader implements IPlaneLoader {
private final CallbackInputData callbackInputData;
private final CallbackInputData.LoadCallback pixelLoad;
@@ -27,12 +27,12 @@ public class CallbackLoader extends BasicLoader implements IPlaneLoader {
@Override
public int[] loadPlaneData(final int plane) {
- final int planePixelCount = dims.getX() * dims.getY();
+ final int planePixelCount = dims.getNumberOfElementsInDimension(2);
final int[] planeData = new int[planePixelCount];
int index = 0;
- for (int y = 0; y < dims.getY(); y++) {
- for (int x = 0; x < dims.getX(); x++) {
+ for (int y = 0; y < dims.getHeight(); y++) {
+ for (int x = 0; x < dims.getWidth(); x++) {
planeData[index++] = pixelLoad.getValueAt(x, y, plane);
}
}
@@ -45,10 +45,10 @@ public class CallbackLoader extends BasicLoader implements IPlaneLoader {
return new int[0];
} else if (planes.length == 1) {
return loadPlaneData(planes[0]);
- } else if (planes.length == dims.getZ()) {
+ } else if (planes.length == dims.getPlaneCount()) {
return loadAllPlanesU16Data();
}
- final int planePixelCount = dims.getX() * dims.getY();
+ final int planePixelCount = dims.getNumberOfElementsInDimension(2);
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.");
@@ -59,8 +59,8 @@ public class CallbackLoader extends BasicLoader implements IPlaneLoader {
final int[] destBuffer = new int[(int) totalValueCount];
int index = 0;
for (final int plane : planes) {
- for (int y = 0; y < dims.getY(); y++) {
- for (int x = 0; x < dims.getX(); x++) {
+ for (int y = 0; y < dims.getHeight(); y++) {
+ for (int x = 0; x < dims.getWidth(); x++) {
destBuffer[index++] = pixelLoad.getValueAt(x, y, plane);
}
}
@@ -69,17 +69,14 @@ public class CallbackLoader extends BasicLoader implements IPlaneLoader {
}
@Override
- public int[] loadAllPlanesU16Data() throws IOException {
- final long totalValueCount = dims.multiplyTogether();
- if (totalValueCount > (long) Integer.MAX_VALUE) {
- throw new IOException("Unable to load all image data, file size is too big.");
- }
+ public int[] loadAllPlanesU16Data() {
+ final long totalValueCount = dims.getNumberOfElementsInDimension(3);
final int[] destBuffer = new int[(int) totalValueCount];
int index = 0;
- for (int z = 0; z < dims.getZ(); z++) {
- for (int y = 0; y < dims.getY(); y++) {
- for (int x = 0; x < dims.getX(); x++) {
+ for (int z = 0; z < dims.getPlaneCount(); z++) {
+ for (int y = 0; y < dims.getHeight(); y++) {
+ for (int x = 0; x < dims.getWidth(); x++) {
destBuffer[index++] = pixelLoad.getValueAt(x, y, z);
}
}
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/FlatBufferLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/FlatBufferLoader.java
index a5b60bb7760ce1da573da626625eeb9c6212cfc4..c580c0e62eecc88ee6e1fb2c7a8fa8f70db7dafa 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/FlatBufferLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/FlatBufferLoader.java
@@ -13,7 +13,7 @@ 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 {
+public class FlatBufferLoader extends GenericLoader implements IPlaneLoader {
/**
* Flat buffer information.
*/
@@ -27,7 +27,7 @@ public class FlatBufferLoader extends BasicLoader implements IPlaneLoader {
public FlatBufferLoader(final FlatBufferInputData bufferDataInfo) {
super(bufferDataInfo.getDimensions());
this.bufferInputData = bufferDataInfo;
- planePixelCount = dims.getX() * dims.getY();
+ planePixelCount = dims.getNumberOfElementsInDimension(2);
}
@Override
@@ -68,18 +68,15 @@ public class FlatBufferLoader extends BasicLoader implements IPlaneLoader {
return new int[0];
} else if (planes.length == 1) {
return loadPlaneData(planes[0]);
- } else if (planes.length == bufferInputData.getDimensions().getZ()) { // Maybe?
+ } else if (planes.length == bufferInputData.getDimensions().getPlaneCount()) {
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.");
- }
+ final int totalValueCount = Math.multiplyExact(planePixelCount, planes.length);
Arrays.sort(planes);
final short[] flatBuffer = (short[]) bufferInputData.getPixelBuffer();
- final int[] destBuffer = new int[(int) totalValueCount];
+ final int[] destBuffer = new int[totalValueCount];
int destOffset = 0;
for (final int planeIndex : planes) {
final int planeOffset = planeIndex * planePixelCount;
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/BasicLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/GenericLoader.java
similarity index 80%
rename from src/main/java/cz/it4i/qcmp/io/loader/BasicLoader.java
rename to src/main/java/cz/it4i/qcmp/io/loader/GenericLoader.java
index a5bac1b035d88aac8927868dcee26f0f9a0a6150..8363538bf2dcf2809ebc5f4bd733045bece0d781 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/BasicLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/GenericLoader.java
@@ -4,21 +4,20 @@ import cz.it4i.qcmp.data.*;
import java.io.IOException;
-public abstract class BasicLoader {
- protected final V3i dims;
+abstract class GenericLoader {
+ protected final HyperStackDimensions dims;
protected int threadCount = 1;
private DataWrappingStrategy wrappingStrategy = DataWrappingStrategy.MirroredRepeat;
- protected BasicLoader(final V3i datasetDims) {
+ protected GenericLoader(final HyperStackDimensions datasetDims) {
this.dims = datasetDims;
}
- public V3i getImageDimensions() {
+ public HyperStackDimensions getDatasetDimensions() {
return dims;
}
-
public DataWrappingStrategy getWrappingStrategy() {
return wrappingStrategy;
}
@@ -37,19 +36,6 @@ public abstract class BasicLoader {
*/
public abstract int[] loadPlaneData(final int plane) throws IOException;
- // /**
- // * Read value from plane at specified offset.
- // *
- // * @param plane Zero based plane index.
- // * @param offset Offset on flattened plane data.
- // * @return Plane value at the index.
- // */
- // protected int valueAt(final int plane, final int offset) {
- // new Exception().printStackTrace(System.err);
- // assert (false) : "Unimplemented overload of BasicLoader::valueAt()";
- // return Integer.MIN_VALUE;
- // }
-
protected abstract int valueAt(final int plane, final int x, final int y, final int width);
/**
@@ -60,9 +46,9 @@ public abstract class BasicLoader {
*/
private int wrapColumnIndex(final int x) {
if (wrappingStrategy == DataWrappingStrategy.ClampToEdge) {
- return dims.getX() - 1;
+ return dims.getWidth() - 1;
} else if (wrappingStrategy == DataWrappingStrategy.MirroredRepeat) {
- return (dims.getX() - (1 + (x % dims.getX())));
+ return (dims.getWidth() - (1 + (x % dims.getWidth())));
}
return x;
}
@@ -75,9 +61,9 @@ public abstract class BasicLoader {
*/
private int wrapRowIndex(final int y) {
if (wrappingStrategy == DataWrappingStrategy.ClampToEdge) {
- return dims.getY() - 1;
+ return dims.getHeight() - 1;
} else if (wrappingStrategy == DataWrappingStrategy.MirroredRepeat) {
- return (dims.getY() - (1 + (y % dims.getY())));
+ return (dims.getHeight() - (1 + (y % dims.getHeight())));
}
return y;
}
@@ -90,17 +76,17 @@ public abstract class BasicLoader {
*/
private int wrapPlaneIndex(final int z) {
if (wrappingStrategy == DataWrappingStrategy.ClampToEdge) {
- return dims.getZ() - 1;
+ return dims.getPlaneCount() - 1;
} else if (wrappingStrategy == DataWrappingStrategy.MirroredRepeat) {
- return (dims.getZ() - (1 + (z % dims.getZ())));
+ return (dims.getPlaneCount() - (1 + (z % dims.getPlaneCount())));
}
return z;
}
protected int[][] loadRowVectorsImplByLoadPlaneData(final int vectorSize, final Range<Integer> planeRange) throws IOException {
- final int rowVectorCount = (int) Math.ceil((double) dims.getX() / (double) vectorSize);
+ final int rowVectorCount = (int) Math.ceil((double) dims.getWidth() / (double) vectorSize);
final int planeCount = planeRange.getTo() - planeRange.getFrom();
- final int vectorCount = planeCount * dims.getY() * rowVectorCount;
+ final int vectorCount = planeCount * dims.getHeight() * rowVectorCount;
final int[][] rowVectors = new int[vectorCount][vectorSize];
int vectorIndex = 0;
@@ -108,19 +94,19 @@ public abstract class BasicLoader {
for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) {
final int[] planeData = loadPlaneData(plane);
- for (int row = 0; row < dims.getY(); row++) {
+ for (int row = 0; row < dims.getHeight(); row++) {
for (int rowVectorIndex = 0; rowVectorIndex < rowVectorCount; rowVectorIndex++) {
// Copy single vector.
baseX = rowVectorIndex * vectorSize;
for (int vectorX = 0; vectorX < vectorSize; vectorX++) {
srcX = baseX + vectorX;
- if (srcX >= dims.getX()) {
+ if (srcX >= dims.getWidth()) {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank)
break;
srcX = wrapColumnIndex(srcX);
}
- rowVectors[vectorIndex][vectorX] = planeData[Block.index(srcX, row, dims.getX())];
+ rowVectors[vectorIndex][vectorX] = planeData[Block.index(srcX, row, dims.getWidth())];
}
++vectorIndex;
}
@@ -130,8 +116,8 @@ public abstract class BasicLoader {
}
protected int[][] loadRowVectorsImplByValueAt(final int vectorSize, final Range<Integer> planeRange) {
- final int rowVectorCount = (int) Math.ceil((double) dims.getX() / (double) vectorSize);
- final int vectorCount = dims.getZ() * dims.getY() * rowVectorCount;
+ final int rowVectorCount = (int) Math.ceil((double) dims.getWidth() / (double) vectorSize);
+ final int vectorCount = dims.getPlaneCount() * dims.getHeight() * rowVectorCount;
final int[][] rowVectors = new int[vectorCount][vectorSize];
@@ -139,21 +125,21 @@ public abstract class BasicLoader {
int baseX, srcX;
for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) {
- for (int row = 0; row < dims.getY(); row++) {
+ for (int row = 0; row < dims.getHeight(); row++) {
for (int rowVectorIndex = 0; rowVectorIndex < rowVectorCount; rowVectorIndex++) {
// Copy single vector.
baseX = rowVectorIndex * vectorSize;
for (int vectorX = 0; vectorX < vectorSize; vectorX++) {
srcX = (baseX + vectorX);
- if (srcX >= dims.getX()) {
+ if (srcX >= dims.getWidth()) {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank)
break;
srcX = wrapColumnIndex(srcX);
}
- // TODO(Moravec): dims.getY() should probably be dims.getX()! Check this!
- rowVectors[vectorIndex][vectorX] = valueAt(plane, srcX, row, dims.getY());
+ // TODO(Moravec): dims.getHeight() should probably be dims.getWidth()! Check this!
+ rowVectors[vectorIndex][vectorX] = valueAt(plane, srcX, row, dims.getHeight());
}
++vectorIndex;
}
@@ -165,15 +151,15 @@ public abstract class BasicLoader {
protected int[][] loadBlocksImplByLoadPlaneData(final V2i blockDim, final Range<Integer> planeRange) throws IOException {
final int blockSize = blockDim.multiplyTogether();
final int planeCount = planeRange.getTo() - planeRange.getFrom();
- final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.toV2i(), blockDim);
+ final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.getPlaneDimensions(), blockDim);
final int[][] blocks = new int[blockCount][blockSize];
int blockIndex = 0;
for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) {
final int[] planeData = loadPlaneData(plane);
- for (int blockYOffset = 0; blockYOffset < dims.getY(); blockYOffset += blockDim.getY()) {
- for (int blockXOffset = 0; blockXOffset < dims.getX(); blockXOffset += blockDim.getX()) {
+ for (int blockYOffset = 0; blockYOffset < dims.getHeight(); blockYOffset += blockDim.getY()) {
+ for (int blockXOffset = 0; blockXOffset < dims.getWidth(); blockXOffset += blockDim.getX()) {
loadBlock(blocks[blockIndex++], planeData, blockXOffset, blockYOffset, blockDim);
}
}
@@ -184,14 +170,14 @@ public abstract class BasicLoader {
protected int[][] loadBlocksImplByValueAt(final V2i blockDim, final Range<Integer> planeRange) {
final int blockSize = blockDim.multiplyTogether();
final int planeCount = planeRange.getTo() - planeRange.getFrom();
- final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.toV2i(), blockDim);
+ final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.getPlaneDimensions(), blockDim);
final int[][] blocks = new int[blockCount][blockSize];
int blockIndex = 0;
for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) {
- for (int blockYOffset = 0; blockYOffset < dims.getY(); blockYOffset += blockDim.getY()) {
- for (int blockXOffset = 0; blockXOffset < dims.getX(); blockXOffset += blockDim.getX()) {
+ for (int blockYOffset = 0; blockYOffset < dims.getHeight(); blockYOffset += blockDim.getY()) {
+ for (int blockXOffset = 0; blockXOffset < dims.getWidth(); blockXOffset += blockDim.getX()) {
loadBlock(blocks[blockIndex++], plane, blockXOffset, blockYOffset, blockDim);
}
}
@@ -204,7 +190,7 @@ public abstract class BasicLoader {
for (int y = 0; y < blockDim.getY(); y++) {
srcY = blockYOffset + y;
// Row overflow
- if (srcY >= dims.getY()) {
+ if (srcY >= dims.getHeight()) {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
}
@@ -215,25 +201,24 @@ public abstract class BasicLoader {
srcX = blockXOffset + x;
// Column overflow.
- if (srcX >= dims.getX()) {
+ if (srcX >= dims.getWidth()) {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
}
srcX = wrapColumnIndex(srcX);
}
- block[Block.index(x, y, blockDim.getX())] = valueAt(planeIndex, srcX, srcY, dims.getX());
+ block[Block.index(x, y, blockDim.getX())] = valueAt(planeIndex, srcX, srcY, dims.getWidth());
}
}
}
-
private void loadBlock(final int[] block, final int[] planeData, final int blockXOffset, final int blockYOffset, final V2i blockDim) {
int srcX, srcY;
for (int y = 0; y < blockDim.getY(); y++) {
srcY = blockYOffset + y;
// Row overflow
- if (srcY >= dims.getY()) {
+ if (srcY >= dims.getHeight()) {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
}
@@ -242,14 +227,14 @@ public abstract class BasicLoader {
for (int x = 0; x < blockDim.getX(); x++) {
srcX = blockXOffset + x;
// Column overflow.
- if (srcX >= dims.getX()) {
+ if (srcX >= dims.getWidth()) {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
}
srcX = wrapColumnIndex(srcX);
}
- block[Block.index(x, y, blockDim.getX())] = planeData[Block.index(srcX, srcY, dims.getX())];
+ block[Block.index(x, y, blockDim.getX())] = planeData[Block.index(srcX, srcY, dims.getWidth())];
}
}
}
@@ -259,7 +244,7 @@ public abstract class BasicLoader {
for (int z = 0; z < voxelDim.getZ(); z++) {
srcZ = voxelZOffset + z;
- if (srcZ >= dims.getZ()) {
+ if (srcZ >= dims.getPlaneCount()) {
// Handle plane overflow.
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
@@ -270,7 +255,7 @@ public abstract class BasicLoader {
for (int y = 0; y < voxelDim.getY(); y++) {
srcY = voxelYOffset + y;
- if (srcY >= dims.getY()) {
+ if (srcY >= dims.getHeight()) {
// Handle row overflow.
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
@@ -281,7 +266,7 @@ public abstract class BasicLoader {
for (int x = 0; x < voxelDim.getX(); x++) {
srcX = voxelXOffset + x;
- if (srcX >= dims.getX()) {
+ if (srcX >= dims.getWidth()) {
// Handle column overflow.
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
@@ -289,7 +274,7 @@ public abstract class BasicLoader {
srcX = wrapColumnIndex(srcX);
}
- voxel[Voxel.dataIndex(x, y, z, voxelDim)] = valueAt(srcZ, srcX, srcY, dims.getX());
+ voxel[Voxel.dataIndex(x, y, z, voxelDim)] = valueAt(srcZ, srcX, srcY, dims.getWidth());
}
}
}
@@ -306,7 +291,7 @@ public abstract class BasicLoader {
for (int y = 0; y < voxelDim.getY(); y++) {
srcY = voxelYOffset + y;
- if (srcY >= dims.getY()) {
+ if (srcY >= dims.getHeight()) {
// Handle row overflow.
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
@@ -317,7 +302,7 @@ public abstract class BasicLoader {
for (int x = 0; x < voxelDim.getX(); x++) {
srcX = voxelXOffset + x;
- if (srcX >= dims.getX()) {
+ if (srcX >= dims.getWidth()) {
// Handle column overflow.
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
break;
@@ -325,7 +310,7 @@ public abstract class BasicLoader {
srcX = wrapColumnIndex(srcX);
}
- voxel[Voxel.dataIndex(x, y, z, voxelDim)] = planesData[z][Block.index(srcX, srcY, dims.getX())];
+ voxel[Voxel.dataIndex(x, y, z, voxelDim)] = planesData[z][Block.index(srcX, srcY, dims.getWidth())];
}
}
}
@@ -339,9 +324,9 @@ public abstract class BasicLoader {
* @return Allocated array.
*/
private int[][] allocateVoxelArray(final V3i voxelDim, final Range<Integer> planeRange) {
- final int voxelElementCount = (int) voxelDim.multiplyTogether();
+ final int voxelElementCount = voxelDim.multiplyTogether();
final int rangeSize = planeRange.getTo() - planeRange.getFrom();
- final V3i srcVoxel = new V3i(dims.getX(), dims.getY(), rangeSize);
+ final V3i srcVoxel = new V3i(dims.getWidth(), dims.getHeight(), rangeSize);
final int voxelCount = Voxel.calculateRequiredVoxelCount(srcVoxel, voxelDim);
return new int[voxelCount][voxelElementCount];
}
@@ -359,8 +344,8 @@ public abstract class BasicLoader {
int voxelIndex = 0;
for (int voxelZOffset = planeRange.getFrom(); voxelZOffset < planeRange.getTo(); voxelZOffset += voxelDim.getZ()) {
- for (int voxelYOffset = 0; voxelYOffset < dims.getY(); voxelYOffset += voxelDim.getY()) {
- for (int voxelXOffset = 0; voxelXOffset < dims.getX(); voxelXOffset += voxelDim.getX()) {
+ for (int voxelYOffset = 0; voxelYOffset < dims.getHeight(); voxelYOffset += voxelDim.getY()) {
+ for (int voxelXOffset = 0; voxelXOffset < dims.getWidth(); voxelXOffset += voxelDim.getX()) {
loadVoxel(voxels[voxelIndex++], voxelXOffset, voxelYOffset, voxelZOffset, voxelDim);
}
}
@@ -370,16 +355,16 @@ public abstract class BasicLoader {
private void preloadPlanesData(final int[][] planesData, final int planeOffset, final int count) throws IOException {
for (int i = 0; i < count; i++) {
- if (planeOffset + i < dims.getZ())
+ if (planeOffset + i < dims.getPlaneCount())
planesData[i] = loadPlaneData(planeOffset + i);
else {
if (wrappingStrategy == DataWrappingStrategy.LeaveBlank) {
- planesData[i] = new int[dims.toV2i().multiplyTogether()];
+ planesData[i] = new int[dims.getWidth() * dims.getHeight()];
} else if (wrappingStrategy == DataWrappingStrategy.ClampToEdge) {
- assert (i > 0) : "Overflow on the first plane of voxel???";
+ // assert (i > 0) : "Overflow on the first plane of voxel???";
planesData[i] = planesData[i - 1];
} else if (wrappingStrategy == DataWrappingStrategy.MirroredRepeat) {
- final int srcZ = dims.getZ() - (((planeOffset + i) - dims.getZ()) + 1);
+ final int srcZ = dims.getPlaneCount() - (((planeOffset + i) - dims.getPlaneCount()) + 1);
planesData[i] = loadPlaneData(srcZ);
}
}
@@ -404,8 +389,8 @@ public abstract class BasicLoader {
preloadPlanesData(planesData, voxelZOffset, voxelDim.getZ());
- for (int voxelYOffset = 0; voxelYOffset < dims.getY(); voxelYOffset += voxelDim.getY()) {
- for (int voxelXOffset = 0; voxelXOffset < dims.getX(); voxelXOffset += voxelDim.getX()) {
+ for (int voxelYOffset = 0; voxelYOffset < dims.getHeight(); voxelYOffset += voxelDim.getY()) {
+ for (int voxelXOffset = 0; voxelXOffset < dims.getWidth(); voxelXOffset += voxelDim.getX()) {
loadVoxel(voxels[voxelIndex++], planesData, voxelXOffset, voxelYOffset, voxelDim);
}
}
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/IPlaneLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/IPlaneLoader.java
index a864ac62bfe7b8209ec06f69043634caf9363944..4db0090b33b9efa2c1e7028e8c1ba24e8f130685 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/IPlaneLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/IPlaneLoader.java
@@ -2,6 +2,7 @@ package cz.it4i.qcmp.io.loader;
import cz.it4i.qcmp.compression.CompressionOptions;
import cz.it4i.qcmp.compression.exception.ImageCompressionException;
+import cz.it4i.qcmp.data.HyperStackDimensions;
import cz.it4i.qcmp.data.Range;
import cz.it4i.qcmp.data.V2i;
import cz.it4i.qcmp.data.V3i;
@@ -41,7 +42,7 @@ public interface IPlaneLoader {
*
* @return Image of the loader image.
*/
- V3i getImageDimensions();
+ HyperStackDimensions getDatasetDimensions();
/**
* Load specified plane data.
@@ -92,7 +93,7 @@ public interface IPlaneLoader {
* @throws IOException When fails to load plane data.
*/
default int[][] loadRowVectors(final int vectorSize) throws IOException {
- return loadRowVectors(vectorSize, new Range<>(0, getImageDimensions().getZ()));
+ return loadRowVectors(vectorSize, new Range<>(0, getDatasetDimensions().getPlaneCount()));
}
/**
@@ -113,7 +114,7 @@ public interface IPlaneLoader {
* @throws IOException When fails to load plane data.
*/
default int[][] loadBlocks(final V2i blockDim) throws IOException {
- return loadBlocks(blockDim, new Range<>(0, getImageDimensions().getZ()));
+ return loadBlocks(blockDim, new Range<>(0, getDatasetDimensions().getPlaneCount()));
}
/**
@@ -134,7 +135,7 @@ public interface IPlaneLoader {
* @throws IOException when fails to load plane data.
*/
default int[][] loadVoxels(final V3i voxelDim) throws IOException {
- return loadVoxels(voxelDim, new Range<>(0, getImageDimensions().getZ()));
+ return loadVoxels(voxelDim, new Range<>(0, getDatasetDimensions().getPlaneCount()));
}
/**
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/ImageJBufferLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/ImageJBufferLoader.java
index a0b8e7eb21759e5c539fc6a686c0cba4c5ccd7e4..e1769dde1288446d4e6c251a089628eda36d490e 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/ImageJBufferLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/ImageJBufferLoader.java
@@ -5,20 +5,17 @@ import cz.it4i.qcmp.data.Range;
import cz.it4i.qcmp.data.V2i;
import cz.it4i.qcmp.data.V3i;
import cz.it4i.qcmp.io.BufferInputData;
-import cz.it4i.qcmp.io.InputData;
import cz.it4i.qcmp.utilities.TypeConverter;
import java.io.IOException;
import java.util.Arrays;
-public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoader {
+public final class ImageJBufferLoader extends GenericLoader implements IPlaneLoader {
private final BufferInputData bufferInputData;
public ImageJBufferLoader(final BufferInputData bufferDataInfo) {
super(bufferDataInfo.getDimensions());
this.bufferInputData = bufferDataInfo;
- // FIXME: Support more pixel types.
- assert (this.bufferInputData.getPixelType() == InputData.PixelType.Gray16);
}
@Override
@@ -37,9 +34,9 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(plane);
return TypeConverter.shortArrayToIntArray(srcBuffer);
}
-
+
@Override
- protected int valueAt(int plane, int x, int y, int width) {
+ protected int valueAt(final int plane, final int x, final int y, final int width) {
return TypeConverter.shortToInt(((short[]) bufferInputData.getPixelBuffer(plane))[Block.index(x, y, width)]);
}
@@ -49,20 +46,15 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
return new int[0];
} else if (planes.length == 1) {
return loadPlaneData(planes[0]);
- } else if (planes.length == bufferInputData.getDimensions().getZ()) { // Maybe?
+ } else if (planes.length == dims.getPlaneCount()) {
return loadAllPlanesU16Data();
}
- final int planePixelCount =
- bufferInputData.getDimensions().getX() * bufferInputData.getDimensions().getY();
- 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.");
- }
+ final int planePixelCount = dims.getNumberOfElementsInDimension(2);
+ final int totalValueCount = Math.multiplyExact(planePixelCount, planes.length);
Arrays.sort(planes);
- final int[] destBuffer = new int[(int) totalValueCount];
+ final int[] destBuffer = new int[totalValueCount];
int destOffset = 0;
for (final int planeIndex : planes) {
final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(planeIndex);
@@ -74,17 +66,12 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
@Override
public int[] loadAllPlanesU16Data() throws IOException {
- final V3i imageDims = bufferInputData.getDimensions();
- final long totalValueCount = imageDims.multiplyTogether();
- final int planePixelCount = imageDims.getX() * imageDims.getY();
-
- if (totalValueCount > (long) Integer.MAX_VALUE) {
- throw new IOException("Unable to load all image data, file size is too big.");
- }
+ final int planePixelCount = dims.getNumberOfElementsInDimension(2);
+ final int totalValueCount = dims.getNumberOfElementsInDimension(3);
- final int[] destBuffer = new int[(int) totalValueCount];
+ final int[] destBuffer = new int[totalValueCount];
int destOffset = 0;
- for (int planeIndex = 0; planeIndex < imageDims.getZ(); planeIndex++) {
+ for (int planeIndex = 0; planeIndex < dims.getPlaneCount(); planeIndex++) {
final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(planeIndex);
copyShortArrayIntoBuffer(srcBuffer, destBuffer, destOffset, planePixelCount);
destOffset += planePixelCount;
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/RawDataLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/RawDataLoader.java
index 55f0e8595f62b7b7f8211a204cc5703ae273ba66..8d4834c2d0ddcfa39ed32d1d696185e794bb39ba 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/RawDataLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/RawDataLoader.java
@@ -12,7 +12,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
-public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
+public final class RawDataLoader extends GenericLoader implements IPlaneLoader {
private final FileInputData inputDataInfo;
private interface StorePlaneDataCallback {
@@ -36,8 +36,8 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
final byte[] buffer;
try (final FileInputStream fileStream = new FileInputStream(inputDataInfo.getFilePath())) {
- final long planeSize = (long) dims.getX() * (long) dims.getY() * 2;
- final long expectedFileSize = planeSize * dims.getZ();
+ final long planeSize = dims.getNumberOfElementsInDimension(2) * 2;
+ final long expectedFileSize = planeSize * dims.getPlaneCount();
final long fileSize = fileStream.getChannel().size();
if (expectedFileSize != fileSize) {
@@ -72,7 +72,7 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
storeCallback.store(0, loadPlaneData(planes[0]));
}
- final int planeValueCount = inputDataInfo.getDimensions().getX() * inputDataInfo.getDimensions().getY();
+ final int planeValueCount = dims.getNumberOfElementsInDimension(2);
final int planeDataSize = 2 * planeValueCount;
final byte[] planeBuffer = new byte[planeDataSize];
@@ -117,13 +117,10 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
@Override
public int[] loadPlanesU16Data(final int[] planes) throws IOException {
+ final int planeValueCount = dims.getNumberOfElementsInDimension(2);
+ final int totalValueCount = dims.getNumberOfElementsInDimension(3);
- final int planeValueCount = inputDataInfo.getDimensions().getX() * inputDataInfo.getDimensions().getY();
- final long totalValueCount = (long) planeValueCount * planes.length;
- if (totalValueCount > (long) Integer.MAX_VALUE) {
- throw new IOException("Integer count is too big.");
- }
- final int[] data = new int[(int) totalValueCount];
+ final int[] data = new int[totalValueCount];
loadPlanesU16DataImpl(planes, (index, planeData) -> {
System.arraycopy(planeData, 0, data, (index * planeValueCount), planeValueCount);
@@ -134,19 +131,16 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
@Override
public int[] loadAllPlanesU16Data() throws IOException {
- final V3i imageDims = inputDataInfo.getDimensions();
- final long dataSize = (long) imageDims.getX() * (long) imageDims.getY() * (long) imageDims.getZ();
+ final int dataElementCount = dims.getNumberOfElementsInDimension(3);
- if (dataSize > (long) Integer.MAX_VALUE) {
- throw new IOException("RawFile size is too big.");
- }
- final int[] values = new int[(int) dataSize];
+ final int[] values = new int[(int) dataElementCount];
+ // TODO(Moravec): dis.readUnsignedShort() should be replaced with .read()!
try (final FileInputStream fileStream = new FileInputStream(inputDataInfo.getFilePath());
final DataInputStream dis = new DataInputStream(new BufferedInputStream(fileStream, 8192))) {
- for (int i = 0; i < (int) dataSize; i++) {
+ for (int i = 0; i < (int) dataElementCount; i++) {
values[i] = dis.readUnsignedShort();
}
}
@@ -155,15 +149,14 @@ public final class RawDataLoader extends BasicLoader implements IPlaneLoader {
}
public int[][] loadAllPlanesTo2DArray() throws IOException {
- final V3i imageDims = inputDataInfo.getDimensions();
- final int planePixelCount = imageDims.getX() * imageDims.getY();
+ final int planePixelCount = dims.getNumberOfElementsInDimension(2);
final int planeDataSize = planePixelCount * 2;
- final int[][] result = new int[imageDims.getZ()][];
+ final int[][] result = new int[dims.getPlaneCount()][];
final byte[] planeBuffer = new byte[planeDataSize];
try (final FileInputStream fileStream = new FileInputStream(inputDataInfo.getFilePath())) {
- for (int plane = 0; plane < imageDims.getZ(); plane++) {
+ for (int plane = 0; plane < dims.getPlaneCount(); plane++) {
int toRead = planeDataSize;
while (toRead > 0) {
final int read = fileStream.read(planeBuffer, planeDataSize - toRead, toRead);
diff --git a/src/main/java/cz/it4i/qcmp/io/loader/SCIFIOLoader.java b/src/main/java/cz/it4i/qcmp/io/loader/SCIFIOLoader.java
index a253532c640cdd23692cbfd6104815280f951911..2d0e8db1e112d9ad93cb45f24ab56e85cfbe8f98 100644
--- a/src/main/java/cz/it4i/qcmp/io/loader/SCIFIOLoader.java
+++ b/src/main/java/cz/it4i/qcmp/io/loader/SCIFIOLoader.java
@@ -12,7 +12,7 @@ import io.scif.Reader;
import java.io.IOException;
import java.util.Arrays;
-public final class SCIFIOLoader extends BasicLoader implements IPlaneLoader {
+public final class SCIFIOLoader extends GenericLoader implements IPlaneLoader {
private final FileInputData inputDataInfo;
private final Reader reader;
@@ -55,7 +55,7 @@ public final class SCIFIOLoader extends BasicLoader implements IPlaneLoader {
return loadPlaneData(planes[0]);
}
- final int planeValueCount = inputDataInfo.getDimensions().getX() * inputDataInfo.getDimensions().getY();
+ final int planeValueCount = dims.getNumberOfElementsInDimension(2);
final long planeDataSize = 2 * (long) planeValueCount;
final long totalValueCount = (long) planeValueCount * planes.length;
@@ -87,9 +87,8 @@ public final class SCIFIOLoader extends BasicLoader implements IPlaneLoader {
@Override
public int[] loadAllPlanesU16Data() throws IOException {
- final V3i imageDims = inputDataInfo.getDimensions();
- final long planePixelCount = (long) imageDims.getX() * (long) imageDims.getY();
- final long dataSize = planePixelCount * (long) imageDims.getZ();
+ final long planePixelCount = dims.getNumberOfElementsInDimension(2);
+ final long dataSize = planePixelCount * (long) dims.getPlaneCount();
if (dataSize > (long) Integer.MAX_VALUE) {
throw new IOException("FileSize is too big.");
@@ -97,7 +96,7 @@ public final class SCIFIOLoader extends BasicLoader implements IPlaneLoader {
final int[] values = new int[(int) dataSize];
byte[] planeBytes;
- for (int plane = 0; plane < imageDims.getZ(); plane++) {
+ for (int plane = 0; plane < dims.getPlaneCount(); plane++) {
try {
planeBytes = reader.openPlane(0, plane).getBytes();
} catch (final FormatException e) {