diff --git a/src/main/java/azgracompress/benchmark/VQBenchmark.java b/src/main/java/azgracompress/benchmark/VQBenchmark.java index 3161f1a04876d654fc6555a9676cecd4a15a36c9..366dfbffd78976f657eeb2598e3828e5998b3b88 100644 --- a/src/main/java/azgracompress/benchmark/VQBenchmark.java +++ b/src/main/java/azgracompress/benchmark/VQBenchmark.java @@ -1,36 +1,23 @@ package azgracompress.benchmark; -import azgracompress.U16; -import azgracompress.cache.QuantizationCacheManager; import azgracompress.cli.ParsedCliOptions; -import azgracompress.compression.CompressionOptions; -import azgracompress.data.*; -import azgracompress.io.loader.IPlaneLoader; -import azgracompress.io.loader.PlaneLoaderFactory; -import azgracompress.quantization.vector.LBGResult; -import azgracompress.quantization.vector.LBGVectorQuantizer; -import azgracompress.quantization.vector.VQCodebook; -import azgracompress.quantization.vector.VectorQuantizer; -import azgracompress.utilities.Utils; - -import java.io.File; -import java.io.IOException; +import azgracompress.data.Chunk2D; +import azgracompress.data.ImageU16; +import azgracompress.data.V2i; +import azgracompress.data.V3i; public class VQBenchmark extends BenchmarkBase { - final static V2i DEFAULT_QVECTOR = new V2i(3, 3); - public VQBenchmark(final ParsedCliOptions options) { super(options); } @Override public void startBenchmark() { - startBenchmark(DEFAULT_QVECTOR); + startBenchmark(options.getQuantizationVector()); } - private ImageU16 reconstructImageFromQuantizedVectors(final ImageU16 plane, - final int[][] vectors, + private ImageU16 reconstructImageFromQuantizedVectors(final int[][] vectors, final V2i qVector) { Chunk2D reconstructedChunk = new Chunk2D(new V2i(rawImageDims.getX(), rawImageDims.getY())); if (qVector.getY() > 1) { @@ -42,111 +29,98 @@ public class VQBenchmark extends BenchmarkBase { return reconstructedChunk.asImageU16(); } - private int[][] getPlaneVectors(final ImageU16 plane, final V2i qVector) { - return plane.toQuantizationVectors(qVector); - } - - public void startBenchmark(final V2i qVector) { - if (planes.length < 1) { - return; - } - IPlaneLoader planeLoader; - try { - planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo()); - } catch (Exception e) { - e.printStackTrace(); - System.err.println("Unable to create SCIFIO reader."); - return; - } - if (qVector.getY() > 1) { - System.out.println("2D qVector"); - } else { - System.out.println("1D qVector"); - } - boolean dirCreated = new File(this.outputDirectory).mkdirs(); - System.out.println(String.format("|CODEBOOK| = %d", codebookSize)); - VectorQuantizer quantizer = null; - - if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { - System.out.println("Loading codebook from cache"); - QuantizationCacheManager cacheManager = new QuantizationCacheManager(cacheFolder); - final VQCodebook codebook = cacheManager.loadVQCodebook(inputFile, codebookSize, qVector.toV3i()); - if (codebook == null) { - System.err.println("Failed to read quantization vectors from cache."); - return; - } - quantizer = new VectorQuantizer(codebook); - System.out.println("Created quantizer from cache"); - - } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { - final int middlePlaneIndex = rawImageDims.getZ() / 2; - final ImageU16 middlePlane; - try { - - middlePlane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(middlePlaneIndex)); - } catch (IOException e) { - e.printStackTrace(); - System.err.println("Failed to load middle plane data."); - return; - } - - final int[][] refPlaneData = getPlaneVectors(middlePlane, qVector); - LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(refPlaneData, - codebookSize, - workerCount, - qVector.toV3i()); - final LBGResult vqResult = vqInitializer.findOptimalCodebook(); - quantizer = new VectorQuantizer(vqResult.getCodebook()); - System.out.println("Created quantizer from middle plane."); - } - - for (final int planeIndex : planes) { - System.out.println(String.format("Loading plane %d ...", planeIndex)); - - final ImageU16 plane; - try { - plane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(planeIndex)); - } catch (IOException e) { - e.printStackTrace(); - System.err.println(String.format("Failed to load plane %d data. Skipping plane.", planeIndex)); - return; - } - - final int[][] planeData = getPlaneVectors(plane, qVector); - - - if (options.getCodebookType() == CompressionOptions.CodebookType.Individual) { - LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeData, - codebookSize, - workerCount, - qVector.toV3i()); - LBGResult vqResult = vqInitializer.findOptimalCodebook(); - quantizer = new VectorQuantizer(vqResult.getCodebook()); - System.out.println("Created plane quantizer."); - } - - final String quantizedFile = String.format(QUANTIZED_FILE_TEMPLATE, planeIndex, codebookSize); - final String diffFile = String.format(DIFFERENCE_FILE_TEMPLATE, planeIndex, codebookSize); - final String absoluteDiffFile = String.format(ABSOLUTE_DIFFERENCE_FILE_TEMPLATE, - planeIndex, - codebookSize); - - final int[][] quantizedData = quantizer.quantize(planeData, workerCount); - - final ImageU16 quantizedImage = reconstructImageFromQuantizedVectors(plane, quantizedData, qVector); - - - final int[] diffArray = Utils.getDifference(plane.getData(), quantizedImage.getData()); - final double mse = Utils.calculateMse(diffArray); - final double PSNR = Utils.calculatePsnr(mse, U16.Max); - System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR)); - - if (!saveQuantizedPlaneData(quantizedImage.getData(), quantizedFile)) { - System.err.println("Failed to save quantized plane."); - return; - } - - saveDifference(diffArray, diffFile, absoluteDiffFile); - } + public void startBenchmark(final V3i qVector) { + // NOTE(Moravec): This will be enabled once we need to benchmark something. + // if (planes.length < 1) { + // return; + // } + // IPlaneLoader planeLoader; + // try { + // planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo()); + // } catch (Exception e) { + // e.printStackTrace(); + // System.err.println("Unable to create specific reader."); + // return; + // } + // if (qVector.getY() > 1) { + // System.out.println("2D qVector"); + // } else { + // System.out.println("1D qVector"); + // } + // boolean dirCreated = new File(this.outputDirectory).mkdirs(); + // System.out.printf("|CODEBOOK| = %d%n", codebookSize); + // VectorQuantizer quantizer = null; + // + // if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { + // System.out.println("Loading codebook from cache"); + // QuantizationCacheManager cacheManager = new QuantizationCacheManager(cacheFolder); + // final VQCodebook codebook = cacheManager.loadVQCodebook(inputFile, codebookSize, qVector); + // if (codebook == null) { + // System.err.println("Failed to read quantization vectors from cache."); + // return; + // } + // quantizer = new VectorQuantizer(codebook); + // System.out.println("Created quantizer from cache"); + // + // } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { + // final int middlePlaneIndex = rawImageDims.getZ() / 2; + // int[][] refPlaneData; + // try { + // refPlaneData = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(middlePlaneIndex)); + // } catch (ImageCompressionException e) { + // e.printStackTrace(); + // System.err.println("Failed to load middle plane data."); + // return; + // } + // + // LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(refPlaneData, codebookSize, workerCount, qVector); + // final LBGResult vqResult = vqInitializer.findOptimalCodebook(); + // + // quantizer = new VectorQuantizer(vqResult.getCodebook()); + // System.out.println("Created quantizer from middle plane."); + // } + // + // for (final int planeIndex : planes) { + // System.out.printf("Loading plane %d ...%n", planeIndex); + // + // int[][] planeData; + // try { + // planeData = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(planeIndex)); + // } catch (ImageCompressionException e) { + // e.printStackTrace(); + // System.err.printf("Failed to load plane %d data.", planeIndex); + // return; + // } + // + // + // if (options.getCodebookType() == CompressionOptions.CodebookType.Individual) { + // LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeData, codebookSize, workerCount, qVector); + // LBGResult vqResult = vqInitializer.findOptimalCodebook(); + // quantizer = new VectorQuantizer(vqResult.getCodebook()); + // System.out.println("Created plane quantizer."); + // } + // + // final String quantizedFile = String.format(QUANTIZED_FILE_TEMPLATE, planeIndex, codebookSize); + // final String diffFile = String.format(DIFFERENCE_FILE_TEMPLATE, planeIndex, codebookSize); + // final String absoluteDiffFile = String.format(ABSOLUTE_DIFFERENCE_FILE_TEMPLATE, planeIndex, codebookSize); + // + // assert (quantizer != null); + // final int[][] quantizedData = quantizer.quantize(planeData, workerCount); + // + // final ImageU16 quantizedImage = reconstructImageFromQuantizedVectors(quantizedData, qVector.toV2i()); + // + // + // final int[] diffArray = Utils.getDifference(plane.getData(), quantizedImage.getData()); + // final double mse = Utils.calculateMse(diffArray); + // final double PSNR = Utils.calculatePsnr(mse, U16.Max); + // System.out.printf("MSE: %.4f\tPSNR: %.4f(dB)%n", mse, PSNR); + // + // if (!saveQuantizedPlaneData(quantizedImage.getData(), quantizedFile)) { + // System.err.println("Failed to save quantized plane."); + // return; + // } + // + // saveDifference(diffArray, diffFile, absoluteDiffFile); + // } } } diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java index 976f40fcc4fd37d9ec9acbd768c7529381b43748..777236c62124b0165b2b4988b15a4fb59559b516 100644 --- a/src/main/java/azgracompress/compression/VQImageCompressor.java +++ b/src/main/java/azgracompress/compression/VQImageCompressor.java @@ -2,8 +2,6 @@ package azgracompress.compression; import azgracompress.cache.QuantizationCacheManager; import azgracompress.compression.exception.ImageCompressionException; -import azgracompress.data.Chunk2D; -import azgracompress.data.ImageU16; import azgracompress.data.Range; import azgracompress.fileformat.QuantizationType; import azgracompress.huffman.Huffman; @@ -12,6 +10,7 @@ import azgracompress.io.loader.IPlaneLoader; import azgracompress.io.loader.PlaneLoaderFactory; import azgracompress.quantization.vector.*; import azgracompress.utilities.Stopwatch; +import azgracompress.utilities.Utils; import org.jetbrains.annotations.NotNull; import java.io.DataOutputStream; @@ -32,9 +31,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm private VectorQuantizer trainVectorQuantizerFromPlaneVectors(final int[][] planeVectors) { LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeVectors, - getCodebookSize(), - options.getWorkerCount(), - options.getQuantizationVector()); + getCodebookSize(), + options.getWorkerCount(), + options.getQuantizationVector()); LBGResult vqResult = vqInitializer.findOptimalCodebook(); return new VectorQuantizer(vqResult.getCodebook()); } @@ -79,14 +78,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder()); if (!cacheManager.doesVQCacheExists(options.getInputDataInfo().getCacheFileName(), - getCodebookSize(), - options.getQuantizationVector())) { + getCodebookSize(), + options.getQuantizationVector())) { trainAndSaveCodebook(); } final VQCodebook codebook = cacheManager.loadVQCodebook(options.getInputDataInfo().getCacheFileName(), - getCodebookSize(), - options.getQuantizationVector()); + getCodebookSize(), + options.getQuantizationVector()); if (codebook == null) { throw new ImageCompressionException("Failed to read quantization vectors from cache."); @@ -132,17 +131,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm writeQuantizerToCompressStream(quantizer, compressStream); } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { stopwatch.restart(); - - final int middlePlaneIndex = getMiddlePlaneIndex(); - ImageU16 middlePlane = null; - try { - middlePlane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(middlePlaneIndex)); - } catch (IOException ex) { - throw new ImageCompressionException("Unable to load reference plane data.", ex); - } - - reportStatusToListeners(String.format("Training vector quantizer from middle plane %d.", middlePlaneIndex)); - final int[][] refPlaneVectors = middlePlane.toQuantizationVectors(options.getQuantizationVector().toV2i()); + reportStatusToListeners("Training vector quantizer from middle plane."); + final int[][] refPlaneVectors = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(getMiddlePlaneIndex())); quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); writeQuantizerToCompressStream(quantizer, compressStream); @@ -158,14 +148,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm stopwatch.restart(); reportStatusToListeners(String.format("Loading plane %d.", planeIndex)); - ImageU16 plane = null; - try { - plane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(planeIndex)); - } catch (IOException ex) { - throw new ImageCompressionException("Unable to load plane data.", ex); - } - - final int[][] planeVectors = plane.toQuantizationVectors(options.getQuantizationVector().toV2i()); + final int[][] planeVectors = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(planeIndex)); if (!hasGeneralQuantizer) { reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex)); @@ -182,99 +165,41 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm stopwatch.stop(); reportProgressToListeners(planeIndex, planeIndices.length, - "Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString()); + "Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString()); } return planeDataSizes; } - - /** - * Load plane and convert the plane into quantization vectors. - * - * @param planeIndex Zero based plane index. - * @return Quantization vectors of configured quantization. - * @throws IOException When reading fails. - */ - - private int[][] loadPlaneQuantizationVectors(final IPlaneLoader planeLoader, - final int planeIndex) throws IOException { - ImageU16 refPlane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(planeIndex)); - return refPlane.toQuantizationVectors(options.getQuantizationVector().toV2i()); - } - - private int[][] loadConfiguredPlanesData() throws ImageCompressionException { + @Override + public void trainAndSaveCodebook() throws ImageCompressionException { + reportStatusToListeners("Loading image data..."); final IPlaneLoader planeLoader; try { planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo()); - planeLoader.setWorkerCount(options.getWorkerCount()); } catch (Exception e) { - throw new ImageCompressionException("Unable to create reader. " + e.getMessage()); + throw new ImageCompressionException("Unable to create plane reader. " + e.getMessage()); } - if (options.getQuantizationType().isOneOf(QuantizationType.Vector1D, QuantizationType.Vector2D)) { - // TODO: Chunk2D operations should eventually be moved to loaders. - // Same as voxel loading, so that we wouldn't have to copy data twice. - final int vectorSize = options.getQuantizationVector().toV2i().multiplyTogether(); - - int[][] trainData; - Stopwatch s = Stopwatch.startNew(); - if (options.getInputDataInfo().isPlaneIndexSet()) { - reportStatusToListeners("VQ: Loading single plane data."); - try { - trainData = loadPlaneQuantizationVectors(planeLoader, options.getInputDataInfo().getPlaneIndex()); - } catch (IOException e) { - throw new ImageCompressionException("Failed to load plane data.", e); - } - } else { - reportStatusToListeners(options.getInputDataInfo().isPlaneRangeSet() ? - "VQ: Loading plane range data." : "VQ: Loading all planes data."); - - final int[] planeIndices = getPlaneIndicesForCompression(); - final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCount(options.getInputDataInfo().getDimensions().toV2i(), - options.getQuantizationVector().toV2i()); - final int totalChunkCount = chunkCountPerPlane * planeIndices.length; - trainData = new int[totalChunkCount][vectorSize]; - - int[][] planeVectors; - int planeCounter = 0; - for (final int planeIndex : planeIndices) { - try { - planeVectors = loadPlaneQuantizationVectors(planeLoader, planeIndex); - assert (planeVectors.length == chunkCountPerPlane) : "Wrong chunk count per plane"; - } catch (IOException e) { - throw new ImageCompressionException(String.format("Failed to load plane %d image data.", planeIndex), e); - } - - System.arraycopy(planeVectors, 0, trainData, (planeCounter * chunkCountPerPlane), chunkCountPerPlane); - ++planeCounter; - } - } - s.stop(); - reportStatusToListeners("Quantization vector load took: " + s.getElapsedTimeString()); - return trainData; - } else { - if (options.getQuantizationType() != QuantizationType.Vector3D) { - throw new ImageCompressionException("Invalid QuantizationType, expected: `QuantizationType.Vector3D`, but got: " + - options.getQuantizationType().toString()); - } - try { - return planeLoader.loadVoxels(options.getQuantizationVector()); - } catch (IOException e) { - throw new ImageCompressionException("Unable to load voxels.", e); - } + int[][] trainingData; + if (options.getInputDataInfo().isPlaneIndexSet()) { + reportStatusToListeners("VQ: Loading single plane data."); + final int planeIndex = options.getInputDataInfo().getPlaneIndex(); + trainingData = planeLoader.loadVectorsFromPlaneRange(options, new Range<>(planeIndex, planeIndex + 1)); + } else if (options.getInputDataInfo().isPlaneRangeSet()) { + reportStatusToListeners("VQ: Loading plane range data."); + trainingData = planeLoader.loadVectorsFromPlaneRange(options, options.getInputDataInfo().getPlaneRange()); + } else { + reportStatusToListeners("VQ: Loading all planes data."); + trainingData = planeLoader.loadVectorsFromPlaneRange(options, + new Range<>(0, options.getInputDataInfo().getDimensions().getZ())); } - } - @Override - public void trainAndSaveCodebook() throws ImageCompressionException { - reportStatusToListeners("Loading image data..."); - final int[][] trainingData = loadConfiguredPlanesData(); LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(trainingData, - getCodebookSize(), - options.getWorkerCount(), - options.getQuantizationVector()); + getCodebookSize(), + options.getWorkerCount(), + options.getQuantizationVector()); reportStatusToListeners("Starting LBG optimization."); vqInitializer.setStatusListener(this::reportStatusToListeners); @@ -348,8 +273,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffman, indices); stopwatch.stop(); reportProgressToListeners(voxelLayerIndex, voxelLayerCount, - "%d/%d Finished voxel layer %s compression pass in %s", - voxelLayerIndex, voxelLayerCount, voxelLayerRange.toString(), stopwatch.getElapsedTimeString()); + "%d/%d Finished voxel layer %s compression pass in %s", + voxelLayerIndex, voxelLayerCount, voxelLayerRange.toString(), stopwatch.getElapsedTimeString()); } return voxelLayersSizes; diff --git a/src/main/java/azgracompress/data/Chunk2D.java b/src/main/java/azgracompress/data/Chunk2D.java index 1f337dee9e7b71647c417170848cbd3026b1473c..3e4664d1a6f90bac52229a187504ffa96a33dbab 100644 --- a/src/main/java/azgracompress/data/Chunk2D.java +++ b/src/main/java/azgracompress/data/Chunk2D.java @@ -70,32 +70,6 @@ public class Chunk2D { return String.format("2D shape %s %d values", dims.toString(), data.length); } - /** - * Divide this Chunk to 1D row vector of given length. - * - * @param vectorSize Vector length. - * @return Array of row vectors. - */ - public int[][] divideInto1DVectors(final int vectorSize) { - final int rowVectorCount = (int) Math.ceil(dims.getX() / (float) vectorSize); - final int vectorCount = rowVectorCount * dims.getY(); - int[][] imageVectors = new int[vectorCount][vectorSize]; - - int vec = 0; - int srcX; - for (int row = 0; row < dims.getY(); row++) { - for (int vecIndex = 0; vecIndex < rowVectorCount; vecIndex++) { - for (int x = 0; x < vectorSize; x++) { - srcX = (vecIndex * vectorSize) + x; - imageVectors[vec][x] = isInside(srcX, row) ? data[index(srcX, row)] : FILL_VALUE; - } - ++vec; - } - } - - return imageVectors; - } - /** * Reconstruct this Chunk from array of 1D row vectors. * @@ -125,27 +99,6 @@ public class Chunk2D { } } - /** - * Divide this Chunk to 2D matrices of given dimensions. - * - * @param qVectorDims Matrix dimension. - * @return Array of matrix data. - */ - public int[][] divideInto2DVectors(final V2i qVectorDims) { - final int chunkSize = qVectorDims.getX() * qVectorDims.getY(); - final int chunkCount = calculateRequiredChunkCount(qVectorDims); - - int[][] vectors = new int[chunkCount][chunkSize]; - int vecIndex = 0; - - for (int chunkYOffset = 0; chunkYOffset < dims.getY(); chunkYOffset += qVectorDims.getY()) { - for (int chunkXOffset = 0; chunkXOffset < dims.getX(); chunkXOffset += qVectorDims.getX()) { - copyDataToVector(vectors[vecIndex++], qVectorDims, chunkXOffset, chunkYOffset); - } - } - return vectors; - } - /** * Reconstruct this Chunk (copy data) from matrix vectors. * @@ -169,17 +122,6 @@ public class Chunk2D { assert (vecIndex == vectors.length); } - - /** - * Calculate the number of required 2D matrices for plane. - * - * @param chunkDims Matrix dimension. - * @return Number of required chunks. - */ - private int calculateRequiredChunkCount(final V2i chunkDims) { - return calculateRequiredChunkCount(dims, chunkDims); - } - /** * Calculate the number of required 2D matrices for plane of given dimensions. * @@ -205,26 +147,6 @@ public class Chunk2D { return (((x >= 0) && (x < dims.getX())) && (y >= 0) && (y < dims.getY())); } - /** - * Copy this chunk data to chunk vector. - * - * @param vector Chunk vector. - * @param qVectorDims Dimensions of the vector. - * @param chunkXOffset Chunk X offset - * @param chunkYOffset Chunk Y offset. - */ - private void copyDataToVector(int[] vector, final V2i qVectorDims, final int chunkXOffset, final int chunkYOffset) { - int srcX, srcY; - for (int y = 0; y < qVectorDims.getY(); y++) { - srcY = chunkYOffset + y; - for (int x = 0; x < qVectorDims.getX(); x++) { - srcX = chunkXOffset + x; - final int dstIndex = index(x, y, qVectorDims.getY()); - vector[dstIndex] = isInside(srcX, srcY) ? data[index(srcX, srcY)] : FILL_VALUE; - } - } - } - /** * Copy data from chunk vector to this chunk. * diff --git a/src/main/java/azgracompress/data/ImageU16.java b/src/main/java/azgracompress/data/ImageU16.java index 65e9afbff0f1dcbaa8bef18845520e2382600a06..589ee1e7fe5dede51e9c9a17aee31579bb0318e8 100644 --- a/src/main/java/azgracompress/data/ImageU16.java +++ b/src/main/java/azgracompress/data/ImageU16.java @@ -54,20 +54,20 @@ public class ImageU16 { return height; } - /** - * Chunk the image data into quantization vectors of requested dimension. - * - * @param qVectorDims Quantization vector dimension. - * @return Array of quantization vectors. - */ - public int[][] toQuantizationVectors(final V2i qVectorDims) { - if (qVectorDims.getY() == 1) { - // 1D row vectors. - return as2dChunk().divideInto1DVectors(qVectorDims.getX()); - } else { - // 2D matrix vectors. - return as2dChunk().divideInto2DVectors(qVectorDims); - //return Chunk2D.chunksAsImageVectors(as2dChunk().divideIntoChunks(qVectorDims)); - } - } +// /** +// * Chunk the image data into quantization vectors of requested dimension. +// * +// * @param qVectorDims Quantization vector dimension. +// * @return Array of quantization vectors. +// */ +// public int[][] toQuantizationVectors(final V2i qVectorDims) { +// if (qVectorDims.getY() == 1) { +// // 1D row vectors. +// return as2dChunk().divideInto1DVectors(qVectorDims.getX()); +// } else { +// // 2D matrix vectors. +// return as2dChunk().divideInto2DVectors(qVectorDims); +// //return Chunk2D.chunksAsImageVectors(as2dChunk().divideIntoChunks(qVectorDims)); +// } +// } } diff --git a/src/main/java/azgracompress/io/loader/IPlaneLoader.java b/src/main/java/azgracompress/io/loader/IPlaneLoader.java index db338cf36b6dffa12b8b59b228e0ac968495f555..e88a46951b7a69106d93b37c5f77c4ee8a57c359 100644 --- a/src/main/java/azgracompress/io/loader/IPlaneLoader.java +++ b/src/main/java/azgracompress/io/loader/IPlaneLoader.java @@ -1,5 +1,7 @@ package azgracompress.io.loader; +import azgracompress.compression.CompressionOptions; +import azgracompress.compression.exception.ImageCompressionException; import azgracompress.data.Range; import azgracompress.data.V2i; import azgracompress.data.V3i; @@ -124,4 +126,33 @@ public interface IPlaneLoader { * @param threadCount Available thread count for loader. */ void setWorkerCount(final int threadCount); + + /** + * Load correct type of vectors (quantization type in options) from specified plane range. + * + * @param planeRange Plane range to load vectors from. + * @return Vector data from plane range. + * @throws ImageCompressionException When fails to load plane range. + */ + default int[][] loadVectorsFromPlaneRange(final CompressionOptions options, + final Range<Integer> planeRange) throws ImageCompressionException { + + setWorkerCount(supportParallelLoading() ? options.getWorkerCount() : 1); + + try { + switch (options.getQuantizationType()) { + case Vector1D: + return loadRowVectors(options.getQuantizationVector().getX(), planeRange); + case Vector2D: + return loadBlocks(options.getQuantizationVector().toV2i(), planeRange); + case Vector3D: + return loadVoxels(options.getQuantizationVector(), planeRange); + default: { + throw new ImageCompressionException("Invalid QuantizationType '" + options.getQuantizationType().toString() + "'"); + } + } + } catch (IOException e) { + throw new ImageCompressionException("Unable to load vectors QuantizationType=" + options.getQuantizationType(), e); + } + } } diff --git a/src/main/java/azgracompress/io/loader/PlaneLoaderFactory.java b/src/main/java/azgracompress/io/loader/PlaneLoaderFactory.java index b147eba2f70b90f52a7de6dd42344c557e407dfe..6783ba6959acc41f7844c342e68fc44d746c8c40 100644 --- a/src/main/java/azgracompress/io/loader/PlaneLoaderFactory.java +++ b/src/main/java/azgracompress/io/loader/PlaneLoaderFactory.java @@ -18,7 +18,7 @@ public final class PlaneLoaderFactory { case RawDataLoader: return new RawDataLoader((FileInputData) inputDataInfo); case SCIFIOLoader: - return new SCIFIOLoader((FileInputData)inputDataInfo); + return new SCIFIOLoader((FileInputData) inputDataInfo); case ImageJBufferLoader: return new ImageJBufferLoader((BufferInputData) inputDataInfo); default: diff --git a/src/main/java/azgracompress/utilities/Utils.java b/src/main/java/azgracompress/utilities/Utils.java index 9d7a773d9b7feb2913f3ffd640f17b7c5964660a..008f6509b0e7e8ddaefa1851c11ddd424a8254eb 100644 --- a/src/main/java/azgracompress/utilities/Utils.java +++ b/src/main/java/azgracompress/utilities/Utils.java @@ -1,6 +1,7 @@ package azgracompress.utilities; import azgracompress.U16; +import azgracompress.data.Range; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -10,6 +11,10 @@ import java.util.ArrayList; public class Utils { + public static Range<Integer> singlePlaneRange(final int index) { + return new Range<>(index, index + 1); + } + public static double calculatePsnr(final double mse, final int signalMax) { double psnr = 10.0 * Math.log10((Math.pow(signalMax, 2) / mse)); return psnr; @@ -19,7 +24,7 @@ public class Utils { FileInputStream fileStream = new FileInputStream(path); try { throw new FileNotFoundException("Implement this actually!"); -// return fileStream.readAllBytes(); + // return fileStream.readAllBytes(); } catch (IOException e) { e.printStackTrace(); }