/* * #%L * OME Bio-Formats package for reading and converting biological file formats. * %% * Copyright (C) 2005 - 2015 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 * <http://www.gnu.org/licenses/gpl-2.0.html>. * #L% */ package loci.formats.in; import java.io.IOException; import java.util.StringTokenizer; import java.util.Vector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import loci.formats.CoreMetadata; import loci.formats.FormatException; import loci.formats.FormatTools; import loci.formats.MetadataTools; import loci.formats.meta.MetadataStore; import loci.formats.tiff.IFD; import loci.formats.tiff.IFDList; import ome.xml.model.primitives.PositiveFloat; import ome.xml.model.primitives.PositiveInteger; import ome.xml.model.primitives.Timestamp; import ome.units.quantity.Length; /** * ImarisTiffReader is the file format reader for * Bitplane Imaris 3 files (TIFF variant). * * @author Melissa Linkert melissa at glencoesoftware.com */ public class ImarisTiffReader extends BaseTiffReader { // -- Constants -- /** Logger for this class. */ private static final Logger LOGGER = LoggerFactory.getLogger(ImarisTiffReader.class); // -- Constructor -- /** Constructs a new Imaris TIFF reader. */ public ImarisTiffReader() { super("Bitplane Imaris 3 (TIFF)", "ims"); suffixSufficient = false; suffixNecessary = true; domains = new String[] {FormatTools.UNKNOWN_DOMAIN}; } // -- Internal FormatReader API methods -- /* @see loci.formats.FormatReader#initFile(String) */ @Override protected void initFile(String id) throws FormatException, IOException { super.initFile(id); // hack up the IFDs // // Imaris TIFFs store a thumbnail in the first IFD; each of the remaining // IFDs defines a stack of tiled planes. // MinimalTiffReader.initFile(String) removes thumbnail IFDs. LOGGER.info("Verifying IFD sanity"); IFDList tmp = new IFDList(); for (IFD ifd : ifds) { long[] byteCounts = ifd.getStripByteCounts(); long[] offsets = ifd.getStripOffsets(); for (int i=0; i<byteCounts.length; i++) { IFD t = new IFD(ifd); t.putIFDValue(IFD.TILE_BYTE_COUNTS, byteCounts[i]); t.putIFDValue(IFD.TILE_OFFSETS, offsets[i]); tmp.add(t); } } String comment = ifds.get(0).getComment(); LOGGER.info("Populating metadata"); CoreMetadata m = core.get(0); m.sizeC = ifds.size(); m.sizeZ = tmp.size() / getSizeC(); m.sizeT = 1; m.sizeX = (int) ifds.get(0).getImageWidth(); m.sizeY = (int) ifds.get(0).getImageLength(); ifds = tmp; m.imageCount = getSizeC() * getSizeZ(); m.dimensionOrder = "XYZCT"; m.interleaved = false; m.rgb = getImageCount() != getSizeZ() * getSizeC() * getSizeT(); m.pixelType = ifds.get(0).getPixelType(); LOGGER.info("Parsing comment"); // likely an INI-style comment, although we can't be sure MetadataStore store = makeFilterMetadata(); MetadataTools.populatePixels(store, this); if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) { String description = null, creationDate = null; Vector<Double> emWave = new Vector<Double>(); Vector<Double> exWave = new Vector<Double>(); Vector<String> channelNames = new Vector<String>(); if (comment != null && comment.startsWith("[")) { // parse key/value pairs StringTokenizer st = new StringTokenizer(comment, "\n"); while (st.hasMoreTokens()) { String line = st.nextToken(); int equals = line.indexOf("="); if (equals < 0) continue; String key = line.substring(0, equals).trim(); String value = line.substring(equals + 1).trim(); addGlobalMeta(key, value); if (key.equals("Description")) { description = value; } else if (key.equals("LSMEmissionWavelength") && !value.equals("0")) { emWave.add(new Double(value)); } else if (key.equals("LSMExcitationWavelength") && !value.equals("0")) { exWave.add(new Double(value)); } else if (key.equals("Name") && !currentId.endsWith(value)) { channelNames.add(value); } else if (key.equals("RecordingDate")) { value = value.replaceAll(" ", "T"); creationDate = value.substring(0, value.indexOf(".")); } } metadata.remove("Comment"); } // populate Image data store.setImageDescription(description, 0); if (creationDate != null) { store.setImageAcquisitionDate(new Timestamp(creationDate), 0); } // populate LogicalChannel data for (int i=0; i<emWave.size(); i++) { Length emission = FormatTools.getEmissionWavelength(emWave.get(i)); Length excitation = FormatTools.getExcitationWavelength(exWave.get(i)); if (emission != null) { store.setChannelEmissionWavelength(emission, 0, i); } if (excitation != null) { store.setChannelExcitationWavelength(excitation, 0, i); } store.setChannelName(channelNames.get(i), 0, i); } } } }