//
// TiffReader.java
//

/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-2006 Melissa Linkert, Curtis Rueden, Chris Allan
and Eric Kjellman.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library 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 Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package loci.formats.in;

import java.io.IOException;
import java.util.StringTokenizer;
import loci.formats.*;

/**
 * TiffReader is the file format reader for TIFF files.
 *
 * @author Curtis Rueden ctrueden at wisc.edu
 * @author Melissa Linkert linkert at cs.wisc.edu
 */

public class TiffReader extends BaseTiffReader {

  /** Number of optical sections in the file */
  private int sizeZ = 1;

  // -- Constructor --

  /** Constructs a new Tiff reader. */
  public TiffReader() {
    super("Tagged Image File Format", new String[] {"tif", "tiff"});
  }

  // -- FormatReader API methods --

  /**
   * Allows the client to specify whether or not to separate channels.
   * By default, channels are left unseparated; thus if we encounter an RGB
   * image plane, it will be left as RGB and not split into 3 separate planes.
   */
  public void setSeparated(boolean separate) {
    separated = separate;
    super.setSeparated(separate);
  }

  /** Get the size of the Z dimension. */
  public int getSizeZ(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return sizeZ;
  }

  // -- Internal BaseTiffForm API methods --

  /** Parses standard metadata. */
  protected void initStandardMetadata() {
    super.initStandardMetadata();
    String comment = (String) metadata.get("Comment");

    // check for ImageJ-style TIFF comment
    boolean ij = comment != null && comment.startsWith("ImageJ=");
    if (ij) {
      int nl = comment.indexOf("\n");
      put("ImageJ", nl < 0 ? comment.substring(7) : comment.substring(7, nl));
      metadata.remove("Comment");
    }

    // check for Improvision-style TIFF comment
    boolean iv = comment != null && comment.startsWith("[Improvision Data]\n");
    put("Improvision", iv ? "yes" : "no");
    if (iv) {
      // 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);
        String value = line.substring(equals + 1);
        metadata.put(key, value);
      }
      metadata.remove("Comment");
    }
  }

  /** Parses OME-XML metadata. */
  protected void initMetadataStore() {
    // check for OME-XML in TIFF comment (OME-TIFF format)
    // we need an extra check to make sure that any XML we find is indeed
    // OME-XML (and not some other XML variant)
    MetadataStore store = new DummyMetadataStore();
    try {
      store = getMetadataStore(currentId);
    }
    catch (Exception e) { }

    String comment = (String) metadata.get("Comment");
    if (store instanceof OMEXMLMetadataStore
      && comment != null && comment.indexOf("ome.xsd") >= 0)
    {
      OMEXMLMetadataStore xmlStore = (OMEXMLMetadataStore) store;
      xmlStore.createRoot(comment);
    }
    else super.initMetadataStore();
  }

  /**
   * Allows a class which is delegating parsing responsibility to
   * <code>TiffReader</code> the ability to affect the <code>sizeZ</code> value
   * that is inserted into the metadata store.
   * @param sizeZ the number of optical sections to use when making a call to
   * {@link MetadataStore#setPixels()}.
   */
  void setInitialSizeZ(int sizeZ) {
    this.sizeZ = sizeZ;
  }

  // -- Main method --

  public static void main(String[] args) throws FormatException, IOException {
    new TiffReader().testRead(args);
  }

}

@@ -1261,16 +1261,17 @@
 the file
+.
  */%0A  pr
@@ -1499,530 +1499,616 @@
  /**
-%0A   * Allows the client to specify whether or not to separate channels.%0A   * By default, channels are left unseparated; thus if we encounter an RGB%0A   * image plane, it will be left as RGB and not split into 3 separate planes.%0A   */%0A  public void setSeparated(boolean separate) %7B%0A    separated = separate;%0A    super.setSeparated(separate);%0A  %7D%0A%0A  /** Get the
+ Get the size of the Z dimension. */%0A  public int getSizeZ(String id) throws FormatException, IOException %7B%0A    if (!id.equals(currentId)) initFile(id);%0A    return sizeZ;%0A  %7D%0A%0A  // -- Internal TiffReader API methods --%0A%0A  /**%0A   * Allows a class which is delegating parsing responsibility to%0A   * %3Ccode%3ETiffReader%3C/code%3E the ability to affect the %3Ccode%3EsizeZ%3C/code%3E value%0A   * that is inserted into the metadata store.%0A   * @param
  size
- of
+Z
  the 
-Z dimension. */%0A  public int getSizeZ(String id) throws FormatException, IOException %7B%0A    if (!id.equals(currentId)) initFile(id);%0A    return
+number of optical sections to use when making a call to%0A   * %7B@link MetadataStore#setPixels()%7D.%0A   */%0A  protected void setInitialSizeZ(int sizeZ) %7B this.sizeZ =
  sizeZ;
-%0A 
  %7D%0A%0A
@@ -2132,20 +2132,22 @@
 BaseTiff
-Form
+Reader
  API met
@@ -3930,396 +3930,8 @@
  %7D%0A%0A
-  /**%0A   * Allows a class which is delegating parsing responsibility to%0A   * %3Ccode%3ETiffReader%3C/code%3E the ability to affect the %3Ccode%3EsizeZ%3C/code%3E value%0A   * that is inserted into the metadata store.%0A   * @param sizeZ the number of optical sections to use when making a call to%0A   * %7B@link MetadataStore#setPixels()%7D.%0A   */%0A  void setInitialSizeZ(int sizeZ) %7B%0A    this.sizeZ = sizeZ;%0A  %7D%0A%0A
   //

Remove duplicate setSeparated implementation; reorganize code a little.