diff --git a/components/formats-api/src/loci/formats/readers.txt b/components/formats-api/src/loci/formats/readers.txt index 5bb9e41890c..e7b90347031 100644 --- a/components/formats-api/src/loci/formats/readers.txt +++ b/components/formats-api/src/loci/formats/readers.txt @@ -146,8 +146,8 @@ loci.formats.in.NDPIReader # ndpi loci.formats.in.PCORAWReader # pcoraw # TIFF-based readers with slow isThisType -loci.formats.in.OMETiffReader # tif loci.formats.in.PyramidTiffReader # tif, tiff +loci.formats.in.OMETiffReader # tif loci.formats.in.MIASReader # tif loci.formats.in.TCSReader # xml, tif loci.formats.in.LeicaReader # lei, tif diff --git a/components/formats-gpl/src/loci/formats/in/PyramidTiffReader.java b/components/formats-gpl/src/loci/formats/in/PyramidTiffReader.java index de72c56c816..e1bbb959f2a 100644 --- a/components/formats-gpl/src/loci/formats/in/PyramidTiffReader.java +++ b/components/formats-gpl/src/loci/formats/in/PyramidTiffReader.java @@ -26,19 +26,33 @@ package loci.formats.in; import java.io.IOException; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import loci.common.RandomAccessInputStream; +import loci.common.services.DependencyException; +import loci.common.services.ServiceException; +import loci.common.services.ServiceFactory; import loci.formats.CoreMetadata; import loci.formats.FormatException; import loci.formats.FormatTools; +import loci.formats.MissingLibraryException; +import loci.formats.meta.IMetadata; +import loci.formats.meta.MetadataConverter; import loci.formats.meta.MetadataStore; +import loci.formats.services.OMEXMLService; +import loci.formats.services.OMEXMLServiceImpl; import loci.formats.tiff.IFD; import loci.formats.tiff.PhotoInterp; import loci.formats.tiff.TiffParser; +import ome.xml.meta.OMEXMLMetadataRoot; +import ome.xml.model.Image; +import ome.xml.model.Pixels; +import ome.xml.model.TiffData; + /** * PyramidTiffReader is the file format reader for pyramid TIFFs. */ @@ -52,6 +66,8 @@ public class PyramidTiffReader extends BaseTiffReader { // -- Fields -- + private IMetadata omexml = null; + // -- Constructor -- /** Constructs a new pyramid TIFF reader. */ @@ -77,6 +93,17 @@ public boolean isThisType(RandomAccessInputStream stream) throws IOException { return software.indexOf("Faas") >= 0; } + /** + * @see loci.formats.IFormatReader#close(boolean) + */ + @Override + public void close(boolean fileOnly) throws IOException { + super.close(fileOnly); + if (!fileOnly) { + omexml = null; + } + } + /** * @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int) */ @@ -85,7 +112,7 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) throws FormatException, IOException { FormatTools.checkPlaneParameters(this, no, buf.length, x, y, w, h); - int index = getCoreIndex(); + int index = getCoreIndex() * getImageCount() + no; tiffParser.setAssumeEqualStrips(equalStrips); tiffParser.getSamples(ifds.get(index), buf, x, y, w, h); return buf; @@ -96,7 +123,7 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) public int getOptimalTileWidth() { FormatTools.assertId(currentId, true, 1); try { - return (int) ifds.get(getCoreIndex()).getTileWidth(); + return (int) ifds.get(getCoreIndex() * getImageCount()).getTileWidth(); } catch (FormatException e) { LOGGER.debug("", e); @@ -109,7 +136,7 @@ public int getOptimalTileWidth() { public int getOptimalTileHeight() { FormatTools.assertId(currentId, true, 1); try { - return (int) ifds.get(getCoreIndex()).getTileLength(); + return (int) ifds.get(getCoreIndex() * getImageCount()).getTileLength(); } catch (FormatException e) { LOGGER.debug("", e); @@ -122,7 +149,38 @@ public int getOptimalTileHeight() { /* @see loci.formats.in.BaseTiffReader#initStandardMetadata() */ @Override protected void initStandardMetadata() throws FormatException, IOException { - int seriesCount = ifds.size(); + // count number of consecutive planes with the same XY dimensions + + int nPlanes = 1; + long baseWidth = ifds.get(0).getImageWidth(); + long baseHeight = ifds.get(0).getImageLength(); + for (int i=1; i 0 && comment.trim().startsWith("<")) { + try { + ServiceFactory factory = new ServiceFactory(); + OMEXMLService service = factory.getInstance(OMEXMLService.class); + omexml = service.createOMEXMLMetadata(comment); + } + catch (DependencyException de) { + throw new MissingLibraryException(OMEXMLServiceImpl.NO_OME_XML_MSG, de); + } + catch (ServiceException e) { + LOGGER.debug("Could not parse comment as OME-XML", e); + } + } // repopulate core metadata core.clear(); @@ -134,7 +192,7 @@ protected void initStandardMetadata() throws FormatException, IOException { ms.resolutionCount = seriesCount; } - IFD ifd = ifds.get(s); + IFD ifd = ifds.get(s * nPlanes); PhotoInterp p = ifd.getPhotometricInterpretation(); int samples = ifd.getSamplesPerPixel(); @@ -145,18 +203,28 @@ protected void initStandardMetadata() throws FormatException, IOException { ms.sizeX = (int) ifd.getImageWidth(); ms.sizeY = (int) ifd.getImageLength(); - ms.sizeZ = 1; - ms.sizeT = 1; - ms.sizeC = ms.rgb ? samples : 1; + if (omexml != null) { + ms.sizeZ = omexml.getPixelsSizeZ(0).getValue(); + ms.sizeT = omexml.getPixelsSizeT(0).getValue(); + ms.sizeC = omexml.getPixelsSizeC(0).getValue(); + ms.dimensionOrder = omexml.getPixelsDimensionOrder(0).getValue(); + } + else { + ms.sizeZ = 1; + ms.sizeT = 1; + ms.sizeC = ms.rgb ? samples : 1; + // assuming all planes are channels + ms.sizeC *= nPlanes; + ms.dimensionOrder = "XYCZT"; + } ms.littleEndian = ifd.isLittleEndian(); ms.indexed = p == PhotoInterp.RGB_PALETTE && (get8BitLookupTable() != null || get16BitLookupTable() != null); - ms.imageCount = 1; + ms.imageCount = nPlanes; ms.pixelType = ifd.getPixelType(); ms.metadataComplete = true; ms.interleaved = false; ms.falseColor = false; - ms.dimensionOrder = "XYCZT"; ms.thumbnail = s > 0; } } @@ -164,12 +232,39 @@ protected void initStandardMetadata() throws FormatException, IOException { /* @see loci.formats.BaseTiffReader#initMetadataStore() */ @Override protected void initMetadataStore() throws FormatException { - super.initMetadataStore(); + boolean setImageNames = true; + if (omexml == null) { + super.initMetadataStore(); + } + else { + OMEXMLMetadataRoot root = (OMEXMLMetadataRoot) omexml.getRoot(); + List images = root.copyImageList(); + for (int i=0; i 0 && !hasFlattenedResolutions()) { + root.removeImage(img); + continue; + } + Pixels pix = img.getPixels(); + List tiffData = pix.copyTiffDataList(); + for (TiffData t : tiffData) { + pix.removeTiffData(t); + } + if (img.getName() != null) { + setImageNames = false; + } + } + omexml.setRoot(root); - MetadataStore store = makeFilterMetadata(); + MetadataConverter.convertMetadata(omexml, makeFilterMetadata()); + } + + if (setImageNames) { + MetadataStore store = makeFilterMetadata(); - for (int i=0; i