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

Use abstract PlaneLoader.

Use ConcretePlaneLoader instead of RawDataIO.
This allows the use of SCIFIO readers.
parent 4496519f
No related branches found
No related tags found
No related merge requests found
Showing
with 415 additions and 316 deletions
...@@ -33,27 +33,11 @@ abstract class BenchmarkBase { ...@@ -33,27 +33,11 @@ abstract class BenchmarkBase {
protected final int workerCount; protected final int workerCount;
protected BenchmarkBase(final String inputFile, protected final ParsedCliOptions options;
final String outputDirectory,
final int[] planes,
final V3i rawImageDims) {
this.inputFile = inputFile;
this.outputDirectory = outputDirectory;
this.planes = planes;
this.rawImageDims = rawImageDims;
hasReferencePlane = false;
referencePlaneIndex = -1;
codebookSize = 256;
hasCacheFolder = false;
cacheFolder = null;
hasGeneralQuantizer = false;
workerCount = 1;
}
protected BenchmarkBase(final ParsedCliOptions options) { protected BenchmarkBase(final ParsedCliOptions options) {
this.options = options;
final InputFileInfo ifi = options.getInputFileInfo(); final InputFileInfo ifi = options.getInputFileInfo();
this.inputFile = ifi.getFilePath(); this.inputFile = ifi.getFilePath();
this.outputDirectory = options.getOutputFile(); this.outputDirectory = options.getOutputFile();
...@@ -98,32 +82,32 @@ abstract class BenchmarkBase { ...@@ -98,32 +82,32 @@ abstract class BenchmarkBase {
return file.getAbsolutePath(); return file.getAbsolutePath();
} }
/** // /**
* Load u16 plane from RAW file. // * Load u16 plane from RAW file.
* // *
* @param planeIndex Zero based plane index. // * @param planeIndex Zero based plane index.
* @return u16 plane. // * @return u16 plane.
*/ // */
protected ImageU16 loadPlane(final int planeIndex) { // protected ImageU16 loadPlane(final int planeIndex) {
try { // try {
return RawDataIO.loadImageU16(inputFile, rawImageDims, planeIndex); // return RawDataIO.loadImageU16(inputFile, rawImageDims, planeIndex);
} catch (Exception ex) { // } catch (Exception ex) {
ex.printStackTrace(); // ex.printStackTrace();
} // }
return null; // return null;
} // }
/** // /**
* Load U16 plane data from RAW file. // * Load U16 plane data from RAW file.
* // *
* @param planeIndex Zero based plane index. // * @param planeIndex Zero based plane index.
* @return U16 array of image plane data. // * @return U16 array of image plane data.
*/ // */
protected int[] loadPlaneData(final int planeIndex) { // protected int[] loadPlaneData(final int planeIndex) {
ImageU16 plane = loadPlane(planeIndex); // ImageU16 plane = loadPlane(planeIndex);
//
return (plane != null) ? plane.getData() : new int[0]; // return (plane != null) ? plane.getData() : new int[0];
} // }
/** /**
......
...@@ -2,9 +2,9 @@ package azgracompress.benchmark; ...@@ -2,9 +2,9 @@ package azgracompress.benchmark;
import azgracompress.U16; import azgracompress.U16;
import azgracompress.cli.ParsedCliOptions; import azgracompress.cli.ParsedCliOptions;
import azgracompress.data.V3i;
import azgracompress.de.DeException; import azgracompress.de.DeException;
import azgracompress.de.shade.ILShadeSolver; import azgracompress.de.shade.ILShadeSolver;
import azgracompress.io.ConcretePlaneLoader;
import azgracompress.quantization.QTrainIteration; import azgracompress.quantization.QTrainIteration;
import azgracompress.quantization.QuantizationValueCache; import azgracompress.quantization.QuantizationValueCache;
import azgracompress.quantization.scalar.LloydMaxU16ScalarQuantization; import azgracompress.quantization.scalar.LloydMaxU16ScalarQuantization;
...@@ -18,13 +18,6 @@ import java.io.OutputStreamWriter; ...@@ -18,13 +18,6 @@ import java.io.OutputStreamWriter;
public class ScalarQuantizationBenchmark extends BenchmarkBase { public class ScalarQuantizationBenchmark extends BenchmarkBase {
private boolean useDiffEvolution = false; private boolean useDiffEvolution = false;
public ScalarQuantizationBenchmark(final String inputFile,
final String outputDirectory,
final int[] planes,
final V3i rawImageDims) {
super(inputFile, outputDirectory, planes, rawImageDims);
}
public ScalarQuantizationBenchmark(final ParsedCliOptions options) { public ScalarQuantizationBenchmark(final ParsedCliOptions options) {
super(options); super(options);
} }
...@@ -32,12 +25,22 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase { ...@@ -32,12 +25,22 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase {
@Override @Override
public void startBenchmark() { public void startBenchmark() {
ConcretePlaneLoader planeLoader = null;
try {
planeLoader = new ConcretePlaneLoader(options.getInputFileInfo());
} catch (Exception e) {
e.printStackTrace();
System.err.println("Unable to create SCIFIO reader.");
return;
}
if (planes.length < 1) { if (planes.length < 1) {
return; return;
} }
boolean dirCreated = new File(this.outputDirectory).mkdirs(); boolean dirCreated = new File(this.outputDirectory).mkdirs();
System.out.println(String.format("|CODEBOOK| = %d", codebookSize)); System.out.println(String.format("|CODEBOOK| = %d", codebookSize));
ScalarQuantizer quantizer = null; ScalarQuantizer quantizer = null;
if (hasCacheFolder) { if (hasCacheFolder) {
System.out.println("Loading codebook from cache"); System.out.println("Loading codebook from cache");
QuantizationValueCache cache = new QuantizationValueCache(cacheFolder); QuantizationValueCache cache = new QuantizationValueCache(cacheFolder);
...@@ -51,11 +54,16 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase { ...@@ -51,11 +54,16 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase {
} }
System.out.println("Created quantizer from cache"); System.out.println("Created quantizer from cache");
} else if (hasReferencePlane) { } else if (hasReferencePlane) {
final int[] refPlaneData = loadPlaneData(referencePlaneIndex); final int[] refPlaneData;
if (refPlaneData.length == 0) {
try {
refPlaneData = planeLoader.loadPlaneU16(referencePlaneIndex).getData();
} catch (IOException e) {
e.printStackTrace();
System.err.println("Failed to load reference plane data."); System.err.println("Failed to load reference plane data.");
return; return;
} }
if (useDiffEvolution) { if (useDiffEvolution) {
quantizer = trainDifferentialEvolution(refPlaneData, codebookSize); quantizer = trainDifferentialEvolution(refPlaneData, codebookSize);
} else { } else {
...@@ -67,7 +75,14 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase { ...@@ -67,7 +75,14 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase {
for (final int planeIndex : planes) { for (final int planeIndex : planes) {
System.out.println(String.format("Loading plane %d ...", planeIndex)); System.out.println(String.format("Loading plane %d ...", planeIndex));
// NOTE(Moravec): Actual planeIndex is zero based. // NOTE(Moravec): Actual planeIndex is zero based.
final int[] planeData = loadPlaneData(planeIndex); final int[] planeData;
try {
planeData = planeLoader.loadPlaneU16(planeIndex).getData();
} catch (IOException e) {
e.printStackTrace();
System.err.println("Failed to load plane data.");
return;
}
if (planeData.length == 0) { if (planeData.length == 0) {
System.err.println(String.format("Failed to load plane %d data. Skipping plane.", planeIndex)); System.err.println(String.format("Failed to load plane %d data. Skipping plane.", planeIndex));
return; return;
......
...@@ -2,6 +2,7 @@ package azgracompress.benchmark; ...@@ -2,6 +2,7 @@ package azgracompress.benchmark;
import azgracompress.cli.ParsedCliOptions; import azgracompress.cli.ParsedCliOptions;
import azgracompress.data.*; import azgracompress.data.*;
import azgracompress.io.ConcretePlaneLoader;
import azgracompress.quantization.QuantizationValueCache; import azgracompress.quantization.QuantizationValueCache;
import azgracompress.quantization.vector.CodebookEntry; import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.LBGResult; import azgracompress.quantization.vector.LBGResult;
...@@ -17,10 +18,6 @@ public class VectorQuantizationBenchmark extends BenchmarkBase { ...@@ -17,10 +18,6 @@ public class VectorQuantizationBenchmark extends BenchmarkBase {
final static V2i DEFAULT_QVECTOR = new V2i(3, 3); final static V2i DEFAULT_QVECTOR = new V2i(3, 3);
public VectorQuantizationBenchmark(String inputFile, String outputDirectory, int[] planes, V3i rawImageDims) {
super(inputFile, outputDirectory, planes, rawImageDims);
}
public VectorQuantizationBenchmark(final ParsedCliOptions options) { public VectorQuantizationBenchmark(final ParsedCliOptions options) {
super(options); super(options);
} }
...@@ -51,6 +48,14 @@ public class VectorQuantizationBenchmark extends BenchmarkBase { ...@@ -51,6 +48,14 @@ public class VectorQuantizationBenchmark extends BenchmarkBase {
if (planes.length < 1) { if (planes.length < 1) {
return; return;
} }
ConcretePlaneLoader planeLoader = null;
try {
planeLoader = new ConcretePlaneLoader(options.getInputFileInfo());
} catch (Exception e) {
e.printStackTrace();
System.err.println("Unable to create SCIFIO reader.");
return;
}
if (qVector.getY() > 1) { if (qVector.getY() > 1) {
System.out.println("2D qVector"); System.out.println("2D qVector");
} else { } else {
...@@ -77,9 +82,11 @@ public class VectorQuantizationBenchmark extends BenchmarkBase { ...@@ -77,9 +82,11 @@ public class VectorQuantizationBenchmark extends BenchmarkBase {
} }
System.out.println("Created quantizer from cache"); System.out.println("Created quantizer from cache");
} else if (hasReferencePlane) { } else if (hasReferencePlane) {
final ImageU16 plane = loadPlane(referencePlaneIndex); final ImageU16 plane;
try {
if (plane == null) { plane = planeLoader.loadPlaneU16(referencePlaneIndex);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Failed to load reference plane data."); System.err.println("Failed to load reference plane data.");
return; return;
} }
...@@ -93,11 +100,12 @@ public class VectorQuantizationBenchmark extends BenchmarkBase { ...@@ -93,11 +100,12 @@ public class VectorQuantizationBenchmark extends BenchmarkBase {
for (final int planeIndex : planes) { for (final int planeIndex : planes) {
System.out.println(String.format("Loading plane %d ...", planeIndex)); System.out.println(String.format("Loading plane %d ...", planeIndex));
// NOTE(Moravec): Actual planeIndex is zero based.
final ImageU16 plane = loadPlane(planeIndex - 1);
if (plane == null) { final ImageU16 plane;
try {
plane = planeLoader.loadPlaneU16(planeIndex);
} catch (IOException e) {
e.printStackTrace();
System.err.println(String.format("Failed to load plane %d data. Skipping plane.", planeIndex)); System.err.println(String.format("Failed to load plane %d data. Skipping plane.", planeIndex));
return; return;
} }
......
...@@ -12,6 +12,8 @@ public class InputFileInfo { ...@@ -12,6 +12,8 @@ public class InputFileInfo {
*/ */
private final String filePath; private final String filePath;
private boolean isRAW = true;
private V3i dimension; private V3i dimension;
private boolean planeIndexSet = false; private boolean planeIndexSet = false;
...@@ -76,4 +78,12 @@ public class InputFileInfo { ...@@ -76,4 +78,12 @@ public class InputFileInfo {
public V2i getPlaneRange() { public V2i getPlaneRange() {
return planeRange; return planeRange;
} }
public boolean isRAW() {
return isRAW;
}
public void setIsRaw(boolean RAW) {
isRAW = RAW;
}
} }
...@@ -130,7 +130,6 @@ public class ParsedCliOptions { ...@@ -130,7 +130,6 @@ public class ParsedCliOptions {
return; return;
} }
inputFileInfo = new InputFileInfo(inputFileArguments[0]); inputFileInfo = new InputFileInfo(inputFileArguments[0]);
// Decompress and Inspect methods doesn't require additional file information. // Decompress and Inspect methods doesn't require additional file information.
...@@ -159,7 +158,8 @@ public class ParsedCliOptions { ...@@ -159,7 +158,8 @@ public class ParsedCliOptions {
// inputFileInfo is already created with TIFF type. // inputFileInfo is already created with TIFF type.
// assert (inputFileInfo.getFileType() == FileType.TIFF) : "Not TIFF type in parse Tiff arguments."; // assert (inputFileInfo.getFileType() == FileType.TIFF) : "Not TIFF type in parse Tiff arguments.";
Reader reader = null; inputFileInfo.setIsRaw(false);
Reader reader;
try { try {
reader = ScifioWrapper.getReader(inputFileInfo.getFilePath()); reader = ScifioWrapper.getReader(inputFileInfo.getFilePath());
} catch (IOException | FormatException e) { } catch (IOException | FormatException e) {
...@@ -223,6 +223,7 @@ public class ParsedCliOptions { ...@@ -223,6 +223,7 @@ public class ParsedCliOptions {
return; return;
} }
inputFileInfo.setIsRaw(true);
parseImageDims(inputFileArguments[1], errorBuilder); parseImageDims(inputFileArguments[1], errorBuilder);
// User specified plane index or plane range. // User specified plane index or plane range.
......
...@@ -2,15 +2,6 @@ package azgracompress.cli.functions; ...@@ -2,15 +2,6 @@ package azgracompress.cli.functions;
import azgracompress.cli.CustomFunctionBase; import azgracompress.cli.CustomFunctionBase;
import azgracompress.cli.ParsedCliOptions; import azgracompress.cli.ParsedCliOptions;
import azgracompress.data.ImageU16;
import azgracompress.data.V3i;
import azgracompress.io.RawDataIO;
import azgracompress.utilities.Utils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
public class MeasurePlaneErrorFunction extends CustomFunctionBase { public class MeasurePlaneErrorFunction extends CustomFunctionBase {
public MeasurePlaneErrorFunction(ParsedCliOptions options) { public MeasurePlaneErrorFunction(ParsedCliOptions options) {
...@@ -66,53 +57,53 @@ public class MeasurePlaneErrorFunction extends CustomFunctionBase { ...@@ -66,53 +57,53 @@ public class MeasurePlaneErrorFunction extends CustomFunctionBase {
} }
private boolean reportPlaneDifference(final String compressedFile, final String reportFile) { private boolean reportPlaneDifference(final String compressedFile, final String reportFile) {
final String referenceFile = "D:\\biology\\tiff_data\\benchmark\\fused_tp_10_ch_1_16bit.raw"; // final String referenceFile = "D:\\biology\\tiff_data\\benchmark\\fused_tp_10_ch_1_16bit.raw";
//
final V3i dims = new V3i(1041, 996, 946); // final V3i dims = new V3i(1041, 996, 946);
final int planePixelCount = dims.getX() * dims.getY(); // final int planePixelCount = dims.getX() * dims.getY();
System.out.println(options.report()); // System.out.println(options.report());
System.out.println("Run custom function."); // System.out.println("Run custom function.");
ImageU16 compressedPlane = null; // ImageU16 compressedPlane = null;
ImageU16 originalPlane = null; // ImageU16 originalPlane = null;
ImageU16 differencePlane = null; // ImageU16 differencePlane = null;
//
PlaneError[] planeErrors = new PlaneError[dims.getZ()]; // PlaneError[] planeErrors = new PlaneError[dims.getZ()];
//
for (int planeIndex = 0; planeIndex < dims.getZ(); planeIndex++) { // for (int planeIndex = 0; planeIndex < dims.getZ(); planeIndex++) {
try { // try {
originalPlane = RawDataIO.loadImageU16(referenceFile, dims, planeIndex); // originalPlane = RawDataIO.loadImageU16(referenceFile, dims, planeIndex);
compressedPlane = RawDataIO.loadImageU16(compressedFile, dims, planeIndex); // compressedPlane = RawDataIO.loadImageU16(compressedFile, dims, planeIndex);
} catch (IOException e) { // } catch (IOException e) {
e.printStackTrace(); // e.printStackTrace();
return true; // return true;
} // }
final int[] diffData = Utils.getDifference(originalPlane.getData(), compressedPlane.getData()); // final int[] diffData = Utils.getDifference(originalPlane.getData(), compressedPlane.getData());
Utils.applyAbsFunction(diffData); // Utils.applyAbsFunction(diffData);
//
//
final double absDiffSum = Arrays.stream(diffData).mapToDouble(v -> v).sum(); // final double absDiffSum = Arrays.stream(diffData).mapToDouble(v -> v).sum();
final double meanPixelError = absDiffSum / (double) planePixelCount; // final double meanPixelError = absDiffSum / (double) planePixelCount;
//
planeErrors[planeIndex] = new PlaneError(planeIndex, absDiffSum, meanPixelError); // planeErrors[planeIndex] = new PlaneError(planeIndex, absDiffSum, meanPixelError);
// System.out.println("Finished plane: " + planeIndex); // // System.out.println("Finished plane: " + planeIndex);
} // }
//
try (FileOutputStream fos = new FileOutputStream(reportFile, false); // try (FileOutputStream fos = new FileOutputStream(reportFile, false);
OutputStreamWriter writer = new OutputStreamWriter(fos)) { // OutputStreamWriter writer = new OutputStreamWriter(fos)) {
//
writer.write("PlaneIndex\tErrorSum\tMeanError\n"); // writer.write("PlaneIndex\tErrorSum\tMeanError\n");
//
for (final PlaneError planeError : planeErrors) { // for (final PlaneError planeError : planeErrors) {
writer.write(String.format("%d\t%.4f\t%.4f\n", // writer.write(String.format("%d\t%.4f\t%.4f\n",
planeError.getPlaneIndex(), // planeError.getPlaneIndex(),
planeError.getAbsoluteError(), // planeError.getAbsoluteError(),
planeError.getMeanAbsoluteError())); // planeError.getMeanAbsoluteError()));
} // }
//
} catch (IOException e) { // } catch (IOException e) {
e.printStackTrace(); // e.printStackTrace();
} // }
System.out.println("Finished reportPlaneDifference"); // System.out.println("Finished reportPlaneDifference");
return false; return false;
} }
} }
...@@ -5,8 +5,8 @@ import azgracompress.cli.InputFileInfo; ...@@ -5,8 +5,8 @@ import azgracompress.cli.InputFileInfo;
import azgracompress.cli.ParsedCliOptions; import azgracompress.cli.ParsedCliOptions;
import azgracompress.compression.exception.ImageCompressionException; import azgracompress.compression.exception.ImageCompressionException;
import azgracompress.data.ImageU16; import azgracompress.data.ImageU16;
import azgracompress.io.ConcretePlaneLoader;
import azgracompress.io.OutBitStream; import azgracompress.io.OutBitStream;
import azgracompress.io.RawDataIO;
import azgracompress.quantization.QuantizationValueCache; import azgracompress.quantization.QuantizationValueCache;
import azgracompress.quantization.scalar.LloydMaxU16ScalarQuantization; import azgracompress.quantization.scalar.LloydMaxU16ScalarQuantization;
import azgracompress.quantization.scalar.ScalarQuantizer; import azgracompress.quantization.scalar.ScalarQuantizer;
...@@ -85,6 +85,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -85,6 +85,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
Stopwatch stopwatch = new Stopwatch(); Stopwatch stopwatch = new Stopwatch();
final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.hasReferencePlaneIndex(); final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.hasReferencePlaneIndex();
final ConcretePlaneLoader planeLoader;
try {
planeLoader = new ConcretePlaneLoader(inputFileInfo);
} catch (Exception e) {
throw new ImageCompressionException("Unable to create SCIFIO reader. " + e.getMessage());
}
ScalarQuantizer quantizer = null; ScalarQuantizer quantizer = null;
if (options.hasCodebookCacheFolder()) { if (options.hasCodebookCacheFolder()) {
Log("Loading codebook from cache file."); Log("Loading codebook from cache file.");
...@@ -96,10 +103,8 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -96,10 +103,8 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
stopwatch.restart(); stopwatch.restart();
ImageU16 referencePlane = null; ImageU16 referencePlane = null;
try { try {
referencePlane = RawDataIO.loadImageU16(inputFileInfo.getFilePath(), referencePlane = planeLoader.loadPlaneU16(options.getReferencePlaneIndex());
inputFileInfo.getDimensions(), } catch (IOException ex) {
options.getReferencePlaneIndex());
} catch (Exception ex) {
throw new ImageCompressionException("Unable to load reference plane data.", ex); throw new ImageCompressionException("Unable to load reference plane data.", ex);
} }
...@@ -121,10 +126,8 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -121,10 +126,8 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
ImageU16 plane = null; ImageU16 plane = null;
try { try {
plane = RawDataIO.loadImageU16(inputFileInfo.getFilePath(), plane = planeLoader.loadPlaneU16(planeIndex);
inputFileInfo.getDimensions(), } catch (IOException ex) {
planeIndex);
} catch (Exception ex) {
throw new ImageCompressionException("Unable to load plane data.", ex); throw new ImageCompressionException("Unable to load plane data.", ex);
} }
...@@ -152,13 +155,17 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -152,13 +155,17 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
private int[] loadConfiguredPlanesData() throws ImageCompressionException { private int[] loadConfiguredPlanesData() throws ImageCompressionException {
final InputFileInfo inputFileInfo = options.getInputFileInfo(); final InputFileInfo inputFileInfo = options.getInputFileInfo();
final ConcretePlaneLoader planeLoader;
try {
planeLoader = new ConcretePlaneLoader(inputFileInfo);
} catch (Exception e) {
throw new ImageCompressionException("Unable to create SCIFIO reader. " + e.getMessage());
}
int[] trainData = null; int[] trainData = null;
if (inputFileInfo.isPlaneIndexSet()) { if (inputFileInfo.isPlaneIndexSet()) {
try { try {
Log("Loading single plane data."); Log("Loading single plane data.");
trainData = RawDataIO.loadImageU16(inputFileInfo.getFilePath(), trainData = planeLoader.loadPlaneU16(inputFileInfo.getPlaneIndex()).getData();
inputFileInfo.getDimensions(),
inputFileInfo.getPlaneIndex()).getData();
} catch (IOException e) { } catch (IOException e) {
throw new ImageCompressionException("Failed to load reference image data.", e); throw new ImageCompressionException("Failed to load reference image data.", e);
} }
...@@ -166,7 +173,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -166,7 +173,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
Log("Loading plane range data."); Log("Loading plane range data.");
final int[] planes = getPlaneIndicesForCompression(); final int[] planes = getPlaneIndicesForCompression();
try { try {
trainData = RawDataIO.loadPlanesData(inputFileInfo.getFilePath(), inputFileInfo.getDimensions(), planes); trainData = planeLoader.loadPlanesU16Data(planes);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
throw new ImageCompressionException("Failed to load plane range data.", e); throw new ImageCompressionException("Failed to load plane range data.", e);
...@@ -174,7 +181,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -174,7 +181,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
} else { } else {
Log("Loading all planes data."); Log("Loading all planes data.");
try { try {
trainData = RawDataIO.loadAllPlanesData(inputFileInfo.getFilePath(), inputFileInfo.getDimensions()); trainData = planeLoader.loadAllPlanesU16Data();
} catch (IOException e) { } catch (IOException e) {
throw new ImageCompressionException("Failed to load all planes data.", e); throw new ImageCompressionException("Failed to load all planes data.", e);
} }
...@@ -185,7 +192,6 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -185,7 +192,6 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
@Override @Override
public void trainAndSaveCodebook() throws ImageCompressionException { public void trainAndSaveCodebook() throws ImageCompressionException {
int[] trainData = loadConfiguredPlanesData(); int[] trainData = loadConfiguredPlanesData();
LloydMaxU16ScalarQuantization lloydMax = new LloydMaxU16ScalarQuantization(trainData, LloydMaxU16ScalarQuantization lloydMax = new LloydMaxU16ScalarQuantization(trainData,
......
...@@ -5,8 +5,9 @@ import azgracompress.cli.ParsedCliOptions; ...@@ -5,8 +5,9 @@ import azgracompress.cli.ParsedCliOptions;
import azgracompress.compression.exception.ImageCompressionException; import azgracompress.compression.exception.ImageCompressionException;
import azgracompress.data.Chunk2D; import azgracompress.data.Chunk2D;
import azgracompress.data.ImageU16; import azgracompress.data.ImageU16;
import azgracompress.io.ConcretePlaneLoader;
import azgracompress.io.IPlaneLoader;
import azgracompress.io.OutBitStream; import azgracompress.io.OutBitStream;
import azgracompress.io.RawDataIO;
import azgracompress.quantization.QuantizationValueCache; import azgracompress.quantization.QuantizationValueCache;
import azgracompress.quantization.vector.CodebookEntry; import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.LBGResult; import azgracompress.quantization.vector.LBGResult;
...@@ -90,6 +91,12 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -90,6 +91,12 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final InputFileInfo inputFileInfo = options.getInputFileInfo(); final InputFileInfo inputFileInfo = options.getInputFileInfo();
Stopwatch stopwatch = new Stopwatch(); Stopwatch stopwatch = new Stopwatch();
final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.hasReferencePlaneIndex(); final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.hasReferencePlaneIndex();
final ConcretePlaneLoader planeLoader;
try {
planeLoader = new ConcretePlaneLoader(inputFileInfo);
} catch (Exception e) {
throw new ImageCompressionException("Unable to create SCIFIO reader. " + e.getMessage());
}
VectorQuantizer quantizer = null; VectorQuantizer quantizer = null;
if (options.hasCodebookCacheFolder()) { if (options.hasCodebookCacheFolder()) {
...@@ -102,10 +109,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -102,10 +109,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
ImageU16 referencePlane = null; ImageU16 referencePlane = null;
try { try {
referencePlane = RawDataIO.loadImageU16(inputFileInfo.getFilePath(), referencePlane = planeLoader.loadPlaneU16(options.getReferencePlaneIndex());
inputFileInfo.getDimensions(), } catch (IOException ex) {
options.getReferencePlaneIndex());
} catch (Exception ex) {
throw new ImageCompressionException("Unable to load reference plane data.", ex); throw new ImageCompressionException("Unable to load reference plane data.", ex);
} }
...@@ -125,10 +130,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -125,10 +130,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
ImageU16 plane = null; ImageU16 plane = null;
try { try {
plane = RawDataIO.loadImageU16(inputFileInfo.getFilePath(), plane = planeLoader.loadPlaneU16(planeIndex);
inputFileInfo.getDimensions(), } catch (IOException ex) {
planeIndex);
} catch (Exception ex) {
throw new ImageCompressionException("Unable to load plane data.", ex); throw new ImageCompressionException("Unable to load plane data.", ex);
} }
...@@ -165,33 +168,38 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -165,33 +168,38 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
* @return Quantization vectors of configured quantization. * @return Quantization vectors of configured quantization.
* @throws IOException When reading fails. * @throws IOException When reading fails.
*/ */
private int[][] loadPlaneQuantizationVectors(final int planeIndex) throws IOException { private int[][] loadPlaneQuantizationVectors(final IPlaneLoader planeLoader,
ImageU16 refPlane = RawDataIO.loadImageU16(options.getInputFileInfo().getFilePath(), final int planeIndex) throws IOException {
options.getInputFileInfo().getDimensions(), ImageU16 refPlane = planeLoader.loadPlaneU16(planeIndex);
planeIndex);
return refPlane.toQuantizationVectors(options.getVectorDimension()); return refPlane.toQuantizationVectors(options.getVectorDimension());
} }
private int[][] loadConfiguredPlanesData() throws ImageCompressionException { private int[][] loadConfiguredPlanesData() throws ImageCompressionException {
final int vectorSize = options.getVectorDimension().getX() * options.getVectorDimension().getY(); final int vectorSize = options.getVectorDimension().getX() * options.getVectorDimension().getY();
final InputFileInfo ifi = options.getInputFileInfo(); final InputFileInfo inputFileInfo = options.getInputFileInfo();
final ConcretePlaneLoader planeLoader;
try {
planeLoader = new ConcretePlaneLoader(inputFileInfo);
} catch (Exception e) {
throw new ImageCompressionException("Unable to create SCIFIO reader. " + e.getMessage());
}
int[][] trainData = null; int[][] trainData = null;
Stopwatch s = new Stopwatch(); Stopwatch s = new Stopwatch();
s.start(); s.start();
if (ifi.isPlaneIndexSet()) { if (inputFileInfo.isPlaneIndexSet()) {
Log("VQ: Loading single plane data."); Log("VQ: Loading single plane data.");
try { try {
trainData = loadPlaneQuantizationVectors(ifi.getPlaneIndex());
trainData = loadPlaneQuantizationVectors(planeLoader, inputFileInfo.getPlaneIndex());
} catch (IOException e) { } catch (IOException e) {
throw new ImageCompressionException("Failed to load reference image data.", e); throw new ImageCompressionException("Failed to load reference image data.", e);
} }
} else { } else {
Log(ifi.isPlaneRangeSet() ? "VQ: Loading plane range data." : "VQ: Loading all planes data."); Log(inputFileInfo.isPlaneRangeSet() ? "VQ: Loading plane range data." : "VQ: Loading all planes data.");
final int[] planeIndices = getPlaneIndicesForCompression(); final int[] planeIndices = getPlaneIndicesForCompression();
final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCountPerPlane( final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCountPerPlane(
ifi.getDimensions().toV2i(), inputFileInfo.getDimensions().toV2i(),
options.getVectorDimension()); options.getVectorDimension());
final int totalChunkCount = chunkCountPerPlane * planeIndices.length; final int totalChunkCount = chunkCountPerPlane * planeIndices.length;
...@@ -201,7 +209,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -201,7 +209,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
int planeCounter = 0; int planeCounter = 0;
for (final int planeIndex : planeIndices) { for (final int planeIndex : planeIndices) {
try { try {
planeVectors = loadPlaneQuantizationVectors(planeIndex); planeVectors = loadPlaneQuantizationVectors(planeLoader, planeIndex);
assert (planeVectors.length == chunkCountPerPlane) : "Wrong chunk count per plane"; assert (planeVectors.length == chunkCountPerPlane) : "Wrong chunk count per plane";
} catch (IOException e) { } catch (IOException e) {
throw new ImageCompressionException(String.format("Failed to load plane %d image data.", throw new ImageCompressionException(String.format("Failed to load plane %d image data.",
......
...@@ -8,13 +8,17 @@ public class ImageU16 { ...@@ -8,13 +8,17 @@ public class ImageU16 {
private final int height; private final int height;
private int[] data; private int[] data;
public ImageU16(int width, int height, int[] data) { public ImageU16(final int width, final int height, final int[] data) {
assert ((width * height) == data.length) : "Wrong data size in ImageU16 constructor."; assert ((width * height) == data.length) : "Wrong data size in ImageU16 constructor.";
this.width = width; this.width = width;
this.height = height; this.height = height;
this.data = data; this.data = data;
} }
public ImageU16(final V2i dims, final int[] data) {
this(dims.getX(), dims.getY(), data);
}
private int index(final int x, final int y) { private int index(final int x, final int y) {
assert ((x >= 0 && x < height) && (y >= 0 && y < width)) : "Index out of bounds"; assert ((x >= 0 && x < height) && (y >= 0 && y < width)) : "Index out of bounds";
return (x * width) + y; return (x * width) + y;
......
package azgracompress.io;
import azgracompress.cli.InputFileInfo;
import azgracompress.data.ImageU16;
import java.io.IOException;
public class ConcretePlaneLoader implements IPlaneLoader {
private final IPlaneLoader loader;
private final InputFileInfo inputFileInfo;
/**
* Create plane loader.
*
* @param inputFileInfo Information about input file.
* @throws Exception When fails to create SCIFIO reader.
*/
public ConcretePlaneLoader(final InputFileInfo inputFileInfo) throws Exception {
this.inputFileInfo = inputFileInfo;
if (inputFileInfo.isRAW()) {
loader = new RawDataLoader(inputFileInfo);
} else {
loader = new SCIFIOLoader(inputFileInfo);
}
}
@Override
public ImageU16 loadPlaneU16(int plane) throws IOException {
return loader.loadPlaneU16(plane);
}
@Override
public int[] loadPlanesU16Data(int[] planes) throws IOException {
return loader.loadPlanesU16Data(planes);
}
@Override
public int[] loadAllPlanesU16Data() throws IOException {
return loader.loadAllPlanesU16Data();
}
}
package azgracompress.io;
import azgracompress.cli.InputFileInfo;
import azgracompress.data.ImageU16;
import java.io.IOException;
public interface IPlaneLoader {
ImageU16 loadPlaneU16(final int plane) throws IOException;
int[] loadPlanesU16Data(int[] planes) throws IOException;
int[] loadAllPlanesU16Data() throws IOException;
}
package azgracompress.io;
import azgracompress.data.ImageU16;
import azgracompress.data.V3i;
import io.scif.jj2000.j2k.NotImplementedError;
import java.io.IOException;
/**
* Class handling loading and writing of plane data.
* Multiple data types should be supported.
* For start: RAW, TIFF
*/
public class ImagePlaneIO {
public static ImageU16 loadImageU16(final String rawFile,
final V3i rawDataDimension,
final int plane) throws IOException {
// TODO(Moravec): Handle loading of different types.
// TODO(Moravec): If the loaded image is not U16 convert it to U16 image.
throw new NotImplementedError();
}
public static int[] loadPlanesData(final String rawFile,
final V3i rawDataDims,
int[] planes) throws IOException {
// TODO(Moravec): Handle loading of different types.
// TODO(Moravec): If the loaded image is not U16 convert it to U16 image.
throw new NotImplementedError();
}
public static int[] loadAllPlanesData(final String rawFile, final V3i imageDims) throws IOException {
// TODO(Moravec): Handle loading of different types.
// TODO(Moravec): If the loaded image is not U16 convert it to U16 image.
throw new NotImplementedError();
}
public static void writeImageU16(final String rawFile,
final ImageU16 image,
final boolean littleEndian) throws IOException {
// TODO(Moravec): Handle writing of U16 image to multiple types.
throw new NotImplementedError();
}
}
package azgracompress.io; package azgracompress.io;
import azgracompress.data.ImageU16; import azgracompress.data.ImageU16;
import azgracompress.data.V3i;
import azgracompress.utilities.TypeConverter; import azgracompress.utilities.TypeConverter;
import java.io.*; import java.io.FileOutputStream;
import java.util.Arrays; import java.io.IOException;
public class RawDataIO { public class RawDataIO {
/**
* Load single U16 image from RAW data file.
*
* @param rawFile Path to the raw file.
* @param rawDataDimension X (Width), Y (Height) of plane and Z(Number of planes)
* @param plane Plane index.
* @return U16 image specified by the plane
*/
public static ImageU16 loadImageU16(final String rawFile,
final V3i rawDataDimension,
final int plane) throws IOException {
byte[] buffer;
try (FileInputStream fileStream = new FileInputStream(rawFile)) {
final long planeSize = (long) rawDataDimension.getX() * (long) rawDataDimension.getY() * 2;
final long expectedFileSize = planeSize * rawDataDimension.getZ();
final long fileSize = fileStream.getChannel().size();
if (expectedFileSize != fileSize) {
throw new IOException(
"File specified by `rawFile` doesn't contains raw data for image of dimensions " +
"`rawDataDimension`");
}
final long planeOffset = plane * planeSize;
buffer = new byte[(int) planeSize];
if (fileStream.skip(planeOffset) != planeOffset) {
throw new IOException("Failed to skip.");
}
if (fileStream.read(buffer, 0, (int) planeSize) != planeSize) {
throw new IOException("Read wrong number of bytes.");
}
}
return new ImageU16(rawDataDimension.getX(),
rawDataDimension.getY(),
TypeConverter.unsignedShortBytesToIntArray(buffer));
}
public static int[] loadPlanesData(final String rawFile,
final V3i rawDataDims,
int[] planes) throws IOException {
if (planes.length < 1)
return new int[0];
final int planeValueCount = rawDataDims.getX() * rawDataDims.getY();
final long planeDataSize = 2 * (long) planeValueCount;
final long totalValueCount = (long) planeValueCount * planes.length;
int[] values = new int[(int) totalValueCount];
if (totalValueCount > (long) Integer.MAX_VALUE) {
throw new IOException("Integer count is too big.");
}
Arrays.sort(planes);
try (FileInputStream fileStream = new FileInputStream(rawFile);
DataInputStream dis = new DataInputStream(new BufferedInputStream(fileStream, 8192))) {
int lastIndex = 0;
int valIndex = 0;
for (final int planeIndex : planes) {
// Skip specific number of bytes to get to the next plane.
final int requestedSkip = (planeIndex == 0) ? 0 : ((planeIndex - lastIndex) - 1) * (int) planeDataSize;
lastIndex = planeIndex;
final int actualSkip = dis.skipBytes(requestedSkip);
if (requestedSkip != actualSkip) {
throw new IOException("Skip operation failed.");
}
for (int i = 0; i < planeValueCount; i++) {
values[valIndex++] = dis.readUnsignedShort();
}
}
}
return values;
}
public static int[] loadAllPlanesData(final String rawFile, final V3i imageDims) throws IOException {
final long dataSize = (long) imageDims.getX() * (long) imageDims.getY() * (long) imageDims.getZ();
int[] values = new int[(int) dataSize];
if (dataSize > (long) Integer.MAX_VALUE) {
throw new IOException("RawFile size is too big.");
}
try (FileInputStream fileStream = new FileInputStream(rawFile);
DataInputStream dis = new DataInputStream(new BufferedInputStream(fileStream, 8192))) {
for (int i = 0; i < (int) dataSize; i++) {
values[i] = dis.readUnsignedShort();
}
}
return values;
}
public static void writeImageU16(final String rawFile, public static void writeImageU16(final String rawFile,
final ImageU16 image, final ImageU16 image,
......
package azgracompress.io;
import azgracompress.cli.InputFileInfo;
import azgracompress.data.ImageU16;
import azgracompress.data.V3i;
import azgracompress.utilities.TypeConverter;
import java.io.*;
import java.util.Arrays;
public class RawDataLoader implements IPlaneLoader {
private final InputFileInfo inputFileInfo;
public RawDataLoader(final InputFileInfo inputFileInfo) {
this.inputFileInfo = inputFileInfo;
}
@Override
public ImageU16 loadPlaneU16(int plane) throws IOException {
byte[] buffer;
final V3i rawDataDimension = inputFileInfo.getDimensions();
try (FileInputStream fileStream = new FileInputStream(inputFileInfo.getFilePath())) {
final long planeSize = (long) rawDataDimension.getX() * (long) rawDataDimension.getY() * 2;
final long expectedFileSize = planeSize * rawDataDimension.getZ();
final long fileSize = fileStream.getChannel().size();
if (expectedFileSize != fileSize) {
throw new IOException(
"File specified by `rawFile` doesn't contains raw data for image of dimensions " +
"`rawDataDimension`");
}
final long planeOffset = plane * planeSize;
buffer = new byte[(int) planeSize];
if (fileStream.skip(planeOffset) != planeOffset) {
throw new IOException("Failed to skip.");
}
if (fileStream.read(buffer, 0, (int) planeSize) != planeSize) {
throw new IOException("Read wrong number of bytes.");
}
}
return new ImageU16(rawDataDimension.getX(),
rawDataDimension.getY(),
TypeConverter.unsignedShortBytesToIntArray(buffer));
}
@Override
public int[] loadPlanesU16Data(int[] planes) throws IOException {
if (planes.length < 1)
return new int[0];
final int planeValueCount = inputFileInfo.getDimensions().getX() * inputFileInfo.getDimensions().getY();
final long planeDataSize = 2 * (long) planeValueCount;
final long totalValueCount = (long) planeValueCount * planes.length;
int[] values = new int[(int) totalValueCount];
if (totalValueCount > (long) Integer.MAX_VALUE) {
throw new IOException("Integer count is too big.");
}
Arrays.sort(planes);
try (FileInputStream fileStream = new FileInputStream(inputFileInfo.getFilePath());
DataInputStream dis = new DataInputStream(new BufferedInputStream(fileStream, 8192))) {
int lastIndex = 0;
int valIndex = 0;
for (final int planeIndex : planes) {
// Skip specific number of bytes to get to the next plane.
final int requestedSkip = (planeIndex == 0) ? 0 : ((planeIndex - lastIndex) - 1) * (int) planeDataSize;
lastIndex = planeIndex;
final int actualSkip = dis.skipBytes(requestedSkip);
if (requestedSkip != actualSkip) {
throw new IOException("Skip operation failed.");
}
for (int i = 0; i < planeValueCount; i++) {
values[valIndex++] = dis.readUnsignedShort();
}
}
}
return values;
}
@Override
public int[] loadAllPlanesU16Data() throws IOException {
final V3i imageDims = inputFileInfo.getDimensions();
final long dataSize = (long) imageDims.getX() * (long) imageDims.getY() * (long) imageDims.getZ();
int[] values = new int[(int) dataSize];
if (dataSize > (long) Integer.MAX_VALUE) {
throw new IOException("RawFile size is too big.");
}
try (FileInputStream fileStream = new FileInputStream(inputFileInfo.getFilePath());
DataInputStream dis = new DataInputStream(new BufferedInputStream(fileStream, 8192))) {
for (int i = 0; i < (int) dataSize; i++) {
values[i] = dis.readUnsignedShort();
}
}
return values;
}
}
package azgracompress.io;
import azgracompress.ScifioWrapper;
import azgracompress.cli.InputFileInfo;
import azgracompress.data.ImageU16;
import azgracompress.utilities.TypeConverter;
import io.scif.FormatException;
import io.scif.Reader;
import io.scif.jj2000.j2k.NotImplementedError;
import java.io.IOException;
public class SCIFIOLoader implements IPlaneLoader {
private final InputFileInfo inputFileInfo;
private final Reader reader;
/**
* Create SCIFIO reader from input file.
*
* @param inputFileInfo Input file info.
* @throws IOException When fails to create SCIFIO reader.
* @throws FormatException When fails to create SCIFIO reader.
*/
public SCIFIOLoader(final InputFileInfo inputFileInfo) throws IOException, FormatException {
this.inputFileInfo = inputFileInfo;
this.reader = ScifioWrapper.getReader(this.inputFileInfo.getFilePath());
}
@Override
public ImageU16 loadPlaneU16(int plane) throws IOException {
byte[] planeBytes;
try {
planeBytes = reader.openPlane(0, plane).getBytes();
} catch (FormatException e) {
throw new IOException("Unable to open plane with the reader. " + e.getMessage());
}
final int[] data = TypeConverter.unsignedShortBytesToIntArray(planeBytes);
return new ImageU16(inputFileInfo.getDimensions().toV2i(), data);
}
@Override
public int[] loadPlanesU16Data(int[] planes) throws IOException {
throw new NotImplementedError("NOT IMPLEMENTED");
}
@Override
public int[] loadAllPlanesU16Data() throws IOException {
throw new NotImplementedError("NOT IMPLEMENTED");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment