Search in sources :

Example 76 with IFD

use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.

the class ZeissLSMReader method initMetadata.

protected void initMetadata(int series) throws FormatException, IOException {
    setSeries(series);
    IFDList ifds = ifdsList.get(series);
    IFD ifd = ifds.get(0);
    in.close();
    in = new RandomAccessInputStream(getLSMFileFromSeries(series), 16);
    in.order(isLittleEndian());
    tiffParser = new TiffParser(in);
    PhotoInterp photo = ifd.getPhotometricInterpretation();
    int samples = ifd.getSamplesPerPixel();
    CoreMetadata ms = core.get(series);
    ms.sizeX = (int) ifd.getImageWidth();
    ms.sizeY = (int) ifd.getImageLength();
    ms.rgb = samples > 1 || photo == PhotoInterp.RGB;
    ms.interleaved = false;
    ms.sizeC = isRGB() ? samples : 1;
    ms.pixelType = ifd.getPixelType();
    ms.imageCount = ifds.size();
    ms.sizeZ = getImageCount();
    ms.sizeT = 1;
    LOGGER.info("Reading LSM metadata for series #{}", series);
    MetadataStore store = makeFilterMetadata();
    int instrument = getEffectiveSeries(series);
    String imageName = getLSMFileFromSeries(series);
    if (imageName.indexOf('.') != -1) {
        imageName = imageName.substring(0, imageName.lastIndexOf("."));
    }
    if (imageName.indexOf(File.separator) != -1) {
        imageName = imageName.substring(imageName.lastIndexOf(File.separator) + 1);
    }
    if (lsmFilenames.length != getSeriesCount()) {
        imageName += " #" + (getPosition(series) + 1);
    }
    // link Instrument and Image
    store.setImageID(MetadataTools.createLSID("Image", series), series);
    String instrumentID = MetadataTools.createLSID("Instrument", instrument);
    store.setInstrumentID(instrumentID, instrument);
    store.setImageInstrumentRef(instrumentID, series);
    RandomAccessInputStream ras = getCZTag(ifd);
    if (ras == null) {
        imageNames.add(imageName);
        return;
    }
    ras.seek(16);
    ms.sizeZ = ras.readInt();
    ras.skipBytes(4);
    ms.sizeT = ras.readInt();
    int dataType = ras.readInt();
    switch(dataType) {
        case 2:
            addSeriesMeta("DataType", "12 bit unsigned integer");
            break;
        case 5:
            addSeriesMeta("DataType", "32 bit float");
            break;
        case 0:
            addSeriesMeta("DataType", "varying data types");
            break;
        default:
            addSeriesMeta("DataType", "8 bit unsigned integer");
    }
    if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        ras.seek(0);
        addSeriesMeta("MagicNumber ", ras.readInt());
        addSeriesMeta("StructureSize", ras.readInt());
        addSeriesMeta("DimensionX", ras.readInt());
        addSeriesMeta("DimensionY", ras.readInt());
        ras.seek(32);
        addSeriesMeta("ThumbnailX", ras.readInt());
        addSeriesMeta("ThumbnailY", ras.readInt());
        // pixel sizes are stored in meters, we need them in microns
        pixelSizeX = ras.readDouble() * 1000000;
        pixelSizeY = ras.readDouble() * 1000000;
        pixelSizeZ = ras.readDouble() * 1000000;
        addSeriesMeta("VoxelSizeX", pixelSizeX);
        addSeriesMeta("VoxelSizeY", pixelSizeY);
        addSeriesMeta("VoxelSizeZ", pixelSizeZ);
        originX = ras.readDouble() * 1000000;
        originY = ras.readDouble() * 1000000;
        originZ = ras.readDouble() * 1000000;
        addSeriesMeta("OriginX", originX);
        addSeriesMeta("OriginY", originY);
        addSeriesMeta("OriginZ", originZ);
    } else
        ras.seek(88);
    int scanType = ras.readShort();
    switch(scanType) {
        case 0:
            addSeriesMeta("ScanType", "x-y-z scan");
            ms.dimensionOrder = "XYZCT";
            break;
        case 1:
            addSeriesMeta("ScanType", "z scan (x-z plane)");
            ms.dimensionOrder = "XYZCT";
            break;
        case 2:
            addSeriesMeta("ScanType", "line scan");
            ms.dimensionOrder = "XYZCT";
            break;
        case 3:
            addSeriesMeta("ScanType", "time series x-y");
            ms.dimensionOrder = "XYTCZ";
            break;
        case 4:
            addSeriesMeta("ScanType", "time series x-z");
            ms.dimensionOrder = "XYZTC";
            break;
        case 5:
            addSeriesMeta("ScanType", "time series 'Mean of ROIs'");
            ms.dimensionOrder = "XYTCZ";
            break;
        case 6:
            addSeriesMeta("ScanType", "time series x-y-z");
            ms.dimensionOrder = "XYZTC";
            break;
        case 7:
            addSeriesMeta("ScanType", "spline scan");
            ms.dimensionOrder = "XYCTZ";
            break;
        case 8:
            addSeriesMeta("ScanType", "spline scan x-z");
            ms.dimensionOrder = "XYCZT";
            break;
        case 9:
            addSeriesMeta("ScanType", "time series spline plane x-z");
            ms.dimensionOrder = "XYTCZ";
            break;
        case 10:
            addSeriesMeta("ScanType", "point mode");
            ms.dimensionOrder = "XYZCT";
            break;
        default:
            addSeriesMeta("ScanType", "x-y-z scan");
            ms.dimensionOrder = "XYZCT";
    }
    ms.indexed = lut != null && lut[series] != null;
    if (isIndexed()) {
        ms.rgb = false;
    }
    if (getSizeC() == 0)
        ms.sizeC = 1;
    if (isRGB()) {
        // shuffle C to front of order string
        ms.dimensionOrder = getDimensionOrder().replaceAll("C", "");
        ms.dimensionOrder = getDimensionOrder().replaceAll("XY", "XYC");
    }
    if (getEffectiveSizeC() == 0) {
        ms.imageCount = getSizeZ() * getSizeT();
    } else {
        ms.imageCount = getSizeZ() * getSizeT() * getEffectiveSizeC();
    }
    if (getImageCount() != ifds.size()) {
        int diff = getImageCount() - ifds.size();
        ms.imageCount = ifds.size();
        if (diff % getSizeZ() == 0) {
            ms.sizeT -= (diff / getSizeZ());
        } else if (diff % getSizeT() == 0) {
            ms.sizeZ -= (diff / getSizeT());
        } else if (getSizeZ() > 1) {
            ms.sizeZ = ifds.size();
            ms.sizeT = 1;
        } else if (getSizeT() > 1) {
            ms.sizeT = ifds.size();
            ms.sizeZ = 1;
        }
    }
    if (getSizeZ() == 0)
        ms.sizeZ = getImageCount();
    if (getSizeT() == 0)
        ms.sizeT = getImageCount() / getSizeZ();
    long channelColorsOffset = 0;
    long timeStampOffset = 0;
    long eventListOffset = 0;
    long scanInformationOffset = 0;
    long channelWavelengthOffset = 0;
    long applicationTagOffset = 0;
    channelColor = new Color[getSizeC()];
    if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        int spectralScan = ras.readShort();
        if (spectralScan != 1) {
            addSeriesMeta("SpectralScan", "no spectral scan");
        } else
            addSeriesMeta("SpectralScan", "acquired with spectral scan");
        int type = ras.readInt();
        switch(type) {
            case 1:
                addSeriesMeta("DataType2", "calculated data");
                break;
            case 2:
                addSeriesMeta("DataType2", "animation");
                break;
            default:
                addSeriesMeta("DataType2", "original scan data");
        }
        long[] overlayOffsets = new long[9];
        String[] overlayKeys = new String[] { "VectorOverlay", "InputLut", "OutputLut", "ROI", "BleachROI", "MeanOfRoisOverlay", "TopoIsolineOverlay", "TopoProfileOverlay", "LinescanOverlay" };
        overlayOffsets[0] = ras.readInt();
        overlayOffsets[1] = ras.readInt();
        overlayOffsets[2] = ras.readInt();
        channelColorsOffset = ras.readInt();
        addSeriesMeta("TimeInterval", ras.readDouble());
        ras.skipBytes(4);
        scanInformationOffset = ras.readInt();
        applicationTagOffset = ras.readInt();
        timeStampOffset = ras.readInt();
        eventListOffset = ras.readInt();
        overlayOffsets[3] = ras.readInt();
        overlayOffsets[4] = ras.readInt();
        ras.skipBytes(4);
        addSeriesMeta("DisplayAspectX", ras.readDouble());
        addSeriesMeta("DisplayAspectY", ras.readDouble());
        addSeriesMeta("DisplayAspectZ", ras.readDouble());
        addSeriesMeta("DisplayAspectTime", ras.readDouble());
        overlayOffsets[5] = ras.readInt();
        overlayOffsets[6] = ras.readInt();
        overlayOffsets[7] = ras.readInt();
        overlayOffsets[8] = ras.readInt();
        if (getMetadataOptions().getMetadataLevel() != MetadataLevel.NO_OVERLAYS) {
            for (int i = 0; i < overlayOffsets.length; i++) {
                parseOverlays(series, overlayOffsets[i], overlayKeys[i], store);
            }
        }
        addSeriesMeta("ToolbarFlags", ras.readInt());
        channelWavelengthOffset = ras.readInt();
        ras.skipBytes(64);
    } else
        ras.skipBytes(182);
    if (getSizeC() > 1) {
        if (!splitPlanes)
            splitPlanes = isRGB();
        ms.rgb = false;
        if (splitPlanes)
            ms.imageCount *= getSizeC();
    }
    // NB: the Zeiss LSM 5.5 specification indicates that there should be
    // 15 32-bit integers here; however, there are actually 16 32-bit
    // integers before the tile position offset.
    // We have confirmed with Zeiss that this is correct, and the 6.0
    // specification was updated to contain the correct information.
    // rotations and phases may be reversed
    // we only have examples where both values are equal
    rotations = ras.readInt();
    phases = ras.readInt();
    illuminations = ras.readInt();
    if (rotations > 1) {
        ms.moduloZ.step = ms.sizeZ;
        ms.moduloZ.end = ms.sizeZ * (rotations - 1);
        ms.moduloZ.type = FormatTools.ROTATION;
        ms.sizeZ *= rotations;
    }
    if (illuminations > 1) {
        ms.moduloC.step = ms.sizeC;
        ms.moduloC.end = ms.sizeC * (illuminations - 1);
        ms.moduloC.type = FormatTools.ILLUMINATION;
        ms.moduloC.parentType = FormatTools.CHANNEL;
        ms.sizeC *= illuminations;
    }
    if (phases > 1) {
        ms.moduloT.step = ms.sizeT;
        ms.moduloT.end = ms.sizeT * (phases - 1);
        ms.moduloT.type = FormatTools.PHASE;
        ms.sizeT *= phases;
    }
    for (int c = 0; c < getEffectiveSizeC(); c++) {
        String lsid = MetadataTools.createLSID("Channel", series, c);
        store.setChannelID(lsid, series, c);
    }
    if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        ras.skipBytes(52);
        int tilePositionOffset = ras.readInt();
        ras.skipBytes(36);
        int positionOffset = ras.readInt();
        // read referenced structures
        addSeriesMeta("DimensionZ", getSizeZ());
        addSeriesMeta("DimensionChannels", getSizeC());
        addSeriesMeta("DimensionM", dimensionM);
        addSeriesMeta("DimensionP", dimensionP);
        if (lsmFilenames.length == 1) {
            xCoordinates.clear();
            yCoordinates.clear();
            zCoordinates.clear();
        }
        if (positionOffset != 0) {
            in.seek(positionOffset);
            int nPositions = in.readInt();
            for (int i = 0; i < nPositions; i++) {
                double xPos = originX + in.readDouble() * 1000000;
                double yPos = originY + in.readDouble() * 1000000;
                double zPos = originZ + in.readDouble() * 1000000;
                xCoordinates.add(xPos);
                yCoordinates.add(yPos);
                zCoordinates.add(zPos);
                addGlobalMetaList("X position for position", xPos);
                addGlobalMetaList("Y position for position", yPos);
                addGlobalMetaList("Z position for position", zPos);
            }
        }
        if (tilePositionOffset != 0) {
            in.seek(tilePositionOffset);
            int nTiles = in.readInt();
            for (int i = 0; i < nTiles; i++) {
                double xPos = originX + in.readDouble() * 1000000;
                double yPos = originY + in.readDouble() * 1000000;
                double zPos = originZ + in.readDouble() * 1000000;
                if (xCoordinates.size() > i) {
                    xPos += xCoordinates.get(i);
                    xCoordinates.set(i, xPos);
                } else if (xCoordinates.size() == i) {
                    xCoordinates.add(xPos);
                }
                if (yCoordinates.size() > i) {
                    yPos += yCoordinates.get(i);
                    yCoordinates.set(i, yPos);
                } else if (yCoordinates.size() == i) {
                    yCoordinates.add(yPos);
                }
                if (zCoordinates.size() > i) {
                    zPos += zCoordinates.get(i);
                    zCoordinates.set(i, zPos);
                } else if (zCoordinates.size() == i) {
                    zCoordinates.add(zPos);
                }
                addGlobalMetaList("X position for position", xPos);
                addGlobalMetaList("Y position for position", yPos);
                addGlobalMetaList("Z position for position", zPos);
            }
        }
        if (channelColorsOffset != 0) {
            in.seek(channelColorsOffset + 12);
            int colorsOffset = in.readInt();
            int namesOffset = in.readInt();
            if (colorsOffset > 0) {
                in.seek(channelColorsOffset + colorsOffset);
                lut[getSeries()] = new byte[getSizeC() * 3][256];
                core.get(getSeries()).indexed = true;
                for (int i = 0; i < getSizeC(); i++) {
                    if (i >= channelColor.length) {
                        continue;
                    }
                    int color = in.readInt();
                    int red = color & 0xff;
                    int green = (color & 0xff00) >> 8;
                    int blue = (color & 0xff0000) >> 16;
                    // otherwise set the color to white, as this will display better
                    if (red == 0 && green == 0 & blue == 0) {
                        if (i > 0) {
                            red = channelColor[i - 1].getRed();
                            green = channelColor[i - 1].getGreen();
                            blue = channelColor[i - 1].getBlue();
                        } else {
                            red = 255;
                            green = 255;
                            blue = 255;
                        }
                    }
                    channelColor[i] = new Color(red, green, blue, 255);
                    for (int j = 0; j < 256; j++) {
                        lut[getSeries()][i * 3][j] = (byte) ((red / 255.0) * j);
                        lut[getSeries()][i * 3 + 1][j] = (byte) ((green / 255.0) * j);
                        lut[getSeries()][i * 3 + 2][j] = (byte) ((blue / 255.0) * j);
                    }
                }
            }
            if (namesOffset > 0) {
                in.seek(channelColorsOffset + namesOffset);
                channelNames[series] = new String[getSizeC()];
                for (int i = 0; i < getSizeC(); i++) {
                    if (in.getFilePointer() >= in.length() - 1)
                        break;
                    // we want to read until we find a null char
                    int length = in.readInt();
                    String name = in.readString(length);
                    while ((name.length() > 0) && (name.codePointAt(name.length() - 1) == 0)) {
                        name = name.substring(0, name.length() - 1);
                    }
                    if (name.length() <= 128) {
                        addSeriesMetaList("ChannelName", name);
                    }
                    channelNames[series][i] = name;
                }
            }
        }
        if (timeStampOffset != 0) {
            in.seek(timeStampOffset + 4);
            int nStamps = in.readInt();
            for (int i = 0; i < nStamps; i++) {
                double stamp = in.readDouble();
                addSeriesMetaList("TimeStamp", stamp);
                timestamps.add(stamp);
            }
        }
        if (eventListOffset != 0) {
            in.seek(eventListOffset + 4);
            int numEvents = in.readInt();
            in.seek(in.getFilePointer() - 4);
            in.order(!in.isLittleEndian());
            int tmpEvents = in.readInt();
            if (numEvents < 0)
                numEvents = tmpEvents;
            else
                numEvents = (int) Math.min(numEvents, tmpEvents);
            in.order(!in.isLittleEndian());
            if (numEvents > 65535)
                numEvents = 0;
            for (int i = 0; i < numEvents; i++) {
                if (in.getFilePointer() + 16 <= in.length()) {
                    int size = in.readInt();
                    double eventTime = in.readDouble();
                    int eventType = in.readInt();
                    addSeriesMetaList("Event Time", eventTime);
                    addSeriesMetaList("Event Type", eventType);
                    long fp = in.getFilePointer();
                    int len = size - 16;
                    if (len > 65536)
                        len = 65536;
                    if (len < 0)
                        len = 0;
                    addSeriesMetaList("Event Description", in.readString(len));
                    in.seek(fp + size - 16);
                    if (in.getFilePointer() < 0)
                        break;
                }
            }
        }
        if (scanInformationOffset != 0) {
            in.seek(scanInformationOffset);
            nextLaser = nextDetector = 0;
            nextFilter = nextDichroicChannel = nextDichroic = 0;
            nextDetectChannel = nextIllumChannel = 0;
            final List<SubBlock> blocks = new ArrayList<SubBlock>();
            while (in.getFilePointer() < in.length() - 12) {
                if (in.getFilePointer() < 0)
                    break;
                int entry = in.readInt();
                int blockType = in.readInt();
                int dataSize = in.readInt();
                if (blockType == TYPE_SUBBLOCK) {
                    SubBlock block = null;
                    switch(entry) {
                        case SUBBLOCK_RECORDING:
                            block = new Recording();
                            break;
                        case SUBBLOCK_LASER:
                            block = new Laser();
                            break;
                        case SUBBLOCK_TRACK:
                            block = new Track();
                            break;
                        case SUBBLOCK_DETECTION_CHANNEL:
                            block = new DetectionChannel();
                            break;
                        case SUBBLOCK_ILLUMINATION_CHANNEL:
                            block = new IlluminationChannel();
                            break;
                        case SUBBLOCK_BEAM_SPLITTER:
                            block = new BeamSplitter();
                            break;
                        case SUBBLOCK_DATA_CHANNEL:
                            block = new DataChannel();
                            break;
                        case SUBBLOCK_TIMER:
                            block = new Timer();
                            break;
                        case SUBBLOCK_MARKER:
                            block = new Marker();
                            break;
                    }
                    if (block != null) {
                        blocks.add(block);
                    }
                } else if (dataSize + in.getFilePointer() <= in.length() && dataSize > 0) {
                    in.skipBytes(dataSize);
                } else
                    break;
            }
            final List<SubBlock> nonAcquiredBlocks = new ArrayList<SubBlock>();
            SubBlock[] metadataBlocks = blocks.toArray(new SubBlock[0]);
            for (SubBlock block : metadataBlocks) {
                block.addToHashtable();
                if (!block.acquire) {
                    nonAcquiredBlocks.add(block);
                    blocks.remove(block);
                }
            }
            for (int i = 0; i < blocks.size(); i++) {
                SubBlock block = blocks.get(i);
                // a valid DataChannel or IlluminationChannel
                if ((block instanceof IlluminationChannel) && i < blocks.size() - 1) {
                    SubBlock nextBlock = blocks.get(i + 1);
                    if (!(nextBlock instanceof DataChannel) && !(nextBlock instanceof IlluminationChannel)) {
                        ((IlluminationChannel) block).wavelength = null;
                    }
                } else // a valid Track or DetectionChannel
                if ((block instanceof DetectionChannel) && i > 0) {
                    SubBlock prevBlock = blocks.get(i - 1);
                    if (!(prevBlock instanceof Track) && !(prevBlock instanceof DetectionChannel)) {
                        block.acquire = false;
                        nonAcquiredBlocks.add(block);
                    }
                }
                if (block.acquire)
                    populateMetadataStore(block, store, series);
            }
            for (SubBlock block : nonAcquiredBlocks) {
                populateMetadataStore(block, store, series);
            }
        }
        if (applicationTagOffset != 0) {
            in.seek(applicationTagOffset);
            parseApplicationTags();
        }
    }
    imageNames.add(imageName);
    if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        if (userName != null) {
            String experimenterID = MetadataTools.createLSID("Experimenter", 0);
            store.setExperimenterID(experimenterID, 0);
            store.setExperimenterUserName(userName, 0);
        }
        Length pixX = FormatTools.getPhysicalSizeX(pixelSizeX);
        Length pixY = FormatTools.getPhysicalSizeY(pixelSizeY);
        Length pixZ = FormatTools.getPhysicalSizeZ(pixelSizeZ);
        if (pixX != null) {
            store.setPixelsPhysicalSizeX(pixX, series);
        }
        if (pixY != null) {
            store.setPixelsPhysicalSizeY(pixY, series);
        }
        if (pixZ != null) {
            store.setPixelsPhysicalSizeZ(pixZ, series);
        }
        for (int i = 0; i < getSizeC(); i++) {
            store.setChannelColor(channelColor[i], series, i);
            if (channelNames[series] != null) {
                store.setChannelName(channelNames[series][i], series, i);
            }
        }
        int stampIndex = 0;
        for (int i = 0; i < series; i++) {
            stampIndex += core.get(i).sizeT;
        }
        double firstStamp = 0;
        if (timestamps.size() > 0 && stampIndex < timestamps.size()) {
            firstStamp = timestamps.get(stampIndex).doubleValue();
        }
        for (int i = 0; i < getImageCount(); i++) {
            int[] zct = FormatTools.getZCTCoords(this, i);
            if (getSizeT() > 1 && zct[2] < timestamps.size() - stampIndex) {
                double thisStamp = timestamps.get(stampIndex + zct[2]).doubleValue();
                store.setPlaneDeltaT(new Time(thisStamp - firstStamp, UNITS.SECOND), series, i);
            }
            if (xCoordinates.size() > series) {
                final Double xCoord = xCoordinates.get(series);
                final Double yCoord = yCoordinates.get(series);
                final Double zCoord = zCoordinates.get(series);
                if (xCoord == null) {
                    store.setPlanePositionX(null, series, i);
                } else {
                    final Length x = new Length(xCoord, UNITS.REFERENCEFRAME);
                    store.setPlanePositionX(x, series, i);
                }
                if (yCoord == null) {
                    store.setPlanePositionY(null, series, i);
                } else {
                    final Length y = new Length(yCoord, UNITS.REFERENCEFRAME);
                    store.setPlanePositionY(y, series, i);
                }
                if (zCoord == null) {
                    store.setPlanePositionZ(null, series, i);
                } else {
                    final Length z = new Length(zCoord, UNITS.REFERENCEFRAME);
                    store.setPlanePositionZ(z, series, i);
                }
            }
        }
    }
    ras.close();
}
Also used : IFD(loci.formats.tiff.IFD) ArrayList(java.util.ArrayList) Time(ome.units.quantity.Time) Color(ome.xml.model.primitives.Color) PhotoInterp(loci.formats.tiff.PhotoInterp) CoreMetadata(loci.formats.CoreMetadata) MetadataStore(loci.formats.meta.MetadataStore) Length(ome.units.quantity.Length) IFDList(loci.formats.tiff.IFDList) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream)

Example 77 with IFD

use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.

the class ZeissLSMReader method initFile.

// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected void initFile(String id) throws FormatException, IOException {
    super.initFile(id);
    if (checkSuffix(id, MDB_SUFFIX)) {
        lsmFilenames = parseMDB(id);
    } else
        lsmFilenames = new String[] { id };
    if (lsmFilenames == null || lsmFilenames.length == 0) {
        throw new FormatException("LSM files were not found.");
    }
    totalROIs = 0;
    timestamps = new ArrayList<Double>();
    imageNames = new ArrayList<String>();
    xCoordinates = new ArrayList<Double>();
    yCoordinates = new ArrayList<Double>();
    zCoordinates = new ArrayList<Double>();
    seriesCounts = new HashMap<String, Integer>();
    int seriesCount = 0;
    final List<String> validFiles = new ArrayList<String>();
    for (String filename : lsmFilenames) {
        try {
            int extraSeries = getExtraSeries(filename);
            seriesCounts.put(filename, extraSeries);
            seriesCount += extraSeries;
            validFiles.add(filename);
        } catch (IOException e) {
            LOGGER.debug("Failed to parse " + filename, e);
        }
    }
    lsmFilenames = validFiles.toArray(new String[validFiles.size()]);
    core.clear();
    for (int c = 0; c < seriesCount; c++) {
        CoreMetadata ms = new CoreMetadata();
        core.add(ms);
    }
    channelNames = new String[seriesCount][];
    ifdsList = new ArrayList<IFDList>();
    for (int series = 0; series < seriesCount; series++) {
        ifdsList.add(null);
    }
    int realSeries = 0;
    for (int i = 0; i < lsmFilenames.length; i++) {
        RandomAccessInputStream stream = null;
        try {
            stream = new RandomAccessInputStream(lsmFilenames[i], 16);
            int count = seriesCounts.get(lsmFilenames[i]);
            TiffParser tp = new TiffParser(stream);
            Boolean littleEndian = tp.checkHeader();
            long[] ifdOffsets = tp.getIFDOffsets();
            int ifdsPerSeries = (ifdOffsets.length / 2) / count;
            int offset = 0;
            Object zeissTag = null;
            for (int s = 0; s < count; s++, realSeries++) {
                CoreMetadata ms = core.get(realSeries);
                ms.littleEndian = littleEndian;
                IFDList ifds = new IFDList();
                while (ifds.size() < ifdsPerSeries) {
                    tp.setDoCaching(offset == 0);
                    IFD ifd = tp.getIFD(ifdOffsets[offset]);
                    if (offset == 0)
                        zeissTag = ifd.get(ZEISS_ID);
                    if (offset > 0 && ifds.isEmpty()) {
                        ifd.putIFDValue(ZEISS_ID, zeissTag);
                    }
                    ifds.add(ifd);
                    if (zeissTag != null)
                        offset += 2;
                    else
                        offset++;
                }
                for (IFD ifd : ifds) {
                    tp.fillInIFD(ifd);
                }
                ifdsList.set(realSeries, ifds);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (stream != null)
                stream.close();
        }
    }
    MetadataStore store = makeFilterMetadata();
    lut = new byte[ifdsList.size()][][];
    long[] previousStripOffsets = null;
    for (int series = 0; series < ifdsList.size(); series++) {
        // the previous series
        if (series > 0 && getSizeT() > 1) {
            previousStripOffsets = null;
        }
        IFDList ifds = ifdsList.get(series);
        for (IFD ifd : ifds) {
            // than LZW compression is used
            if (ifd.getCompression() != TiffCompression.LZW) {
                ifd.putIFDValue(IFD.PREDICTOR, 1);
            }
        }
        // fix the offsets for > 4 GB files
        RandomAccessInputStream s = null;
        try {
            s = new RandomAccessInputStream(getLSMFileFromSeries(series));
            for (int i = 0; i < ifds.size(); i++) {
                long[] stripOffsets = ifds.get(i).getStripOffsets();
                if (stripOffsets == null || (i != 0 && previousStripOffsets == null)) {
                    throw new FormatException("Strip offsets are missing; this is an invalid file.");
                } else if (i == 0 && previousStripOffsets == null) {
                    previousStripOffsets = stripOffsets;
                    continue;
                }
                boolean neededAdjustment = false;
                for (int j = 0; j < stripOffsets.length; j++) {
                    if (j >= previousStripOffsets.length)
                        break;
                    if (stripOffsets[j] < previousStripOffsets[j]) {
                        stripOffsets[j] = (previousStripOffsets[j] & ~0xffffffffL) | (stripOffsets[j] & 0xffffffffL);
                        if (stripOffsets[j] < previousStripOffsets[j]) {
                            long newOffset = stripOffsets[j] + 0x100000000L;
                            if (newOffset < s.length()) {
                                stripOffsets[j] = newOffset;
                            }
                        }
                        neededAdjustment = true;
                    }
                    if (neededAdjustment) {
                        ifds.get(i).putIFDValue(IFD.STRIP_OFFSETS, stripOffsets);
                    }
                }
                previousStripOffsets = stripOffsets;
            }
            initMetadata(series);
        } catch (IOException e) {
            throw e;
        } finally {
            if (s != null)
                s.close();
        }
    }
    for (int i = 0; i < getSeriesCount(); i++) {
        CoreMetadata ms = core.get(i);
        ms.imageCount = ms.sizeZ * ms.sizeC * ms.sizeT;
    }
    MetadataTools.populatePixels(store, this, true);
    for (int series = 0; series < ifdsList.size(); series++) {
        setSeries(series);
        if (series < imageNames.size()) {
            store.setImageName(imageNames.get(series), series);
        }
        if (acquiredDate.containsKey(series)) {
            store.setImageAcquisitionDate(new Timestamp(acquiredDate.get(series)), series);
        }
    }
    setSeries(0);
}
Also used : IFD(loci.formats.tiff.IFD) ArrayList(java.util.ArrayList) IOException(java.io.IOException) CoreMetadata(loci.formats.CoreMetadata) Timestamp(ome.xml.model.primitives.Timestamp) FormatException(loci.formats.FormatException) MetadataStore(loci.formats.meta.MetadataStore) IFDList(loci.formats.tiff.IFDList) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream)

Example 78 with IFD

use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.

the class ScanrReader method isThisType.

/* @see loci.formats.IFormatReader#isThisType(RandomAccessInputStream) */
@Override
public boolean isThisType(RandomAccessInputStream stream) throws IOException {
    TiffParser p = new TiffParser(stream);
    IFD ifd = p.getFirstIFD();
    if (ifd == null)
        return false;
    Object s = ifd.getIFDValue(IFD.SOFTWARE);
    if (s == null)
        return false;
    String software = s instanceof String[] ? ((String[]) s)[0] : s.toString();
    return software.trim().equals("National Instruments IMAQ");
}
Also used : IFD(loci.formats.tiff.IFD) TiffParser(loci.formats.tiff.TiffParser)

Example 79 with IFD

use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.

the class SVSReader method initStandardMetadata.

// -- Internal BaseTiffReader API methods --
/* @see loci.formats.BaseTiffReader#initStandardMetadata() */
@Override
protected void initStandardMetadata() throws FormatException, IOException {
    super.initStandardMetadata();
    ifds = tiffParser.getIFDs();
    int seriesCount = ifds.size();
    pixelSize = new Length[seriesCount];
    comments = new String[seriesCount];
    core.clear();
    for (int i = 0; i < seriesCount; i++) {
        core.add(new CoreMetadata());
    }
    for (int i = 0; i < seriesCount; i++) {
        setSeries(i);
        int index = getIFDIndex(i);
        tiffParser.fillInIFD(ifds.get(index));
        if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
            String comment = ifds.get(index).getComment();
            if (comment == null) {
                continue;
            }
            String[] lines = comment.split("\n");
            String[] tokens;
            String key, value;
            for (String line : lines) {
                tokens = line.split("[|]");
                for (String t : tokens) {
                    if (t.indexOf('=') == -1) {
                        addGlobalMeta("Comment", t);
                        comments[i] = t;
                    } else {
                        key = t.substring(0, t.indexOf('=')).trim();
                        value = t.substring(t.indexOf('=') + 1).trim();
                        addSeriesMeta(key, value);
                        if (key.equals("MPP")) {
                            pixelSize[i] = FormatTools.getPhysicalSizeX(DataTools.parseDouble(value));
                        } else if (key.equals("Date")) {
                            date = value;
                        } else if (key.equals("Time")) {
                            time = value;
                        } else if (key.equals("Emission Wavelength")) {
                            emissionWavelength = DataTools.parseDouble(value);
                        } else if (key.equals("Excitation Wavelength")) {
                            excitationWavelength = DataTools.parseDouble(value);
                        } else if (key.equals("Exposure Time")) {
                            exposureTime = DataTools.parseDouble(value);
                        } else if (key.equals("Exposure Scale")) {
                            exposureScale = DataTools.parseDouble(value);
                        } else if (key.equals("AppMag")) {
                            magnification = DataTools.parseDouble(value);
                        }
                    }
                }
            }
        }
    }
    setSeries(0);
    for (int s = 0; s < seriesCount; s++) {
        CoreMetadata ms = core.get(s);
        if (s == 0 && getSeriesCount() > 2) {
            ms.resolutionCount = getSeriesCount() - 2;
        }
        IFD ifd = ifds.get(getIFDIndex(s));
        PhotoInterp p = ifd.getPhotometricInterpretation();
        int samples = ifd.getSamplesPerPixel();
        ms.rgb = samples > 1 || p == PhotoInterp.RGB;
        ms.sizeX = (int) ifd.getImageWidth();
        ms.sizeY = (int) ifd.getImageLength();
        ms.sizeZ = 1;
        ms.sizeT = 1;
        ms.sizeC = ms.rgb ? samples : 1;
        ms.littleEndian = ifd.isLittleEndian();
        ms.indexed = p == PhotoInterp.RGB_PALETTE && (get8BitLookupTable() != null || get16BitLookupTable() != null);
        ms.imageCount = 1;
        ms.pixelType = ifd.getPixelType();
        ms.metadataComplete = true;
        ms.interleaved = false;
        ms.falseColor = false;
        ms.dimensionOrder = "XYCZT";
        ms.thumbnail = s != 0;
    }
    reorderResolutions();
}
Also used : IFD(loci.formats.tiff.IFD) PhotoInterp(loci.formats.tiff.PhotoInterp) CoreMetadata(loci.formats.CoreMetadata)

Example 80 with IFD

use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.

the class SlidebookTiffReader method getTimestamp.

// -- Helper methods --
private String getTimestamp(String path) throws FormatException, IOException {
    RandomAccessInputStream s = new RandomAccessInputStream(path);
    TiffParser parser = new TiffParser(s);
    IFD ifd = parser.getFirstIFD();
    Object date = ifd.getIFDValue(IFD.DATE_TIME);
    s.close();
    return date == null ? null : date.toString();
}
Also used : IFD(loci.formats.tiff.IFD) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream)

Aggregations

IFD (loci.formats.tiff.IFD)121 TiffParser (loci.formats.tiff.TiffParser)74 RandomAccessInputStream (loci.common.RandomAccessInputStream)51 CoreMetadata (loci.formats.CoreMetadata)33 FormatException (loci.formats.FormatException)32 MetadataStore (loci.formats.meta.MetadataStore)21 IFDList (loci.formats.tiff.IFDList)21 PhotoInterp (loci.formats.tiff.PhotoInterp)18 IOException (java.io.IOException)17 Location (loci.common.Location)15 ArrayList (java.util.ArrayList)14 Timestamp (ome.xml.model.primitives.Timestamp)11 Length (ome.units.quantity.Length)10 Time (ome.units.quantity.Time)8 TiffIFDEntry (loci.formats.tiff.TiffIFDEntry)7 TiffRational (loci.formats.tiff.TiffRational)6 File (java.io.File)5 TiffReader (loci.formats.in.TiffReader)5 NonNegativeInteger (ome.xml.model.primitives.NonNegativeInteger)5 PositiveInteger (ome.xml.model.primitives.PositiveInteger)5