/*
* Copyright (C) 2015 Patryk Strach
*
* This file is part of Virtual Slide Viewer.
*
* Virtual Slide Viewer is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* Virtual Slide Viewer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Virtual Slide Viewer.
* If not, see <http://www.gnu.org/licenses/>.
*/
package virtualslideviewer.bioformats;
import java.awt.Dimension;
import java.io.IOException;
import java.nio.channels.ClosedByInterruptException;
import java.nio.file.Path;
import loci.formats.*;
import loci.formats.meta.IMetadata;
import virtualslideviewer.UncheckedInterruptedException;
import virtualslideviewer.core.VirtualSlide;
import virtualslideviewer.core.persistence.VirtualSlideLoadException;
import virtualslideviewer.core.persistence.VirtualSlideLoader;
import virtualslideviewer.util.ParameterValidator;
public class BioformatsLoader implements VirtualSlideLoader
{
private final PaddingCalculator mPaddingCalculator;
public BioformatsLoader(PaddingCalculator paddingCalculator)
{
ParameterValidator.throwIfNull(paddingCalculator, "paddingCalculator");
mPaddingCalculator = paddingCalculator;
}
@Override
public boolean canLoad(Path filePath)
{
try(IFormatReader reader = new ImageReader())
{
return reader.isThisType(filePath.toString());
}
catch(IOException e)
{
return false;
}
}
/**
* @param filePath Path of the file to open.
*
* @throws VirtualSlideLoadException When virtual slide could not be loaded because file does not exist or is in unsupported format.
*/
@Override
public VirtualSlide load(Path filePath) throws VirtualSlideLoadException, UncheckedInterruptedException
{
ParameterValidator.throwIfNull(filePath, "filePath");
IMetadata metadata = MetadataTools.createOMEXMLMetadata();
ReaderPool readerPool = new ReaderPool(() -> initReader(filePath, metadata));
try
{
BioformatsVirtualSlide newSlide = new BioformatsVirtualSlide(metadata, getFileFormat(readerPool));
loadImages(newSlide, readerPool);
return newSlide;
}
catch(Exception e)
{
readerPool.close();
throw e;
}
}
private String getFileFormat(ReaderPool readerPool)
{
String fileFormat;
IFormatReader reader = readerPool.borrow();
{
fileFormat = reader.getFormat();
}
readerPool.putBack(reader);
return fileFormat;
}
/**
* Adds all images found in a virtual slide file to a list of images.
*/
protected void loadImages(BioformatsVirtualSlide slide, ReaderPool readerPool) throws UncheckedInterruptedException
{
IFormatReader reader = readerPool.borrow();
try
{
for(int seriesIndex = 0; seriesIndex < reader.getSeriesCount(); seriesIndex++)
{
reader.setSeries(seriesIndex);
String imageName = slide.getBioformatsMetadata().getImageName(seriesIndex);
int resCount = reader.getResolutionCount();
BioformatsVirtualSlideImage image = new BioformatsVirtualSlideImage(imageName, seriesIndex, resCount, readerPool);
computePaddingForEveryResolutionOfImage(image);
slide.addImage(seriesIndex, image);
}
}
finally
{
readerPool.putBack(reader);
}
}
protected void computePaddingForEveryResolutionOfImage(BioformatsVirtualSlideImage image) throws UncheckedInterruptedException
{
for(int i = 0; i < image.getResolutionCount(); i++)
{
Dimension padding = mPaddingCalculator.computePadding(image, i);
image.setPadding(i, padding);
}
}
/**
* Inits the reader which will be used to load the data of the virtual slide.
*/
private IFormatReader initReader(Path filePath, IMetadata metadataStore)
{
try
{
IFormatReader newReader = new ChannelFiller(new ImageReader());
newReader.setMetadataStore(metadataStore);
newReader.setFlattenedResolutions(false);
newReader.setId(filePath.toString());
return newReader;
}
catch(ClosedByInterruptException e)
{
// Cannot throw checked exception from a lambda...
throw new UncheckedInterruptedException(e.getMessage());
}
catch(FormatException | IOException e)
{
// Had to create new (unchecked) exception type because checked exception cannot be thrown from lamdba in which it is called...
throw new VirtualSlideLoadException(e.getMessage(), e);
}
}
}