From 6cb7188e7aabca592d3692384106d9477aed2c6d Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 2 Feb 2023 17:55:52 -0600 Subject: [PATCH 1/4] Add getter and setter for each command line option --- .../pyramid/PyramidFromDirectoryWriter.java | 218 ++++++++++++++++-- .../raw2ometiff/test/ConversionTest.java | 19 ++ 2 files changed, 216 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java index 4df255a..fe2e9dc 100755 --- a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java +++ b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java @@ -115,93 +115,262 @@ public class PyramidFromDirectoryWriter implements Callable { private BlockingQueue tileQueue; private ExecutorService executor; - /** Where to write? */ + Path outputFilePath; + Path inputDirectory; + private volatile String logLevel = "WARN"; + private volatile boolean progressBars = false; + boolean printVersion = false; + String compression = "LZW"; + Double compressionQuality; + boolean legacy = false; + int maxWorkers = Runtime.getRuntime().availableProcessors(); + boolean rgb = false; + + private List series = new ArrayList(); + + private ZarrGroup reader = null; + + /** Writer metadata. */ + OMEPyramidStore metadata; + + private Map plateData = null; + + /** + * Construct a writer for performing the pyramid conversion. + */ + public PyramidFromDirectoryWriter() { + tileQueue = new LimitedQueue(maxWorkers); + } + + /** + * Where to write? + * + * @param output path to output TIFF + */ @Parameters( index = "1", arity = "1", description = "Relative path to the output OME-TIFF file" ) - Path outputFilePath; + public void setOutputPath(Path output) { + outputFilePath = output; + } - /** Where to read? */ + /** + * Where to read? + * + * @param input path to input Zarr directory + */ @Parameters( index = "0", arity = "1", description = "Directory containing pixel data to convert" ) - Path inputDirectory; + public void setInputPath(Path input) { + inputDirectory = input; + } + /** + * Set the slf4j logging level. Defaults to "WARN". + * + * @param level logging level + */ @Option( names = {"--log-level", "--debug"}, arity = "0..1", description = "Change logging level; valid values are " + "OFF, ERROR, WARN, INFO, DEBUG, TRACE and ALL. " + "(default: ${DEFAULT-VALUE})", + defaultValue = "WARN", fallbackValue = "DEBUG" ) - private volatile String logLevel = "WARN"; + public void setLogLevel(String level) { + logLevel = level; + } + /** + * Configure whether or not progress bars are shown during conversion. + * Progress bars are turned off by default. + * + * @param useProgressBars whether or not to show progress bars + */ @Option( names = {"-p", "--progress"}, description = "Print progress bars during conversion", help = true ) - private volatile boolean progressBars = false; + public void setProgressBars(boolean useProgressBars) { + progressBars = useProgressBars; + } + /** + * Configure whether to print version information and exit + * without converting. + * + * @param versionOnly whether or not to print version information and exit + */ @Option( names = "--version", description = "Print version information and exit", help = true ) - boolean printVersion = false; + public void setPrintVersionOnly(boolean versionOnly) { + printVersion = versionOnly; + } + /** + * Set the compression type for the output OME-TIFF. Defaults to LZW. + * Valid types are defined in the CompressionTypes class. + * + * @param compressionType compression type + */ @Option( names = "--compression", completionCandidates = CompressionTypes.class, description = "Compression type for output OME-TIFF file " + - "(${COMPLETION-CANDIDATES}; default: ${DEFAULT-VALUE})" + "(${COMPLETION-CANDIDATES}; default: ${DEFAULT-VALUE})", + defaultValue = "LZW" ) - String compression = "LZW"; + public void setCompression(String compressionType) { + compression = compressionType; + } + /** + * Set the compression quality. The interpretation of the quality value + * depends upon the selected compression type. + * + * This value currently only applies to "JPEG-2000 Lossy" compression, + * and corresponds to the encoded bitrate in bits per pixel. + * The quality is a floating point number and must be greater than 0. + * A larger number implies less data loss but also larger file size. + * By default, the quality is set to the largest positive finite double value. + * This is equivalent to lossless compression; to see truly lossy compression, + * the quality should be set to less than the bit depth of the input image. + * + * @param quality compression quality + */ @Option( names = "--quality", description = "Compression quality" ) - Double compressionQuality; + public void setCompressionQuality(Double quality) { + compressionQuality = quality; + } + /** + * Configure whether to write a pyramid OME-TIFF compatible with + * Bio-Formats 6.x (the default), or a legacy pyramid TIFF compatible + * with Bio-Formats 5.9.x. + * + * @param legacyTIFF true if a legacy pyramid TIFF should be written + */ @Option( names = "--legacy", description = "Write a Bio-Formats 5.9.x pyramid instead of OME-TIFF" ) - boolean legacy = false; + public void setLegacyTIFF(boolean legacyTIFF) { + legacy = legacyTIFF; + } + /** + * Set the maximum number of workers to use for converting tiles. + * Defaults to the number of detected CPUs. + * + * @param workers maximum worker count + */ @Option( names = "--max_workers", description = "Maximum number of workers (default: ${DEFAULT-VALUE})" ) - int maxWorkers = Runtime.getRuntime().availableProcessors(); + public void setMaxWorkers(int workers) { + maxWorkers = workers; + } + /** + * Write an RGB TIFF, if the input data contains a multiple of 3 channels + * If RGB TIFFs are written, any channel metadata (names, wavelengths, etc.) + * in the input data will be lost. + * + * @param isRGB true if an RGB TIFF should be written + */ @Option( names = "--rgb", description = "Attempt to write channels as RGB; " + "channel count must be a multiple of 3" ) - boolean rgb = false; + public void setRGB(boolean isRGB) { + rgb = isRGB; + } - private List series = new ArrayList(); + /** + * @return path to output data + */ + public Path getOutputPath() { + return outputFilePath; + } - private ZarrGroup reader = null; + /** + * @return path to input data + */ + public Path getInputPath() { + return inputDirectory; + } - /** Writer metadata. */ - OMEPyramidStore metadata; + /** + * @return slf4j logging level + */ + public String getLogLevel() { + return logLevel; + } - private Map plateData = null; + /** + * @return true if progress bars are displayed + */ + public boolean getProgressBars() { + return progressBars; + } /** - * Construct a writer for performing the pyramid conversion. + * @return true if only version info is displayed */ - public PyramidFromDirectoryWriter() { - tileQueue = new LimitedQueue(maxWorkers); + public boolean getPrintVersionOnly() { + return printVersion; + } + + /** + * @return compression type + */ + public String getCompression() { + return compression; + } + + /** + * @return compression quality + */ + public Double getCompressionQuality() { + return compressionQuality; + } + + /** + * @return true if a legacy pyramid TIFF will be written + * instead of pyramid OME-TIFF + */ + public boolean getLegacyTIFF() { + return legacy; + } + + /** + * @return maximum number of worker threads + */ + public int getMaxWorkers() { + return maxWorkers; + } + + /** + * @return true if an RGB TIFF should be written + */ + public boolean getRGB() { + return rgb; } /** @@ -219,6 +388,13 @@ public Void call() throws Exception { return null; } + if (inputDirectory == null) { + throw new IllegalArgumentException("Input directory not specified"); + } + if (outputFilePath == null) { + throw new IllegalArgumentException("Output path not specified"); + } + // Resolve symlinks inputDirectory = inputDirectory.toRealPath(); diff --git a/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java b/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java index 3c31c29..a2e175a 100644 --- a/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java +++ b/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java @@ -497,6 +497,25 @@ public void testSingleImageNoHCS() throws Exception { } } + /** + * Test RGB with multiple channels using API instead of command line. + */ + @Test + public void testOptionsAPI() throws Exception { + input = fake("sizeC", "12", "rgb", "3"); + assertBioFormats2Raw(); + + outputOmeTiff = output.resolve("output.ome.tiff"); + PyramidFromDirectoryWriter apiConverter = new PyramidFromDirectoryWriter(); + apiConverter.setInputPath(output); + apiConverter.setOutputPath(outputOmeTiff); + apiConverter.setCompression("raw"); + apiConverter.setRGB(true); + apiConverter.call(); + + iteratePixels(); + } + /** * Test "--version" with no other arguments. * Does not test the version values, just makes sure that an exception From 399f418a932bc48e68d1a9caeaf8c6598062df0b Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Tue, 14 Mar 2023 19:05:31 -0500 Subject: [PATCH 2/4] Use String for input/output path API --- .../pyramid/PyramidFromDirectoryWriter.java | 19 +++++++++++-------- .../raw2ometiff/test/ConversionTest.java | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java index fe2e9dc..520e567 100755 --- a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java +++ b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java @@ -11,6 +11,7 @@ import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -152,8 +153,9 @@ public PyramidFromDirectoryWriter() { arity = "1", description = "Relative path to the output OME-TIFF file" ) - public void setOutputPath(Path output) { - outputFilePath = output; + public void setOutputPath(String output) { + // could be expanded to allow other output locations + outputFilePath = Paths.get(output); } /** @@ -166,8 +168,9 @@ public void setOutputPath(Path output) { arity = "1", description = "Directory containing pixel data to convert" ) - public void setInputPath(Path input) { - inputDirectory = input; + public void setInputPath(String input) { + // could be expanded to allow other input locations + inputDirectory = Paths.get(input); } /** @@ -305,15 +308,15 @@ public void setRGB(boolean isRGB) { /** * @return path to output data */ - public Path getOutputPath() { - return outputFilePath; + public String getOutputPath() { + return outputFilePath.toString(); } /** * @return path to input data */ - public Path getInputPath() { - return inputDirectory; + public String getInputPath() { + return inputDirectory.toString(); } /** diff --git a/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java b/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java index a2e175a..f028eac 100644 --- a/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java +++ b/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java @@ -507,8 +507,8 @@ public void testOptionsAPI() throws Exception { outputOmeTiff = output.resolve("output.ome.tiff"); PyramidFromDirectoryWriter apiConverter = new PyramidFromDirectoryWriter(); - apiConverter.setInputPath(output); - apiConverter.setOutputPath(outputOmeTiff); + apiConverter.setInputPath(output.toString()); + apiConverter.setOutputPath(outputOmeTiff.toString()); apiConverter.setCompression("raw"); apiConverter.setRGB(true); apiConverter.call(); From 0344585668c712b190ba1ed93ff5f76a41387841 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Mon, 27 Mar 2023 15:01:22 -0500 Subject: [PATCH 3/4] Update compression API to be a little more flexible The compression type now uses the new CompressionType enum, and compression options can be set with a CodecOptions object (that includes quality). The command line "--quality" will be wrapped in a CodecOptions behind the scenes, but this does not add any other command line arguments for setting compression options. --- .../pyramid/CompressionQualityConverter.java | 31 ++++++++ .../pyramid/CompressionType.java | 70 +++++++++++++++++++ .../pyramid/CompressionTypeConverter.java | 23 ++++++ .../pyramid/CompressionTypes.java | 62 ---------------- .../pyramid/PyramidFromDirectoryWriter.java | 47 +++++++------ .../raw2ometiff/test/ConversionTest.java | 20 +++++- 6 files changed, 169 insertions(+), 84 deletions(-) create mode 100644 src/main/java/com/glencoesoftware/pyramid/CompressionQualityConverter.java create mode 100644 src/main/java/com/glencoesoftware/pyramid/CompressionType.java create mode 100644 src/main/java/com/glencoesoftware/pyramid/CompressionTypeConverter.java delete mode 100644 src/main/java/com/glencoesoftware/pyramid/CompressionTypes.java diff --git a/src/main/java/com/glencoesoftware/pyramid/CompressionQualityConverter.java b/src/main/java/com/glencoesoftware/pyramid/CompressionQualityConverter.java new file mode 100644 index 0000000..5e56517 --- /dev/null +++ b/src/main/java/com/glencoesoftware/pyramid/CompressionQualityConverter.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2023 Glencoe Software, Inc. All rights reserved. + * + * This software is distributed under the terms described by the LICENSE.txt + * file you can find at the root of the distribution bundle. If the file is + * missing please request a copy by contacting info@glencoesoftware.com + */ + +package com.glencoesoftware.pyramid; + +import loci.formats.codec.CodecOptions; +import loci.formats.codec.JPEG2000CodecOptions; + +import picocli.CommandLine.ITypeConverter; + +/** + * Convert a string to a CodecOptions. + */ +public class CompressionQualityConverter + implements ITypeConverter +{ + @Override + public CodecOptions convert(String value) throws Exception { + // JPEG2000CodecOptions used here as it's the only way to pass + // a quality value through to the JPEG-2000 codecs + // this could be changed later if/when we support options on other codecs + CodecOptions options = JPEG2000CodecOptions.getDefaultOptions(); + options.quality = Double.parseDouble(value); + return options; + } +} diff --git a/src/main/java/com/glencoesoftware/pyramid/CompressionType.java b/src/main/java/com/glencoesoftware/pyramid/CompressionType.java new file mode 100644 index 0000000..e30db20 --- /dev/null +++ b/src/main/java/com/glencoesoftware/pyramid/CompressionType.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2019-2020 Glencoe Software, Inc. All rights reserved. + * + * This software is distributed under the terms described by the LICENSE.txt + * file you can find at the root of the distribution bundle. If the file is + * missing please request a copy by contacting info@glencoesoftware.com + */ +package com.glencoesoftware.pyramid; + +import java.util.EnumSet; +import loci.formats.out.TiffWriter; +import loci.formats.tiff.TiffCompression; + +/** + * List of valid compression types for the output OME-TIFF file. + */ +public enum CompressionType { + UNCOMPRESSED( + TiffWriter.COMPRESSION_UNCOMPRESSED, TiffCompression.UNCOMPRESSED), + LZW(TiffWriter.COMPRESSION_LZW, TiffCompression.LZW), + JPEG(TiffWriter.COMPRESSION_JPEG, TiffCompression.JPEG), + JPEG_2000(TiffWriter.COMPRESSION_J2K, TiffCompression.JPEG_2000), + JPEG_2000_LOSSY( + TiffWriter.COMPRESSION_J2K_LOSSY, TiffCompression.JPEG_2000_LOSSY); + + private String compressionName; + private TiffCompression compressionType; + + /** + * Construct a list of valid compression types. + * + * @param name compression name (used in command line arguments) + * @param type corresponding TIFF compression + */ + private CompressionType(String name, TiffCompression type) { + compressionName = name; + compressionType = type; + } + + /** + * Find the compression corresponding to the given name. + * If there is no matching name, return the uncompressed type. + * + * @param compressionName desired compression name + * @return corresponding CompressionType, or UNCOMPRESSED if no match + */ + public static CompressionType lookup(String compressionName) { + for (CompressionType t : EnumSet.allOf(CompressionType.class)) { + if (t.getName().equals(compressionName)) { + return t; + } + } + return UNCOMPRESSED; + } + + /** + * @return name of this compression type + */ + public String getName() { + return compressionName; + } + + /** + * @return TiffCompression for this compression type + */ + public TiffCompression getTIFFCompression() { + return compressionType; + } + +} diff --git a/src/main/java/com/glencoesoftware/pyramid/CompressionTypeConverter.java b/src/main/java/com/glencoesoftware/pyramid/CompressionTypeConverter.java new file mode 100644 index 0000000..7cea87a --- /dev/null +++ b/src/main/java/com/glencoesoftware/pyramid/CompressionTypeConverter.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2023 Glencoe Software, Inc. All rights reserved. + * + * This software is distributed under the terms described by the LICENSE.txt + * file you can find at the root of the distribution bundle. If the file is + * missing please request a copy by contacting info@glencoesoftware.com + */ + +package com.glencoesoftware.pyramid; + +import picocli.CommandLine.ITypeConverter; + +/** + * Convert a string to a CompressionType. + */ +public class CompressionTypeConverter + implements ITypeConverter +{ + @Override + public CompressionType convert(String value) throws Exception { + return CompressionType.lookup(value); + } +} diff --git a/src/main/java/com/glencoesoftware/pyramid/CompressionTypes.java b/src/main/java/com/glencoesoftware/pyramid/CompressionTypes.java deleted file mode 100644 index 7c0d470..0000000 --- a/src/main/java/com/glencoesoftware/pyramid/CompressionTypes.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2019-2020 Glencoe Software, Inc. All rights reserved. - * - * This software is distributed under the terms described by the LICENSE.txt - * file you can find at the root of the distribution bundle. If the file is - * missing please request a copy by contacting info@glencoesoftware.com - */ -package com.glencoesoftware.pyramid; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import loci.formats.out.TiffWriter; -import loci.formats.tiff.TiffCompression; - -/** - * List of valid compression types for the output OME-TIFF file. - */ -public class CompressionTypes extends ArrayList { - - /** - * Construct a list of valid compression types. - */ - public CompressionTypes() { - super(CompressionTypes.getCompressionTypes()); - } - - private static List getCompressionTypes() { - try (TiffWriter v = new TiffWriter()) { - return Arrays.asList(v.getCompressionTypes()); - } - catch (Exception e) { - return new ArrayList(); - } - } - - /** - * Convert the compression argument to a TiffCompression object that can - * be used to compress tiles. - * - * @param compression type - * @return TiffCompression corresponding to the compression argument, - */ - public static TiffCompression getTIFFCompression(String compression) { - if (compression.equals(TiffWriter.COMPRESSION_LZW)) { - return TiffCompression.LZW; - } - else if (compression.equals(TiffWriter.COMPRESSION_J2K)) { - return TiffCompression.JPEG_2000; - } - else if (compression.equals(TiffWriter.COMPRESSION_J2K_LOSSY)) { - return TiffCompression.JPEG_2000_LOSSY; - } - else if (compression.equals(TiffWriter.COMPRESSION_JPEG)) { - return TiffCompression.JPEG; - } - else if (compression.equals(TiffWriter.COMPRESSION_ZLIB)) { - return TiffCompression.DEFLATE; - } - return TiffCompression.UNCOMPRESSED; - } -} diff --git a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java index 520e567..76df029 100755 --- a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java +++ b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java @@ -121,8 +121,8 @@ public class PyramidFromDirectoryWriter implements Callable { private volatile String logLevel = "WARN"; private volatile boolean progressBars = false; boolean printVersion = false; - String compression = "LZW"; - Double compressionQuality; + CompressionType compression = CompressionType.LZW; + CodecOptions compressionOptions; boolean legacy = false; int maxWorkers = Runtime.getRuntime().availableProcessors(); boolean rgb = false; @@ -223,23 +223,26 @@ public void setPrintVersionOnly(boolean versionOnly) { /** * Set the compression type for the output OME-TIFF. Defaults to LZW. - * Valid types are defined in the CompressionTypes class. + * Valid types are defined in the CompressionType enum. * * @param compressionType compression type */ @Option( names = "--compression", - completionCandidates = CompressionTypes.class, description = "Compression type for output OME-TIFF file " + "(${COMPLETION-CANDIDATES}; default: ${DEFAULT-VALUE})", + converter = CompressionTypeConverter.class, defaultValue = "LZW" ) - public void setCompression(String compressionType) { + public void setCompression(CompressionType compressionType) { compression = compressionType; } /** - * Set the compression quality. The interpretation of the quality value + * Set the compression options. + * + * When using the command line "--quality" option, the quality value will be + * wrapped in a CodecOptions. The interpretation of the quality value * depends upon the selected compression type. * * This value currently only applies to "JPEG-2000 Lossy" compression, @@ -250,14 +253,20 @@ public void setCompression(String compressionType) { * This is equivalent to lossless compression; to see truly lossy compression, * the quality should be set to less than the bit depth of the input image. * - * @param quality compression quality + * Options other than quality may be specified in this object, but their + * interpretation will also depend upon the compression type selected. + * Options that conflict with the input data (e.g. bits per pixel) + * will be ignored. + * + * @param options compression options */ @Option( names = "--quality", + converter = CompressionQualityConverter.class, description = "Compression quality" ) - public void setCompressionQuality(Double quality) { - compressionQuality = quality; + public void setCompressionOptions(CodecOptions options) { + compressionOptions = options; } /** @@ -343,15 +352,15 @@ public boolean getPrintVersionOnly() { /** * @return compression type */ - public String getCompression() { + public CompressionType getCompression() { return compression; } /** - * @return compression quality + * @return compression options */ - public Double getCompressionQuality() { - return compressionQuality; + public CodecOptions getCompressionOptions() { + return compressionOptions; } /** @@ -1204,8 +1213,7 @@ private IFD makeIFD(PyramidSeries s, int resolution, int plane) ifd.put(IFD.IMAGE_LENGTH, (long) descriptor.sizeY); ifd.put(IFD.TILE_WIDTH, descriptor.tileSizeX); ifd.put(IFD.TILE_LENGTH, descriptor.tileSizeY); - ifd.put(IFD.COMPRESSION, - CompressionTypes.getTIFFCompression(compression).getCode()); + ifd.put(IFD.COMPRESSION, compression.getTIFFCompression().getCode()); ifd.put(IFD.PLANAR_CONFIGURATION, s.rgb ? 2 : 1); @@ -1296,9 +1304,9 @@ private void writeTile(PyramidSeries s, s.index, imageNumber, tileIndex); IFD ifd = s.ifds[resolution].get(imageNumber); - TiffCompression tiffCompression = - CompressionTypes.getTIFFCompression(compression); - CodecOptions options = tiffCompression.getCompressionCodecOptions(ifd); + TiffCompression tiffCompression = compression.getTIFFCompression(); + CodecOptions options = + tiffCompression.getCompressionCodecOptions(ifd, compressionOptions); // buffer has been padded to full tile width before calling writeTile // but is not necessarily full tile height (if in the bottom row) @@ -1307,9 +1315,6 @@ private void writeTile(PyramidSeries s, options.height = buffer.length / (options.width * bpp); options.bitsPerSample = bpp * 8; options.channels = 1; - if (compressionQuality != null) { - options.quality = compressionQuality; - } byte[] realTile = tiffCompression.compress(buffer, options); LOG.debug(" writing {} compressed bytes at {}", diff --git a/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java b/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java index f028eac..90413b3 100644 --- a/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java +++ b/src/test/java/com/glencoesoftware/raw2ometiff/test/ConversionTest.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.glencoesoftware.bioformats2raw.Converter; +import com.glencoesoftware.pyramid.CompressionType; import com.glencoesoftware.pyramid.PyramidFromDirectoryWriter; import loci.common.DataTools; @@ -509,13 +510,30 @@ public void testOptionsAPI() throws Exception { PyramidFromDirectoryWriter apiConverter = new PyramidFromDirectoryWriter(); apiConverter.setInputPath(output.toString()); apiConverter.setOutputPath(outputOmeTiff.toString()); - apiConverter.setCompression("raw"); + apiConverter.setCompression(CompressionType.UNCOMPRESSED); apiConverter.setRGB(true); apiConverter.call(); iteratePixels(); } + /** + * Test "--quality" command line option. + */ + @Test + public void testCompressionQuality() throws Exception { + input = fake("sizeC", "3", "rgb", "3"); + assertBioFormats2Raw(); + assertTool("--compression", "JPEG-2000", "--quality", "0.25", "--rgb"); + + try (ImageReader reader = new ImageReader()) { + reader.setFlattenedResolutions(false); + reader.setId(outputOmeTiff.toString()); + Assert.assertEquals(1, reader.getSeriesCount()); + Assert.assertEquals(3, reader.getRGBChannelCount()); + } + } + /** * Test "--version" with no other arguments. * Does not test the version values, just makes sure that an exception From dda535a8a5e3c94326726902ce9976507f101319 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 29 Mar 2023 09:54:30 -0500 Subject: [PATCH 4/4] Make sure worker count is positive --- .../glencoesoftware/pyramid/PyramidFromDirectoryWriter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java index 76df029..3025986 100755 --- a/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java +++ b/src/main/java/com/glencoesoftware/pyramid/PyramidFromDirectoryWriter.java @@ -295,7 +295,9 @@ public void setLegacyTIFF(boolean legacyTIFF) { description = "Maximum number of workers (default: ${DEFAULT-VALUE})" ) public void setMaxWorkers(int workers) { - maxWorkers = workers; + if (workers > 0) { + maxWorkers = workers; + } } /**