diff --git a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java index 603c1cd5c4ba9f8c48fc4b08373abc4da49e1266..89b5fd76724196f662c358b72b86a1062357ee9c 100644 --- a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java +++ b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java @@ -1,5 +1,7 @@ package azgracompress.compression; +import azgracompress.compression.listeners.IProgressListener; +import azgracompress.compression.listeners.IStatusListener; import azgracompress.io.InputData; import azgracompress.compression.exception.ImageCompressionException; import azgracompress.huffman.Huffman; @@ -15,9 +17,52 @@ public abstract class CompressorDecompressorBase { protected final CompressionOptions options; private final int codebookSize; + private IStatusListener statusListener = null; + private IProgressListener progressListener = null; + public CompressorDecompressorBase(CompressionOptions options) { this.options = options; this.codebookSize = (int) Math.pow(2, this.options.getBitsPerCodebookIndex()); + // Default status listener, which can be override by setStatusListener. + } + + public void setStatusListener(IStatusListener listener) { + this.statusListener = listener; + } + + public void setProgressListener(IProgressListener listener) { + this.progressListener = listener; + } + + protected IProgressListener getProgressListener() { + return progressListener; + } + + protected IStatusListener getStatusListener() { + return statusListener; + } + + protected void reportStatusToListeners(final String status) { + if (this.statusListener != null) { + this.statusListener.sendMessage(status); + } + } + + protected void reportStatusToListeners(final String format, final Object... args) { + reportStatusToListeners(String.format(format, args)); + } + + protected void reportProgressListeners(final int index, final int finalIndex, final String message) { + if (this.progressListener != null) { + this.progressListener.sendProgress(message, index, finalIndex); + } + } + + protected void reportProgressListeners(final int index, + final int finalIndex, + final String message, + final Object... args) { + reportProgressListeners(index, finalIndex, String.format(message, args)); } protected int[] createHuffmanSymbols(final int codebookSize) { @@ -76,28 +121,12 @@ public abstract class CompressorDecompressorBase { } - protected void Log(final String message) { + private void defaultLog(final String message) { if (options.isVerbose()) { System.out.println(message); } } - protected void Log(final String format, final Object... args) { - if (options.isVerbose()) { - System.out.println(String.format(format, args)); - } - } - - protected void DebugLog(final String message) { - System.out.println(message); - } - - protected void LogError(final String message) { - if (options.isVerbose()) { - System.err.println(message); - } - } - /** * Get index of the middle plane. * diff --git a/src/main/java/azgracompress/compression/IImageCompressor.java b/src/main/java/azgracompress/compression/IImageCompressor.java index be9d499576b1de60a8e24bfd86f0580a1d82d8bb..c2e6ee2ec27198996c18c7f16eaac15167b5d3a8 100644 --- a/src/main/java/azgracompress/compression/IImageCompressor.java +++ b/src/main/java/azgracompress/compression/IImageCompressor.java @@ -4,7 +4,7 @@ import azgracompress.compression.exception.ImageCompressionException; import java.io.DataOutputStream; -public interface IImageCompressor { +public interface IImageCompressor extends IListenable { /** * Compress the image planes. diff --git a/src/main/java/azgracompress/compression/IImageDecompressor.java b/src/main/java/azgracompress/compression/IImageDecompressor.java index da1f871184339758abd3d6a8fe47aa5e0ed7646c..7e2d35cabca3759ea4efc65fdbe9252b48409e87 100644 --- a/src/main/java/azgracompress/compression/IImageDecompressor.java +++ b/src/main/java/azgracompress/compression/IImageDecompressor.java @@ -6,7 +6,7 @@ import azgracompress.fileformat.QCMPFileHeader; import java.io.DataInputStream; import java.io.DataOutputStream; -public interface IImageDecompressor { +public interface IImageDecompressor extends IListenable { /** * Get correct size of data block. * @@ -38,5 +38,4 @@ public interface IImageDecompressor { void decompressToBuffer(DataInputStream compressedStream, short[][] buffer, final QCMPFileHeader header) throws ImageDecompressionException; - } diff --git a/src/main/java/azgracompress/compression/IListenable.java b/src/main/java/azgracompress/compression/IListenable.java new file mode 100644 index 0000000000000000000000000000000000000000..4b17fe615b3f006b1d37efc3e250b45a450e3d03 --- /dev/null +++ b/src/main/java/azgracompress/compression/IListenable.java @@ -0,0 +1,20 @@ +package azgracompress.compression; + +import azgracompress.compression.listeners.IProgressListener; +import azgracompress.compression.listeners.IStatusListener; + +public interface IListenable { + /** + * Set status listener. Status messages are reported to this listener. + * + * @param listener Status listener. + */ + void setStatusListener(IStatusListener listener); + + /** + * Set progress listener. Status messages with progress information are reported to this listener. + * + * @param listener Progress listener. + */ + void setProgressListener(IProgressListener listener); +} diff --git a/src/main/java/azgracompress/compression/ImageCompressor.java b/src/main/java/azgracompress/compression/ImageCompressor.java index ed65191b96868516a51eaccc370d56cdb42eae2d..4c0dbe2558442ee3caaff72c9788b3f4202160f3 100644 --- a/src/main/java/azgracompress/compression/ImageCompressor.java +++ b/src/main/java/azgracompress/compression/ImageCompressor.java @@ -2,6 +2,8 @@ package azgracompress.compression; import azgracompress.cli.ParsedCliOptions; import azgracompress.compression.exception.ImageCompressionException; +import azgracompress.compression.listeners.IProgressListener; +import azgracompress.compression.listeners.IStatusListener; import azgracompress.fileformat.QCMPFileHeader; import java.io.*; @@ -19,19 +21,32 @@ public class ImageCompressor extends CompressorDecompressorBase { * @return Correct implementation of image compressor or null if configuration is not valid. */ private IImageCompressor getImageCompressor() { + IImageCompressor compressor = null; switch (options.getQuantizationType()) { - case Scalar: { - return new SQImageCompressor(options); - } + case Scalar: + compressor = new SQImageCompressor(options); + break; case Vector1D: - case Vector2D: { - return new VQImageCompressor(options); - } + case Vector2D: + + compressor = new VQImageCompressor(options); + break; case Vector3D: case Invalid: default: return null; } + + // Forward listeners to image compressor. + final IStatusListener parentStatusListener = getStatusListener(); + if (parentStatusListener != null) + compressor.setStatusListener(parentStatusListener); + + final IProgressListener parentProgressListener = getProgressListener(); + if (parentProgressListener != null) + compressor.setProgressListener(parentProgressListener); + + return compressor; } private void reportCompressionRatio(final QCMPFileHeader header, final int written) { @@ -41,7 +56,7 @@ public class ImageCompressor extends CompressorDecompressorBase { } public boolean trainAndSaveCodebook() { - Log("=== Training codebook ==="); + reportStatusToListeners("=== Training codebook ==="); IImageCompressor imageCompressor = getImageCompressor(); if (imageCompressor == null) { return false; diff --git a/src/main/java/azgracompress/compression/ImageDecompressor.java b/src/main/java/azgracompress/compression/ImageDecompressor.java index 9961b31f79b62d05d3479a1da20806ff2339faaf..7062f8d809cca9d3af573f15ce1d7227a5a05703 100644 --- a/src/main/java/azgracompress/compression/ImageDecompressor.java +++ b/src/main/java/azgracompress/compression/ImageDecompressor.java @@ -1,6 +1,8 @@ package azgracompress.compression; import azgracompress.compression.exception.ImageDecompressionException; +import azgracompress.compression.listeners.IProgressListener; +import azgracompress.compression.listeners.IStatusListener; import azgracompress.data.ImageU16Dataset; import azgracompress.fileformat.QCMPFileHeader; import azgracompress.utilities.Stopwatch; @@ -38,17 +40,31 @@ public class ImageDecompressor extends CompressorDecompressorBase { * @return Correct implementation of image decompressor. */ private IImageDecompressor getImageDecompressor(final QCMPFileHeader header) { + IImageDecompressor decompressor = null; switch (header.getQuantizationType()) { case Scalar: - return new SQImageDecompressor(options); + decompressor = new SQImageDecompressor(options); + break; case Vector1D: case Vector2D: - return new VQImageDecompressor(options); + decompressor = new VQImageDecompressor(options); + break; case Vector3D: case Invalid: default: return null; } + + // Forward listeners to image decompressor. + final IStatusListener parentStatusListener = getStatusListener(); + if (parentStatusListener != null) + decompressor.setStatusListener(parentStatusListener); + + final IProgressListener parentProgressListener = getProgressListener(); + if (parentProgressListener != null) + decompressor.setProgressListener(parentProgressListener); + + return decompressor; } /** @@ -203,7 +219,7 @@ public class ImageDecompressor extends CompressorDecompressorBase { final double seconds = decompressionStopwatch.totalElapsedSeconds(); final double MBSize = ((double) decompressedFileSize / 1000.0) / 1000.0; final double MBPerSec = MBSize / seconds; - Log("Decompression speed: %.4f MB/s", MBPerSec); + reportStatusToListeners("Decompression speed: %.4f MB/s", MBPerSec); return true; } @@ -213,7 +229,7 @@ public class ImageDecompressor extends CompressorDecompressorBase { final long dataSize = fileSize - header.getHeaderSize(); final long expectedDataSize = imageDecompressor.getExpectedDataSize(header); if (dataSize != expectedDataSize) { - LogError("Invalid file size."); + reportStatusToListeners("Invalid file size."); return false; } return true; diff --git a/src/main/java/azgracompress/compression/SQImageCompressor.java b/src/main/java/azgracompress/compression/SQImageCompressor.java index 7a3b067ed5ebb7bcf9df5b1391c4f55faddbb81e..2796178b19129c09da551c1f43bc7c3cd094f476 100644 --- a/src/main/java/azgracompress/compression/SQImageCompressor.java +++ b/src/main/java/azgracompress/compression/SQImageCompressor.java @@ -60,7 +60,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm throw new ImageCompressionException("Unable to write codebook to compress stream.", ioEx); } if (options.isVerbose()) { - Log("Wrote quantization values to compressed stream."); + reportStatusToListeners("Wrote quantization values to compressed stream."); } } @@ -106,12 +106,12 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm Huffman huffman = null; final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize()); if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { - Log("Loading codebook from cache file."); + reportStatusToListeners("Loading codebook from cache file."); quantizer = loadQuantizerFromCache(); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies()); - Log("Cached quantizer with huffman coder created."); + reportStatusToListeners("Cached quantizer with huffman coder created."); writeCodebookToOutputStream(quantizer, compressStream); } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { stopwatch.restart(); @@ -124,13 +124,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm throw new ImageCompressionException("Unable to load middle plane data.", ex); } - Log(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex)); + reportStatusToListeners(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex)); quantizer = trainScalarQuantizerFromData(middlePlane.getData()); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies()); stopwatch.stop(); writeCodebookToOutputStream(quantizer, compressStream); - Log("Middle plane codebook with huffman coder created in: " + stopwatch.getElapsedTimeString()); + reportStatusToListeners("Middle plane codebook with huffman coder created in: " + stopwatch.getElapsedTimeString()); } final int[] planeIndices = getPlaneIndicesForCompression(); @@ -138,7 +138,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm int planeCounter = 0; for (final int planeIndex : planeIndices) { stopwatch.restart(); - Log(String.format("Loading plane %d.", planeIndex)); + reportStatusToListeners(String.format("Loading plane %d.", planeIndex)); ImageU16 plane = null; @@ -150,7 +150,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm } if (!hasGeneralQuantizer) { - Log(String.format("Training scalar quantizer from plane %d.", planeIndex)); + reportStatusToListeners(String.format("Training scalar quantizer from plane %d.", planeIndex)); quantizer = trainScalarQuantizerFromData(plane.getData()); writeCodebookToOutputStream(quantizer, compressStream); @@ -161,14 +161,14 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm assert (quantizer != null) : "Scalar Quantizer wasn't initialized."; assert (huffman != null) : "Huffman wasn't initialized."; - Log("Compressing plane..."); + reportStatusToListeners("Compressing plane..."); final int[] indices = quantizer.quantizeIntoIndices(plane.getData(), 1); planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices); stopwatch.stop(); - Log("Plane time: " + stopwatch.getElapsedTimeString()); - Log(String.format("Finished processing of plane %d", planeIndex)); + reportStatusToListeners("Plane time: " + stopwatch.getElapsedTimeString()); + reportStatusToListeners(String.format("Finished processing of plane %d", planeIndex)); } return planeDataSizes; } @@ -185,13 +185,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm if (inputDataInfo.isPlaneIndexSet()) { try { - Log("Loading single plane data."); + reportStatusToListeners("Loading single plane data."); trainData = planeLoader.loadPlaneU16(inputDataInfo.getPlaneIndex()).getData(); } catch (IOException e) { throw new ImageCompressionException("Failed to load plane data.", e); } } else if (inputDataInfo.isPlaneRangeSet()) { - Log("Loading plane range data."); + reportStatusToListeners("Loading plane range data."); final int[] planes = getPlaneIndicesForCompression(); try { trainData = planeLoader.loadPlanesU16Data(planes); @@ -200,7 +200,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm throw new ImageCompressionException("Failed to load plane range data.", e); } } else { - Log("Loading all planes data."); + reportStatusToListeners("Loading all planes data."); try { trainData = planeLoader.loadAllPlanesU16Data(); } catch (IOException e) { @@ -217,18 +217,18 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm LloydMaxU16ScalarQuantization lloydMax = new LloydMaxU16ScalarQuantization(trainData, getCodebookSize(), options.getWorkerCount()); - Log("Starting LloydMax training."); + reportStatusToListeners("Starting LloydMax training."); lloydMax.train(options.isVerbose()); final SQCodebook codebook = lloydMax.getCodebook(); - Log("Finished LloydMax training."); + reportStatusToListeners("Finished LloydMax training."); - Log(String.format("Saving cache file to %s", options.getOutputFilePath())); + reportStatusToListeners(String.format("Saving cache file to %s", options.getOutputFilePath())); QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder()); try { cacheManager.saveCodebook(options.getInputDataInfo().getCacheFileName(), codebook); } catch (IOException e) { throw new ImageCompressionException("Unable to write cache.", e); } - Log("Operation completed."); + reportStatusToListeners("Operation completed."); } } diff --git a/src/main/java/azgracompress/compression/SQImageDecompressor.java b/src/main/java/azgracompress/compression/SQImageDecompressor.java index 6c6ea59eb979234454ade33305ca810036f608b6..fefc9b0b1bc9c77803e59b2b9a31e06011b993c9 100644 --- a/src/main/java/azgracompress/compression/SQImageDecompressor.java +++ b/src/main/java/azgracompress/compression/SQImageDecompressor.java @@ -70,7 +70,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I Huffman huffman = null; if (!header.isCodebookPerPlane()) { // There is only one codebook. - Log("Loading single codebook and huffman coder."); + reportStatusToListeners("Loading single codebook and huffman coder."); codebook = readScalarQuantizationValues(compressedStream, codebookSize); huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); } @@ -79,13 +79,13 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) { stopwatch.restart(); if (header.isCodebookPerPlane()) { - Log("Loading plane codebook..."); + reportStatusToListeners("Loading plane codebook..."); codebook = readScalarQuantizationValues(compressedStream, codebookSize); huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); } assert (codebook != null && huffman != null); - Log(String.format("Decompressing plane %d...", planeIndex)); + reportStatusToListeners(String.format("Decompressing plane %d...", planeIndex)); byte[] decompressedPlaneData = null; final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex]; try (InBitStream inBitStream = new InBitStream(compressedStream, @@ -120,7 +120,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I } stopwatch.stop(); - Log(String.format("Decompressed plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString())); + reportStatusToListeners(String.format("Decompressed plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString())); } } @@ -141,6 +141,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I } for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) { + reportProgressListeners(planeIndex, planeCountForDecompression, "Decompressing plane %d", planeIndex); if (header.isCodebookPerPlane()) { codebook = readScalarQuantizationValues(compressedStream, codebookSize); huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java index d94984ca218d9262c006f50ea468e90f0acbfe0c..0f5d6b79d2b9de0b413858ded2609d05c2e44127 100644 --- a/src/main/java/azgracompress/compression/VQImageCompressor.java +++ b/src/main/java/azgracompress/compression/VQImageCompressor.java @@ -61,7 +61,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm throw new ImageCompressionException("Unable to write codebook to compress stream.", ioEx); } if (options.isVerbose()) { - Log("Wrote quantization vectors to compressed stream."); + reportStatusToListeners("Wrote quantization vectors to compressed stream."); } } @@ -112,10 +112,10 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm Huffman huffman = null; if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { - Log("Loading codebook from cache file."); + reportStatusToListeners("Loading codebook from cache file."); quantizer = loadQuantizerFromCache(); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); - Log("Cached quantizer with huffman coder created."); + reportStatusToListeners("Cached quantizer with huffman coder created."); writeQuantizerToCompressStream(quantizer, compressStream); } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { stopwatch.restart(); @@ -129,13 +129,13 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm throw new ImageCompressionException("Unable to load reference plane data.", ex); } - Log(String.format("Training vector quantizer from middle plane %d.", middlePlaneIndex)); + reportStatusToListeners(String.format("Training vector quantizer from middle plane %d.", middlePlaneIndex)); final int[][] refPlaneVectors = middlePlane.toQuantizationVectors(options.getVectorDimension()); quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); writeQuantizerToCompressStream(quantizer, compressStream); stopwatch.stop(); - Log("Middle plane codebook created in: " + stopwatch.getElapsedTimeString()); + reportStatusToListeners("Middle plane codebook created in: " + stopwatch.getElapsedTimeString()); } final int[] planeIndices = getPlaneIndicesForCompression(); @@ -144,7 +144,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm for (final int planeIndex : planeIndices) { stopwatch.restart(); - Log(String.format("Loading plane %d.", planeIndex)); + reportStatusToListeners(String.format("Loading plane %d.", planeIndex)); ImageU16 plane = null; try { @@ -157,23 +157,23 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm final int[][] planeVectors = plane.toQuantizationVectors(options.getVectorDimension()); if (!hasGeneralQuantizer) { - Log(String.format("Training vector quantizer from plane %d.", planeIndex)); + reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex)); quantizer = trainVectorQuantizerFromPlaneVectors(planeVectors); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); writeQuantizerToCompressStream(quantizer, compressStream); - Log("Wrote plane codebook."); + reportStatusToListeners("Wrote plane codebook."); } assert (quantizer != null); - Log("Compressing plane..."); + reportStatusToListeners("Compressing plane..."); final int[] indices = quantizer.quantizeIntoIndices(planeVectors, options.getWorkerCount()); planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices); stopwatch.stop(); - Log("Plane time: " + stopwatch.getElapsedTimeString()); - Log(String.format("Finished processing of plane %d.", planeIndex)); + reportStatusToListeners("Plane time: " + stopwatch.getElapsedTimeString()); + reportStatusToListeners(String.format("Finished processing of plane %d.", planeIndex)); } return planeDataSizes; } @@ -206,7 +206,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm Stopwatch s = new Stopwatch(); s.start(); if (inputDataInfo.isPlaneIndexSet()) { - Log("VQ: Loading single plane data."); + reportStatusToListeners("VQ: Loading single plane data."); try { trainData = loadPlaneQuantizationVectors(planeLoader, inputDataInfo.getPlaneIndex()); @@ -214,7 +214,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm throw new ImageCompressionException("Failed to load plane data.", e); } } else { - Log(inputDataInfo.isPlaneRangeSet() ? "VQ: Loading plane range data." : "VQ: Loading all planes data."); + reportStatusToListeners(inputDataInfo.isPlaneRangeSet() ? "VQ: Loading plane range data." : "VQ: Loading all planes data."); final int[] planeIndices = getPlaneIndicesForCompression(); final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCountPerPlane( @@ -244,7 +244,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm } } s.stop(); - Log("Quantization vector load took: " + s.getElapsedTimeString()); + reportStatusToListeners("Quantization vector load took: " + s.getElapsedTimeString()); return trainData; } @@ -256,19 +256,19 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm getCodebookSize(), options.getWorkerCount(), options.getVectorDimension().toV3i()); - Log("Starting LBG optimization."); + reportStatusToListeners("Starting LBG optimization."); LBGResult lbgResult = vqInitializer.findOptimalCodebook(options.isVerbose()); - Log("Learned the optimal codebook."); + reportStatusToListeners("Learned the optimal codebook."); - Log("Saving cache file to %s", options.getOutputFilePath()); + reportStatusToListeners("Saving cache file to %s", options.getOutputFilePath()); QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder()); try { cacheManager.saveCodebook(options.getInputDataInfo().getCacheFileName(), lbgResult.getCodebook()); } catch (IOException e) { throw new ImageCompressionException("Unable to write VQ cache.", e); } - Log("Operation completed."); + reportStatusToListeners("Operation completed."); } diff --git a/src/main/java/azgracompress/compression/VQImageDecompressor.java b/src/main/java/azgracompress/compression/VQImageDecompressor.java index 168513c50b2c3e08c7f5ed23344a87c9bdaff2fc..1e1d61e6727b34ceb77ab388fc47276b8c2e44b2 100644 --- a/src/main/java/azgracompress/compression/VQImageDecompressor.java +++ b/src/main/java/azgracompress/compression/VQImageDecompressor.java @@ -117,7 +117,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I Huffman huffman = null; if (!header.isCodebookPerPlane()) { // There is only one codebook. - Log("Loading codebook from cache..."); + reportStatusToListeners("Loading codebook from cache..."); codebook = readCodebook(compressedStream, codebookSize, vectorSize); huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies()); } @@ -126,13 +126,13 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) { stopwatch.restart(); if (header.isCodebookPerPlane()) { - Log("Loading plane codebook..."); + reportStatusToListeners("Loading plane codebook..."); codebook = readCodebook(compressedStream, codebookSize, vectorSize); huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies()); } assert (codebook != null && huffman != null); - Log(String.format("Decompressing plane %d...", planeIndex)); + reportStatusToListeners(String.format("Decompressing plane %d...", planeIndex)); byte[] decompressedPlaneData = null; @@ -176,7 +176,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I } stopwatch.stop(); - Log(String.format("Decompressed plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString())); + reportStatusToListeners(String.format("Decompressed plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString())); } } diff --git a/src/main/java/azgracompress/compression/listeners/IProgressListener.java b/src/main/java/azgracompress/compression/listeners/IProgressListener.java new file mode 100644 index 0000000000000000000000000000000000000000..3c9c68828f96533f777bf0f3dd9332c1c94d0dde --- /dev/null +++ b/src/main/java/azgracompress/compression/listeners/IProgressListener.java @@ -0,0 +1,5 @@ +package azgracompress.compression.listeners; + +public interface IProgressListener { + void sendProgress(final String message, final int index, final int finalIndex); +} diff --git a/src/main/java/azgracompress/compression/listeners/IStatusListener.java b/src/main/java/azgracompress/compression/listeners/IStatusListener.java new file mode 100644 index 0000000000000000000000000000000000000000..bd549e4c5de18abd2d9a262d806460139dcca410 --- /dev/null +++ b/src/main/java/azgracompress/compression/listeners/IStatusListener.java @@ -0,0 +1,5 @@ +package azgracompress.compression.listeners; + +public interface IStatusListener { + void sendMessage(final String message); +}