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

Enable usage of multiple decompressors.

This contains functionality to map mipmap level to codebook size. Also -compress-from options is added to set the minimal mipmap level to compress.

Eg. -comress-from 1, means that level 0 is not compressed and levels > 1 are.
parent 36a1e302
Branches
No related tags found
No related merge requests found
package azgracompress;
public class ViewerCompressionOptions {
private boolean enabled = false;
private int compressFromMipmapLevel = 0;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(final boolean enable) {
this.enabled = enable;
}
public int getCompressFromMipmapLevel() {
return compressFromMipmapLevel;
}
public void setCompressFromMipmapLevel(final int compressFrom) {
this.compressFromMipmapLevel = compressFrom;
}
}
...@@ -29,73 +29,55 @@ ...@@ -29,73 +29,55 @@
*/ */
package bdv; package bdv;
import java.io.File; import azgracompress.ViewerCompressionOptions;
import java.io.FileNotFoundException; import azgracompress.utilities.ColorConsole;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ActionMap;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.filechooser.FileFilter;
import azgracompress.cache.ICacheFile;
import net.imglib2.Volatile;
import net.imglib2.converter.Converter;
import net.imglib2.display.ColorConverter;
import net.imglib2.display.RealARGBColorConverter;
import net.imglib2.display.ScaledARGBConverter;
import net.imglib2.type.numeric.ARGBType;
import net.imglib2.type.numeric.NumericType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.volatiles.VolatileARGBType;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.scijava.ui.behaviour.io.InputTriggerConfig;
import org.scijava.ui.behaviour.io.yaml.YamlConfigIO;
import bdv.cache.CacheControl; import bdv.cache.CacheControl;
import bdv.export.ProgressWriter; import bdv.export.ProgressWriter;
import bdv.export.ProgressWriterConsole; import bdv.export.ProgressWriterConsole;
import bdv.spimdata.SpimDataMinimal; import bdv.spimdata.SpimDataMinimal;
import bdv.spimdata.WrapBasicImgLoader; import bdv.spimdata.WrapBasicImgLoader;
import bdv.spimdata.XmlIoSpimDataMinimal; import bdv.spimdata.XmlIoSpimDataMinimal;
import bdv.tools.HelpDialog; import bdv.tools.*;
import bdv.tools.InitializeViewerState;
import bdv.tools.RecordMaxProjectionDialog;
import bdv.tools.RecordMovieDialog;
import bdv.tools.VisibilityAndGroupingDialog;
import bdv.tools.bookmarks.Bookmarks; import bdv.tools.bookmarks.Bookmarks;
import bdv.tools.bookmarks.BookmarksEditor; import bdv.tools.bookmarks.BookmarksEditor;
import bdv.tools.brightness.BrightnessDialog; import bdv.tools.brightness.*;
import bdv.tools.brightness.ConverterSetup;
import bdv.tools.brightness.MinMaxGroup;
import bdv.tools.brightness.RealARGBColorConverterSetup;
import bdv.tools.brightness.SetupAssignments;
import bdv.tools.crop.CropDialog; import bdv.tools.crop.CropDialog;
import bdv.tools.transformation.ManualTransformation; import bdv.tools.transformation.ManualTransformation;
import bdv.tools.transformation.ManualTransformationEditor; import bdv.tools.transformation.ManualTransformationEditor;
import bdv.tools.transformation.TransformedSource; import bdv.tools.transformation.TransformedSource;
import bdv.viewer.NavigationActions; import bdv.viewer.*;
import bdv.viewer.SourceAndConverter;
import bdv.viewer.ViewerFrame;
import bdv.viewer.ViewerOptions;
import bdv.viewer.ViewerPanel;
import mpicbg.spim.data.SpimDataException; import mpicbg.spim.data.SpimDataException;
import mpicbg.spim.data.generic.AbstractSpimData; import mpicbg.spim.data.generic.AbstractSpimData;
import mpicbg.spim.data.generic.sequence.AbstractSequenceDescription; import mpicbg.spim.data.generic.sequence.AbstractSequenceDescription;
import mpicbg.spim.data.generic.sequence.BasicViewSetup; import mpicbg.spim.data.generic.sequence.BasicViewSetup;
import mpicbg.spim.data.sequence.Angle; import mpicbg.spim.data.sequence.Angle;
import mpicbg.spim.data.sequence.Channel; import mpicbg.spim.data.sequence.Channel;
import net.imglib2.Volatile;
import net.imglib2.converter.Converter;
import net.imglib2.display.ColorConverter;
import net.imglib2.display.RealARGBColorConverter;
import net.imglib2.display.ScaledARGBConverter;
import net.imglib2.type.numeric.ARGBType;
import net.imglib2.type.numeric.NumericType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.volatiles.VolatileARGBType;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.scijava.ui.behaviour.io.InputTriggerConfig;
import org.scijava.ui.behaviour.io.yaml.YamlConfigIO;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class BigDataViewer { public class BigDataViewer {
protected final ViewerFrame viewerFrame; protected final ViewerFrame viewerFrame;
...@@ -465,10 +447,10 @@ public class BigDataViewer { ...@@ -465,10 +447,10 @@ public class BigDataViewer {
final String windowTitle, final String windowTitle,
final ProgressWriter progressWriter, final ProgressWriter progressWriter,
final ViewerOptions options, final ViewerOptions options,
final boolean allowCompression) throws SpimDataException { final ViewerCompressionOptions ops) throws SpimDataException {
final XmlIoSpimDataMinimal xmlIoSpimDataMinimal = new XmlIoSpimDataMinimal(); final XmlIoSpimDataMinimal xmlIoSpimDataMinimal = new XmlIoSpimDataMinimal();
xmlIoSpimDataMinimal.setAllowCompression(allowCompression); xmlIoSpimDataMinimal.setViewerCompressionOptions(ops);
final SpimDataMinimal spimData = xmlIoSpimDataMinimal.load(xmlFilename); final SpimDataMinimal spimData = xmlIoSpimDataMinimal.load(xmlFilename);
final BigDataViewer bdv = open(spimData, windowTitle, progressWriter, options); final BigDataViewer bdv = open(spimData, windowTitle, progressWriter, options);
if (!bdv.tryLoadSettings(xmlFilename)) if (!bdv.tryLoadSettings(xmlFilename))
...@@ -635,19 +617,37 @@ public class BigDataViewer { ...@@ -635,19 +617,37 @@ public class BigDataViewer {
viewer.requestRepaint(); viewer.requestRepaint();
} }
public static void main(final String[] args) {
// Default
String fn = "http://127.0.0.1:8080/drosophila32";
public static void main(final String[] args) {
if (args.length < 1) { if (args.length < 1) {
System.err.println("Provide path."); System.err.println("Provide path.");
return; return;
} }
final String fn = args[0];
final ViewerCompressionOptions ops = new ViewerCompressionOptions();
if (args.length > 1) {
for (int i = 1; i < args.length; i++) {
switch (args[i]) {
case "-qcmp":
ops.setEnabled(true);
break;
case "-compress-from":
if (args.length <= i + 1) {
System.err.println("Missing -compress-from integer parameter.");
return;
}
ops.setCompressFromMipmapLevel(Integer.parseInt(args[++i]));
break;
}
}
}
fn = args[0]; ColorConsole.printf(ColorConsole.Color.Green, "Compression:\t" + (ops.isEnabled() ? "ON" : "OFF"));
final boolean allowCompression = (args.length > 1) && (args[1].equals("-qcmp")); if (ops.isEnabled())
ColorConsole.printf(ColorConsole.Color.Green, "CompressFrom:\t" + ops.getCompressFromMipmapLevel());
try { try {
System.setProperty("apple.laf.useScreenMenuBar", "true"); System.setProperty("apple.laf.useScreenMenuBar", "true");
...@@ -656,7 +656,7 @@ public class BigDataViewer { ...@@ -656,7 +656,7 @@ public class BigDataViewer {
"Server test", "Server test",
new ProgressWriterConsole(), new ProgressWriterConsole(),
ViewerOptions.options(), ViewerOptions.options(),
allowCompression); ops);
} catch (final Exception e) { } catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
package bdv.img.remote; package bdv.img.remote;
import azgracompress.ViewerCompressionOptions;
import azgracompress.cache.ICacheFile; import azgracompress.cache.ICacheFile;
import azgracompress.cache.QuantizationCacheManager; import azgracompress.cache.QuantizationCacheManager;
import azgracompress.compression.ImageDecompressor; import azgracompress.compression.ImageDecompressor;
...@@ -77,7 +78,7 @@ public class RemoteImageLoader implements ViewerImgLoader { ...@@ -77,7 +78,7 @@ public class RemoteImageLoader implements ViewerImgLoader {
/** /**
* Flag whether we allow the server to send us compressed data. * Flag whether we allow the server to send us compressed data.
*/ */
private boolean allowCompression; private ViewerCompressionOptions viewerCompressionOptions;
/** /**
...@@ -124,19 +125,15 @@ public class RemoteImageLoader implements ViewerImgLoader { ...@@ -124,19 +125,15 @@ public class RemoteImageLoader implements ViewerImgLoader {
for (final int setupId : metadata.perSetupMipmapInfo.keySet()) for (final int setupId : metadata.perSetupMipmapInfo.keySet())
setupImgLoaders.put(setupId, new SetupImgLoader(setupId)); setupImgLoaders.put(setupId, new SetupImgLoader(setupId));
if (allowCompression) { if (viewerCompressionOptions.isEnabled()) {
setupCompression(); setupCompression();
} }
} }
} }
} }
public boolean shouldAllowCompression() { public void setViewerCompressionOptions(final ViewerCompressionOptions ops) {
return allowCompression; this.viewerCompressionOptions = ops;
}
public void setAllowCompression(final boolean compressionEnabled) {
this.allowCompression = compressionEnabled;
} }
private void setupCompression() throws IOException { private void setupCompression() throws IOException {
...@@ -166,10 +163,11 @@ public class RemoteImageLoader implements ViewerImgLoader { ...@@ -166,10 +163,11 @@ public class RemoteImageLoader implements ViewerImgLoader {
ColorConsole.fprintf(ColorConsole.Target.stdout, ColorConsole.Color.Yellow, "Received %d cache files.", cacheFiles.size()); ColorConsole.fprintf(ColorConsole.Target.stdout, ColorConsole.Color.Yellow, "Received %d cache files.", cacheFiles.size());
final ICacheFile cachedCodebook = cacheFiles.get(cacheFiles.size() - 1); final ImageDecompressor[] decompressors = new ImageDecompressor[cacheFiles.size()];
// TODO(Moravec): Provide all decompressors. for (int i = 0; i < cacheFiles.size(); i++) {
shortLoader.setDataDecompressor(new ImageDecompressor(cachedCodebook)); decompressors[i] = new ImageDecompressor(cacheFiles.get(i));
System.out.println("\u001b[33mRemoteImageLoader::setupCompression() - instantiated image decompressor in shortLoader.\u001b[0m"); }
shortLoader.setDataDecompressors(decompressors, metadata.maxNumLevels, viewerCompressionOptions.getCompressFromMipmapLevel());
} }
......
...@@ -29,7 +29,9 @@ ...@@ -29,7 +29,9 @@
*/ */
package bdv.img.remote; package bdv.img.remote;
import azgracompress.compression.CompressorDecompressorBase;
import azgracompress.compression.ImageDecompressor; import azgracompress.compression.ImageDecompressor;
import azgracompress.utilities.ColorConsole;
import bdv.img.cache.CacheArrayLoader; import bdv.img.cache.CacheArrayLoader;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray; import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray;
...@@ -38,12 +40,17 @@ import java.io.InputStream; ...@@ -38,12 +40,17 @@ import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<VolatileShortArray> { public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<VolatileShortArray> {
private final RemoteImageLoader imgLoader; private final RemoteImageLoader imgLoader;
private boolean requestCompressedData = false; private boolean requestCompressedData = false;
private ImageDecompressor decompressor; private HashMap<Integer, ImageDecompressor> decompressors;
private ImageDecompressor lowestResDecompressor;
private int compressFromMipmapLevel = 0;
public RemoteVolatileShortArrayLoader(final RemoteImageLoader imgLoader) { public RemoteVolatileShortArrayLoader(final RemoteImageLoader imgLoader) {
...@@ -70,10 +77,9 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile ...@@ -70,10 +77,9 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile
final int setup, final int setup,
final int level, final int level,
final int[] dimensions, final int[] dimensions,
final long[] min) throws InterruptedException { final long[] min) {
if (requestCompressedData && level >= compressFromMipmapLevel) {
if (requestCompressedData) {
return loadArrayFromCompressedDataStream(timepoint, setup, level, dimensions, min); return loadArrayFromCompressedDataStream(timepoint, setup, level, dimensions, min);
} }
...@@ -104,13 +110,13 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile ...@@ -104,13 +110,13 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile
public VolatileShortArray loadArrayFromCompressedDataStream(final int timepoint, public VolatileShortArray loadArrayFromCompressedDataStream(final int timepoint,
final int setup, final int setup,
final int level, final int mipmapLevel,
final int[] dimensions, final int[] dimensions,
final long[] min) { final long[] min) {
short[] data = null; short[] data = null;
try { try {
final URL url = new URL(constructRequestUrl("cell_qcmp", timepoint, setup, level, dimensions, min)); final URL url = new URL(constructRequestUrl("cell_qcmp", timepoint, setup, mipmapLevel, dimensions, min));
final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET"); connection.setRequestMethod("GET");
...@@ -119,7 +125,7 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile ...@@ -119,7 +125,7 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile
final int contentLength = connection.getContentLength(); final int contentLength = connection.getContentLength();
final InputStream urlStream = connection.getInputStream(); final InputStream urlStream = connection.getInputStream();
data = decompressor.decompressStream(urlStream, contentLength); data = getDecompressorForMipmapLevel(mipmapLevel).decompressStream(urlStream, contentLength);
urlStream.close(); urlStream.close();
} catch (final Exception e) { } catch (final Exception e) {
...@@ -134,8 +140,35 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile ...@@ -134,8 +140,35 @@ public class RemoteVolatileShortArrayLoader implements CacheArrayLoader<Volatile
return 2; return 2;
} }
public void setDataDecompressor(final ImageDecompressor imageDecompressor) { private ImageDecompressor getDecompressorForMipmapLevel(final int mipmapLevel) {
this.decompressor = imageDecompressor; assert (decompressors != null && !decompressors.isEmpty());
requestCompressedData = true; if (decompressors.containsKey(mipmapLevel)) {
return decompressors.get(mipmapLevel);
}
return lowestResDecompressor;
}
public void setDataDecompressors(final ImageDecompressor[] imageDecompressors,
final int levelCount,
final int compressFromMipmapLevel) {
Arrays.sort(imageDecompressors, Comparator.comparingInt(CompressorDecompressorBase::getBitsPerCodebookIndex));
final int numberOfDecompressionLevels = Math.min((levelCount - compressFromMipmapLevel), imageDecompressors.length);
decompressors = new HashMap<>(numberOfDecompressionLevels);
for (int mipmapLevel = 0; mipmapLevel < numberOfDecompressionLevels; mipmapLevel++) {
final ImageDecompressor decompressor = imageDecompressors[(imageDecompressors.length - 1) - mipmapLevel];
final int cbSize = (int) Math.pow(2, decompressor.getBitsPerCodebookIndex());
final int actualKey = mipmapLevel + compressFromMipmapLevel;
decompressors.put(actualKey, decompressor);
ColorConsole.fprintf(ColorConsole.Target.stdout, ColorConsole.Color.Yellow,
"Created decompressor for mipmap level %d with codebook of size %d.",
actualKey, cbSize);
lowestResDecompressor = decompressor;
}
this.compressFromMipmapLevel = compressFromMipmapLevel;
requestCompressedData = !decompressors.isEmpty();
} }
} }
...@@ -29,11 +29,9 @@ ...@@ -29,11 +29,9 @@
*/ */
package bdv.spimdata; package bdv.spimdata;
import static mpicbg.spim.data.XmlKeys.SPIMDATA_TAG; import azgracompress.ViewerCompressionOptions;
import java.io.File;
import bdv.img.remote.RemoteImageLoader; import bdv.img.remote.RemoteImageLoader;
import bdv.spimdata.legacy.XmlIoSpimDataMinimalLegacy;
import mpicbg.spim.data.SpimDataException; import mpicbg.spim.data.SpimDataException;
import mpicbg.spim.data.SpimDataIOException; import mpicbg.spim.data.SpimDataIOException;
import mpicbg.spim.data.generic.XmlIoAbstractSpimData; import mpicbg.spim.data.generic.XmlIoAbstractSpimData;
...@@ -43,58 +41,53 @@ import mpicbg.spim.data.generic.sequence.XmlIoBasicViewSetups; ...@@ -43,58 +41,53 @@ import mpicbg.spim.data.generic.sequence.XmlIoBasicViewSetups;
import mpicbg.spim.data.registration.XmlIoViewRegistrations; import mpicbg.spim.data.registration.XmlIoViewRegistrations;
import mpicbg.spim.data.sequence.XmlIoMissingViews; import mpicbg.spim.data.sequence.XmlIoMissingViews;
import mpicbg.spim.data.sequence.XmlIoTimePoints; import mpicbg.spim.data.sequence.XmlIoTimePoints;
import org.jdom2.Document; import org.jdom2.Document;
import org.jdom2.Element; import org.jdom2.Element;
import org.jdom2.input.SAXBuilder; import org.jdom2.input.SAXBuilder;
import bdv.spimdata.legacy.XmlIoSpimDataMinimalLegacy; import java.io.File;
import static mpicbg.spim.data.XmlKeys.SPIMDATA_TAG;
public class XmlIoSpimDataMinimal extends XmlIoAbstractSpimData< SequenceDescriptionMinimal, SpimDataMinimal > public class XmlIoSpimDataMinimal extends XmlIoAbstractSpimData<SequenceDescriptionMinimal, SpimDataMinimal> {
{ private ViewerCompressionOptions compressionOptions;
private boolean allowCompression = false;
public XmlIoSpimDataMinimal() public XmlIoSpimDataMinimal() {
{ super(SpimDataMinimal.class,
super( SpimDataMinimal.class, new XmlIoAbstractSequenceDescription<>(
new XmlIoAbstractSequenceDescription<>( SequenceDescriptionMinimal.class,
SequenceDescriptionMinimal.class, new XmlIoTimePoints(),
new XmlIoTimePoints(), new XmlIoBasicViewSetups<>(BasicViewSetup.class),
new XmlIoBasicViewSetups<>( BasicViewSetup.class ), new XmlIoMissingViews()),
new XmlIoMissingViews() ), new XmlIoViewRegistrations());
new XmlIoViewRegistrations() ); }
}
public void setAllowCompression(final boolean allowCompression) { public void setViewerCompressionOptions(final ViewerCompressionOptions ops) {
this.allowCompression = allowCompression; this.compressionOptions = ops;
} }
@Override @Override
public SpimDataMinimal load( final String xmlFilename ) throws SpimDataException public SpimDataMinimal load(final String xmlFilename) throws SpimDataException {
{ final SAXBuilder sax = new SAXBuilder();
final SAXBuilder sax = new SAXBuilder(); final Document doc;
Document doc; try {
try doc = sax.build(xmlFilename);
{ } catch (final Exception e) {
doc = sax.build( xmlFilename ); throw new SpimDataIOException(e);
} }
catch ( final Exception e ) final Element root = doc.getRootElement();
{
throw new SpimDataIOException( e );
}
final Element root = doc.getRootElement();
if ( root.getName().equals( "SequenceDescription" ) ) if (root.getName().equals("SequenceDescription"))
return XmlIoSpimDataMinimalLegacy.fromXml( root, new File( xmlFilename ) ); return XmlIoSpimDataMinimalLegacy.fromXml(root, new File(xmlFilename));
if ( root.getName() != SPIMDATA_TAG ) if (root.getName() != SPIMDATA_TAG)
throw new RuntimeException( "expected <" + SPIMDATA_TAG + "> root element. wrong file?" ); throw new RuntimeException("expected <" + SPIMDATA_TAG + "> root element. wrong file?");
SpimDataMinimal spimDataMinimal = fromXml(root, new File(xmlFilename)); final SpimDataMinimal spimDataMinimal = fromXml(root, new File(xmlFilename));
if (spimDataMinimal.getSequenceDescription().getImgLoader() instanceof RemoteImageLoader) { if (spimDataMinimal.getSequenceDescription().getImgLoader() instanceof RemoteImageLoader) {
final RemoteImageLoader remoteImageLoader = (RemoteImageLoader) spimDataMinimal.getSequenceDescription().getImgLoader(); final RemoteImageLoader remoteImageLoader = (RemoteImageLoader) spimDataMinimal.getSequenceDescription().getImgLoader();
remoteImageLoader.setAllowCompression(allowCompression); remoteImageLoader.setViewerCompressionOptions(compressionOptions);
} }
return spimDataMinimal; return spimDataMinimal;
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment