diff --git a/.github/workflows/ant.yml b/.github/workflows/ant.yml index 0466551c8e7..e93b61600fc 100644 --- a/.github/workflows/ant.yml +++ b/.github/workflows/ant.yml @@ -11,7 +11,7 @@ jobs: os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 with: diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index cd3aa28dbba..3440ecedb6d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -19,7 +19,7 @@ jobs: env: maven_commands: install # default is install steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 with: @@ -33,7 +33,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Retrieve version id: get_version run: | @@ -66,7 +66,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Retrieve version id: get_version run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8886e06f13a..667c6c32a4e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: name: Release artifacts runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK uses: actions/setup-java@v3 with: diff --git a/components/bio-formats-plugins/pom.xml b/components/bio-formats-plugins/pom.xml index 92281eea25f..fdb7aab2935 100644 --- a/components/bio-formats-plugins/pom.xml +++ b/components/bio-formats-plugins/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../.. diff --git a/components/bio-formats-plugins/src/loci/plugins/out/Exporter.java b/components/bio-formats-plugins/src/loci/plugins/out/Exporter.java index 92897a6116c..0e614bf58e2 100644 --- a/components/bio-formats-plugins/src/loci/plugins/out/Exporter.java +++ b/components/bio-formats-plugins/src/loci/plugins/out/Exporter.java @@ -446,6 +446,15 @@ else if (store.getImageCount() > 1) { store.setPixelsSizeC(new PositiveInteger(channels*imp.getNChannels()), 0); store.setPixelsSizeT(new PositiveInteger(imp.getNFrames()), 0); + try { + // if a subset of the data was opened, the number of Channels + // in the OME-XML may not match the ImagePlus channel count + // channel count mismatches can cause problems when actually writing pixels + service.removeChannels(service.getOMEMetadata(store), 0, imp.getNChannels()); + } + catch (ServiceException e) { + } + if (store.getImageID(0) == null) { store.setImageID(MetadataTools.createLSID("Image", 0), 0); } diff --git a/components/bio-formats-tools/pom.xml b/components/bio-formats-tools/pom.xml index 6dca9e341c6..9fe6f016778 100644 --- a/components/bio-formats-tools/pom.xml +++ b/components/bio-formats-tools/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../.. diff --git a/components/bio-formats-tools/src/loci/formats/tools/GenerateCache.java b/components/bio-formats-tools/src/loci/formats/tools/GenerateCache.java index dd34d0c598c..5a297e71513 100644 --- a/components/bio-formats-tools/src/loci/formats/tools/GenerateCache.java +++ b/components/bio-formats-tools/src/loci/formats/tools/GenerateCache.java @@ -9,13 +9,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/components/bundles/bioformats_package/pom.xml b/components/bundles/bioformats_package/pom.xml index 836ec6e2ce8..ef7fcd018cb 100644 --- a/components/bundles/bioformats_package/pom.xml +++ b/components/bundles/bioformats_package/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../../../ diff --git a/components/forks/turbojpeg/pom.xml b/components/forks/turbojpeg/pom.xml index 221e02ca0ec..df27e1968ff 100644 --- a/components/forks/turbojpeg/pom.xml +++ b/components/forks/turbojpeg/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../../../ diff --git a/components/formats-api/pom.xml b/components/formats-api/pom.xml index d9bcb8c24da..a5b34b42d13 100644 --- a/components/formats-api/pom.xml +++ b/components/formats-api/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../.. diff --git a/components/formats-api/src/loci/formats/CoreMetadataList.java b/components/formats-api/src/loci/formats/CoreMetadataList.java index 82928f5eaf4..8d2ffdf65ba 100644 --- a/components/formats-api/src/loci/formats/CoreMetadataList.java +++ b/components/formats-api/src/loci/formats/CoreMetadataList.java @@ -9,13 +9,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/components/formats-api/src/loci/formats/MetadataList.java b/components/formats-api/src/loci/formats/MetadataList.java index b1a09f9ac35..078d7322bee 100644 --- a/components/formats-api/src/loci/formats/MetadataList.java +++ b/components/formats-api/src/loci/formats/MetadataList.java @@ -1,6 +1,6 @@ /* * #%L - * primary reader and writer APIs + * Top-level reader and writer APIs * %% * Copyright (C) 2018 Open Microscopy Environment: * - Board of Regents of the University of Wisconsin-Madison @@ -9,13 +9,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/components/formats-api/test/loci/formats/utests/CoreMetadataListTest.java b/components/formats-api/test/loci/formats/utests/CoreMetadataListTest.java index 0cd22e6a887..beb18cc1f53 100644 --- a/components/formats-api/test/loci/formats/utests/CoreMetadataListTest.java +++ b/components/formats-api/test/loci/formats/utests/CoreMetadataListTest.java @@ -9,13 +9,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/components/formats-api/test/loci/formats/utests/MetadataListTest.java b/components/formats-api/test/loci/formats/utests/MetadataListTest.java index 548a5a15293..e325066acf4 100644 --- a/components/formats-api/test/loci/formats/utests/MetadataListTest.java +++ b/components/formats-api/test/loci/formats/utests/MetadataListTest.java @@ -9,13 +9,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/components/formats-bsd/pom.xml b/components/formats-bsd/pom.xml index 7b6328e8531..28842a8ae24 100644 --- a/components/formats-bsd/pom.xml +++ b/components/formats-bsd/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../.. diff --git a/components/formats-bsd/src/loci/formats/in/OBFReader.java b/components/formats-bsd/src/loci/formats/in/OBFReader.java index 019b04f47f3..a5d4ec6447c 100644 --- a/components/formats-bsd/src/loci/formats/in/OBFReader.java +++ b/components/formats-bsd/src/loci/formats/in/OBFReader.java @@ -10,13 +10,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/components/formats-bsd/src/loci/formats/in/OMETiffReader.java b/components/formats-bsd/src/loci/formats/in/OMETiffReader.java index d6ff74ab992..91569b16ea7 100644 --- a/components/formats-bsd/src/loci/formats/in/OMETiffReader.java +++ b/components/formats-bsd/src/loci/formats/in/OMETiffReader.java @@ -1103,6 +1103,9 @@ else if (t == 0) { if (firstFile == null || (testFile != null && !info[s][0].reader.isThisType(testFile))) { + if (info[s][0].id != null && failOnMissingTIFF()) { + throw new FormatException("Invalid file (may be corrupted): " + info[s][0].id); + } LOGGER.warn("{} is not a valid OME-TIFF", info[s][0].id); info[s][0].id = currentId; info[s][0].exists = false; diff --git a/components/formats-bsd/src/loci/formats/in/SlideBook7Reader.java b/components/formats-bsd/src/loci/formats/in/SlideBook7Reader.java index 5eb6388e56e..e7fead7ff25 100644 --- a/components/formats-bsd/src/loci/formats/in/SlideBook7Reader.java +++ b/components/formats-bsd/src/loci/formats/in/SlideBook7Reader.java @@ -1,26 +1,33 @@ /* * #%L - * OME Bio-Formats package for reading and converting biological file formats. + * BSD implementations of Bio-Formats readers and writers * %% * Copyright (C) 2005 - 2022 Open Microscopy Environment: * - Board of Regents of the University of Wisconsin-Madison * - Glencoe Software, Inc. * - University of Dundee * %% - * This program 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 2 of the - * License, or (at your option) any later version. - * - * This program 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 this program. If not, see - * . + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * #L% */ diff --git a/components/formats-bsd/src/loci/formats/out/DicomWriter.java b/components/formats-bsd/src/loci/formats/out/DicomWriter.java index 3164bd36728..3aa822f437b 100644 --- a/components/formats-bsd/src/loci/formats/out/DicomWriter.java +++ b/components/formats-bsd/src/loci/formats/out/DicomWriter.java @@ -188,6 +188,10 @@ public void saveBytes(int no, byte[] buf, int x, int y, int w, int h) { checkParams(no, buf, x, y, w, h); + int resolutionIndex = getIndex(series, resolution); + int thisTileWidth = tileWidth[resolutionIndex]; + int thisTileHeight = tileHeight[resolutionIndex]; + MetadataRetrieve r = getMetadataRetrieve(); if ((!(r instanceof IPyramidStore) || ((IPyramidStore) r).getResolutionCount(series) == 1) && @@ -195,11 +199,17 @@ public void saveBytes(int no, byte[] buf, int x, int y, int w, int h) { throw new FormatException("DicomWriter does not allow tiles for non-pyramid images"); } + else if (x % thisTileWidth != 0 || y % thisTileHeight != 0 || + (w != thisTileWidth && x + w != getSizeX()) || + (h != thisTileHeight && y + h != getSizeY())) + { + throw new FormatException("Tile too small, expected " + thisTileWidth + "x" + thisTileHeight + + ". Setting the tile size to " + getSizeX() + "x" + getSizeY() + " or smaller may work."); + } checkPixelCount(false); boolean first = x == 0 && y == 0; boolean last = x + w == getSizeX() && y + h == getSizeY(); - int resolutionIndex = getIndex(series, resolution); // the compression type isn't supplied to the writer until // after setId is called, so metadata that indicates or @@ -264,8 +274,6 @@ public void saveBytes(int no, byte[] buf, int x, int y, int w, int h) byte[] paddedBuf = null; - int thisTileWidth = tileWidth[resolutionIndex]; - int thisTileHeight = tileHeight[resolutionIndex]; int thisTilePixels = thisTileWidth * thisTileHeight; // pad the last row and column of tiles to match specified tile size diff --git a/components/formats-bsd/src/loci/formats/services/JPEGTurboServiceImpl.java b/components/formats-bsd/src/loci/formats/services/JPEGTurboServiceImpl.java index 49f82deff58..3231da2686b 100644 --- a/components/formats-bsd/src/loci/formats/services/JPEGTurboServiceImpl.java +++ b/components/formats-bsd/src/loci/formats/services/JPEGTurboServiceImpl.java @@ -105,8 +105,10 @@ public JPEGTurboServiceImpl() { logger = Logger.getLogger(NATIVE_LIB_CLASS); logger.setLevel(Level.SEVERE); if (!libraryLoaded) { - NativeLibraryUtil.loadNativeLibrary(TJ.class, "turbojpeg"); - libraryLoaded = true; + libraryLoaded = NativeLibraryUtil.loadNativeLibrary(TJ.class, "turbojpeg"); + if (!libraryLoaded) { + throw new RuntimeException("TurboJPEG could not be loaded"); + } } } diff --git a/components/formats-bsd/src/loci/formats/tiff/IFD.java b/components/formats-bsd/src/loci/formats/tiff/IFD.java index 4fff9d2cf90..71ab6c02ccd 100644 --- a/components/formats-bsd/src/loci/formats/tiff/IFD.java +++ b/components/formats-bsd/src/loci/formats/tiff/IFD.java @@ -615,6 +615,9 @@ public int getPixelType() throws FormatException { case 24: return FormatTools.FLOAT; case 64: + if (bitFormat != 3) { + throw new FormatException("64-bit int data not supported"); + } return FormatTools.DOUBLE; case 32: if (bitFormat == 3) return FormatTools.FLOAT; diff --git a/components/formats-bsd/src/loci/formats/tiff/TiffParser.java b/components/formats-bsd/src/loci/formats/tiff/TiffParser.java index 809bd5d3356..9658bfd21fa 100644 --- a/components/formats-bsd/src/loci/formats/tiff/TiffParser.java +++ b/components/formats-bsd/src/loci/formats/tiff/TiffParser.java @@ -546,6 +546,9 @@ public Object getIFDValue(TiffIFDEntry entry) throws IOException { offset &= 0xffffffffL; offset += 0x100000000L; } + if (offset >= in.length()) { + return null; + } in.seek(offset); } diff --git a/components/formats-bsd/test/spec/AbstractTest.java b/components/formats-bsd/test/spec/AbstractTest.java index c2130923bc8..b5444a77692 100644 --- a/components/formats-bsd/test/spec/AbstractTest.java +++ b/components/formats-bsd/test/spec/AbstractTest.java @@ -1,8 +1,11 @@ /* * #%L - * Tests for OME-XML specification classes. + * BSD implementations of Bio-Formats readers and writers * %% - * Copyright (C) 2010-2013 Glencoe Software, Inc. + * Copyright (C) 2005 - 2017 Open Microscopy Environment: + * - Board of Regents of the University of Wisconsin-Madison + * - Glencoe Software, Inc. + * - University of Dundee * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -24,10 +27,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of any organization. * #L% */ diff --git a/components/formats-gpl/pom.xml b/components/formats-gpl/pom.xml index 3bbddb4ab42..71c926459de 100644 --- a/components/formats-gpl/pom.xml +++ b/components/formats-gpl/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../.. @@ -153,7 +153,7 @@ org.json json - 20230227 + 20231013 org.xerial diff --git a/components/formats-gpl/src/loci/formats/in/GatanReader.java b/components/formats-gpl/src/loci/formats/in/GatanReader.java index 9029b59eab0..ae4e99caebf 100644 --- a/components/formats-gpl/src/loci/formats/in/GatanReader.java +++ b/components/formats-gpl/src/loci/formats/in/GatanReader.java @@ -347,8 +347,15 @@ else if (pixelSizes.size() == 4) { for (String token : scopeInfo) { token = token.trim(); if (token.startsWith("Mode")) { - token = token.substring(token.indexOf(' ')).trim(); - mode = token.substring(0, token.indexOf(' ')).trim(); + if (token.indexOf(' ') > 0) { + token = token.substring(token.indexOf(' ')).trim(); + } + if (token.indexOf(' ') > 0) { + mode = token.substring(0, token.indexOf(' ')).trim(); + } + else { + mode = token; + } if (mode.equals("TEM")) mode = "Other"; } } diff --git a/components/formats-gpl/src/loci/formats/in/GelReader.java b/components/formats-gpl/src/loci/formats/in/GelReader.java index 37ed73714f7..1d0a2b36d41 100644 --- a/components/formats-gpl/src/loci/formats/in/GelReader.java +++ b/components/formats-gpl/src/loci/formats/in/GelReader.java @@ -90,7 +90,11 @@ public GelReader() { public boolean isThisType(RandomAccessInputStream stream) throws IOException { TiffParser parser = new TiffParser(stream); parser.setDoCaching(false); - IFD ifd = parser.getFirstIFD(); + long[] offsets = parser.getIFDOffsets(); + if (offsets.length == 0 || offsets.length > 2) { + return false; + } + IFD ifd = parser.getIFD(offsets[0]); if (ifd == null) return false; return ifd.containsKey(MD_FILETAG); } diff --git a/components/formats-gpl/src/loci/formats/in/IonpathMIBITiffReader.java b/components/formats-gpl/src/loci/formats/in/IonpathMIBITiffReader.java index 3f1961ddd55..76a3e9d7440 100644 --- a/components/formats-gpl/src/loci/formats/in/IonpathMIBITiffReader.java +++ b/components/formats-gpl/src/loci/formats/in/IonpathMIBITiffReader.java @@ -11,12 +11,12 @@ * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 2 of the * License, or (at your option) any later version. - * + * * This program 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 this program. If not, see * . diff --git a/components/formats-gpl/src/loci/formats/in/IvisionReader.java b/components/formats-gpl/src/loci/formats/in/IvisionReader.java index 4de6677c9d6..22b758de9b5 100644 --- a/components/formats-gpl/src/loci/formats/in/IvisionReader.java +++ b/components/formats-gpl/src/loci/formats/in/IvisionReader.java @@ -94,7 +94,12 @@ public boolean isThisType(RandomAccessInputStream stream) throws IOException { String version = stream.readString(3); try { Double.parseDouble(version); - return version.indexOf('.') != -1 && version.indexOf('-') == -1; + boolean validVersion = version.indexOf('.') != -1 && version.indexOf('-') == -1; + boolean validPatch = Character.isAlphabetic(stream.read()); + stream.skipBytes(1); + int dataType = stream.read(); + boolean validType = dataType >= 0 && dataType <= 8; + return validVersion && validPatch && validType; } catch (NumberFormatException e) { } return false; diff --git a/components/formats-gpl/src/loci/formats/in/NDPIReader.java b/components/formats-gpl/src/loci/formats/in/NDPIReader.java index c2db3029207..6da4236d697 100644 --- a/components/formats-gpl/src/loci/formats/in/NDPIReader.java +++ b/components/formats-gpl/src/loci/formats/in/NDPIReader.java @@ -71,6 +71,7 @@ public class NDPIReader extends BaseTiffReader { private static final int TISSUE_INDEX = 65425; private static final int MARKER_TAG = 65426; private static final int REFERENCE = 65427; + private static final int MARKER_TAG_HIGH_BYTES = 65432; private static final int FILTER_SET_NAME = 65434; private static final int EXPOSURE_RATIO = 65435; private static final int RED_MULTIPLIER = 65436; @@ -197,11 +198,34 @@ else if (useTiffParser(ifds.get(ifdIndex))) { try { service.close(); long[] markers = ifd.getIFDLongArray(MARKER_TAG); + long[] markerHighBytes = ifd.getIFDLongArray(MARKER_TAG_HIGH_BYTES); if (!use64Bit) { for (int i=0; i 0) { diff --git a/components/formats-gpl/src/loci/formats/in/SVSReader.java b/components/formats-gpl/src/loci/formats/in/SVSReader.java index 11e74b554d0..9bc9728ed96 100644 --- a/components/formats-gpl/src/loci/formats/in/SVSReader.java +++ b/components/formats-gpl/src/loci/formats/in/SVSReader.java @@ -90,10 +90,19 @@ public class SVSReader extends BaseTiffReader { private ArrayList dyeNames = new ArrayList(); private transient Color displayColor = null; + + // explicitly record the series and IFD indexes + // for the label and macro images + // this makes it easier to calculate IFD mappings private int labelIndex = -1; private int macroIndex = -1; + + // total number of extra (label and macro) images private int extraImages = 0; + private transient Double physicalDistanceFromLeftEdge; + private transient Double physicalDistanceFromTopEdge; + // -- Constructor -- /** Constructs a new SVS reader. */ @@ -275,7 +284,7 @@ protected void initStandardMetadata() throws FormatException, IOException { for (int i=0; i= 0) { } else { ifds.remove(s); + if (s < labelIndex) { + labelIndex--; + } + if (s < macroIndex) { + macroIndex--; + } } } if (uniqueZ.size() == 0) { @@ -469,6 +484,12 @@ else if (t.toLowerCase().indexOf("macro") >= 0) { int color = Integer.parseInt(value); displayColor = new Color((color << 8) | 0xff); break; + case "Left": + physicalDistanceFromLeftEdge = DataTools.parseDouble(value); + break; + case "Top": + physicalDistanceFromTopEdge = DataTools.parseDouble(value); + break; } } } @@ -486,7 +507,10 @@ protected void initMetadataStore() throws FormatException { super.initMetadataStore(); MetadataStore store = makeFilterMetadata(); - MetadataTools.populatePixels(store, this, getImageCount() > 1); + boolean populatePlaneData = getImageCount() > 1 || + physicalDistanceFromTopEdge != null || + physicalDistanceFromLeftEdge != null; + MetadataTools.populatePixels(store, this, populatePlaneData); String instrument = MetadataTools.createLSID("Instrument", 0); String objective = MetadataTools.createLSID("Objective", 0, 0); @@ -501,6 +525,21 @@ protected void initMetadataStore() throws FormatException { store.setImageInstrumentRef(instrument, i); store.setObjectiveSettingsID(objective, i); + if (i == 0) { + if (physicalDistanceFromTopEdge != null) { + Length yPos = FormatTools.getStagePosition(physicalDistanceFromTopEdge, UNITS.MM); + for (int p=0; p extraImages) { store.setImageName("Series " + (i + 1), i); } @@ -508,10 +547,10 @@ protected void initMetadataStore() throws FormatException { if (i == 0) { store.setImageName("", i); } - else if (i == labelIndex) { + else if (core.flattenedIndex(i, 0) == labelIndex) { store.setImageName("label image", i); } - else if (i == macroIndex) { + else if (core.flattenedIndex(i, 0) == macroIndex) { store.setImageName("macro image", i); } } @@ -559,7 +598,10 @@ else if (i == macroIndex) { private int getIFDIndex(int coreIndex, int no) { int index = coreIndex; + // coreCount is the number of pyramid resolutions (independent of flattening) int coreCount = core.flattenedSize() - extraImages; + + // this is the case where the requested IFD is within the pyramid if (coreIndex > 0 && coreIndex < coreCount) { if (core.get(0, 0).imageCount > 1) { index++; @@ -568,6 +610,7 @@ private int getIFDIndex(int coreIndex, int no) { index = coreCount - coreIndex; } } + if ((coreIndex > 0 && coreIndex < coreCount) || no > 0) { for (int i=0; i= coreCount && core.get(0, 0).imageCount > 1) { - for (int i=0; i= coreCount) { + if (core.get(0, 0).imageCount > 1) { + for (int i=0; i getDyeNames() { diff --git a/components/formats-gpl/src/loci/formats/in/TillVisionReader.java b/components/formats-gpl/src/loci/formats/in/TillVisionReader.java index 4060304ed7a..74cbd362517 100644 --- a/components/formats-gpl/src/loci/formats/in/TillVisionReader.java +++ b/components/formats-gpl/src/loci/formats/in/TillVisionReader.java @@ -74,6 +74,10 @@ public class TillVisionReader extends FormatReader { new byte[] {0x43, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x03, 0x00}; private static final byte[] MARKER_3 = new byte[] {(byte) 0x83, 3, 0}; + private static final byte[] DESCRIPTION_MARKER = new byte[] { + 0, 0, 0, 0, 0, (byte) 0xff + }; + private static final String[] DATE_FORMATS = new String[] { "mm/dd/yy HH:mm:ss aa", "mm/dd/yy HH:mm:ss aa", "mm/dd/yy", "HH:mm:ss aa", "HH:mm:ss aa"}; @@ -339,6 +343,8 @@ else if (vwsFile.isDirectory()) { int lowerBound = 0; int upperBound = 0x1000; + // parse main metadata stream in two steps: + // first get the list of image names... while (s.getFilePointer() < s.length() - 2) { LOGGER.debug(" Looking for image at {}", s.getFilePointer()); s.order(false); @@ -358,6 +364,28 @@ else if (vwsFile.isDirectory()) { upperBound = 0x4000; } if (len < lowerBound || len > upperBound) continue; + s.skipBytes(len); + } + + // ...and now get the acquisition metadata text + // the image names and other key/value pairs are + // often not co-located, so this seems to be more accurate + // than trying to parse everything together + // + // the expected series count (nImages) is based on how many + // metadata text blocks are found + s.seek(0); + s.order(true); + while (s.getFilePointer() < s.length() - 2) { + long offset = findNextOffset(s, DESCRIPTION_MARKER); + if (offset < 0 || offset >= s.length() - 2) { + break; + } + s.seek(offset); + int len = s.readShort(); + if (len <= 0 || len > 0x1000) { + continue; + } String description = s.readString(len); LOGGER.debug("Description: {}", description); @@ -366,10 +394,13 @@ else if (vwsFile.isDirectory()) { String dateTime = ""; String[] lines = description.split("[\r\n]"); + boolean validLine = false; for (String line : lines) { line = line.trim(); int colon = line.indexOf(':'); if (colon != -1 && !line.startsWith(";")) { + validLine = true; + String key = line.substring(0, colon).trim(); String value = line.substring(colon + 1).trim(); String metaKey = "Series " + nImages + " " + key; @@ -405,7 +436,9 @@ else if (key.equals("Image type")) { } dates.add(success ? dateTime : ""); } - nImages++; + if (validLine) { + nImages++; + } } } } @@ -414,7 +447,7 @@ else if (key.equals("Image type")) { Location directory = new Location(currentId).getAbsoluteFile().getParentFile(); - String[] pixelsFile = new String[nImages]; + List pixelsFile = new ArrayList(nImages); if (!embeddedImages) { if (nImages == 0) { @@ -427,8 +460,6 @@ else if (key.equals("Image type")) { String name = currentId.substring( currentId.lastIndexOf(File.separator) + 1, currentId.lastIndexOf(".")); - int nextFile = 0; - for (String f : files) { if (checkSuffix(f, "pst")) { Location pst = new Location(directory, f); @@ -436,31 +467,40 @@ else if (key.equals("Image type")) { String[] subfiles = pst.list(true); Arrays.sort(subfiles); for (String q : subfiles) { - if (checkSuffix(q, "pst") && nextFile < nImages) { - pixelsFile[nextFile++] = f + File.separator + q; + if (checkSuffix(q, "pst")) { + String path = f + File.separator + q; + // usually the number of .pst files matches the number of + // metadata text blocks parsed earlier + // in rare cases, there are actually fewer metadata text blocks + // than .pst files, so err on the side of showing all image data + if (pixelsFile.size() >= nImages) { + LOGGER.warn("Adding {}, no matching acquisition metadata", path); + } + pixelsFile.add(path); } } } } } - if (nextFile == 0) { + if (pixelsFile.size() == 0) { for (String f : files) { if (checkSuffix(f, "pst")) { - pixelsFile[nextFile++] = - new Location(directory, f).getAbsolutePath(); + pixelsFile.add(new Location(directory, f).getAbsolutePath()); } } - if (nextFile == 0) throw new FormatException("No image files found."); + if (pixelsFile.size() == 0) { + throw new FormatException("No image files found."); + } } } - Arrays.sort(pixelsFile); + pixelsFile.sort(null); int nSeries = core.size(); if (!embeddedImages) { core.clear(); - nSeries = nImages; + nSeries = pixelsFile.size(); } pixelsFiles = new String[nSeries]; @@ -479,7 +519,7 @@ else if (key.equals("Image type")) { // make sure that pixels file exists - String file = pixelsFile[i]; + String file = pixelsFile.get(i); file = file.replace('/', File.separatorChar); file = file.replace('\\', File.separatorChar); diff --git a/components/formats-gpl/src/loci/formats/in/VentanaReader.java b/components/formats-gpl/src/loci/formats/in/VentanaReader.java index 49749983e7d..12b0ec9860f 100644 --- a/components/formats-gpl/src/loci/formats/in/VentanaReader.java +++ b/components/formats-gpl/src/loci/formats/in/VentanaReader.java @@ -230,8 +230,8 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) int outputRowLen = w * tilePixel; int scale = getScale(getCoreIndex()); - int thisTileWidth = tileWidth / scale; - int thisTileHeight = tileHeight / scale; + int thisTileWidth = scaleCoordinate(tileWidth, getCoreIndex()); + int thisTileHeight = scaleCoordinate(tileHeight, getCoreIndex()); byte[] subResTile = null; int subResX = -1, subResY = -1; @@ -250,8 +250,8 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) } tileBox.x = scaleCoordinate(tileBox.x, getCoreIndex()); tileBox.y = scaleCoordinate(tileBox.y, getCoreIndex()); - tileBox.width /= scale; - tileBox.height /= scale; + tileBox.width = scaleCoordinate(tileBox.width, getCoreIndex()); + tileBox.height = scaleCoordinate(tileBox.height, getCoreIndex()); if (tileBox.intersects(imageBox)) { if (scale == 1) { @@ -292,9 +292,13 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) input = inRow * (c * tileHeight + offsetY) + offsetX * tilePixel; output = c * thisTileHeight * outRow; for (int row=0; row= 0) { + System.arraycopy(subResTile, input, tilePixels, output, copy); + input += inRow; + output += outRow; + } } } } diff --git a/components/test-suite/pom.xml b/components/test-suite/pom.xml index f8990bd8055..09d8dcd53fa 100644 --- a/components/test-suite/pom.xml +++ b/components/test-suite/pom.xml @@ -8,7 +8,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ../.. diff --git a/pom.xml b/pom.xml index 283ef45c21d..4b3cb4f1945 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ ome pom-bio-formats - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT pom Bio-Formats projects @@ -34,7 +34,7 @@ When possible, we advise using the relevant groupId and version properties for your dependencies rather than hardcoding them. --> - 7.0.1-SNAPSHOT + 7.1.0-SNAPSHOT ${maven.build.timestamp} 2017 ${basedir} @@ -48,7 +48,7 @@ 1.7.30 5.4.0 6.8 - 6.0.19 + 6.0.20 org.openmicroscopy 6.3.3 5.3.7