  protected void initFile(String id) throws FormatException, IOException {
    if (debug) debug("ND2Reader.initFile(" + id + ")");
    if (noJ2k) throw new FormatException(NO_J2K_MSG);
    super.initFile(id);
    in = new RandomAccessStream(id);
    if (in.read() == -38 && in.read() == -50) {
      isJPEG = false;
      in.seek(0);
      in.order(true);
      byte[] b = new byte[1024 * 1024];
      while (in.getFilePointer() < in.length()) {
        if (in.read() == -38 && in.read() == -50 && in.read() == -66 &&
          in.read() == 10)
        {
          int len = in.readInt() + in.readInt();
          if (len > b.length) {
            int size = b.length + b.length;
            if (size < len) size = len;
            b = new byte[size];
          }
          in.skipBytes(4);
          if (debug) {
            debug("Reading chunk of size " + len +
              " at position " + in.getFilePointer());
          }
          in.readFully(b, 0, len);
          if (len >= 12 && b[0] == 'I' && b[1] == 'm' && b[2] == 'a' &&
            b[3] == 'g' && b[4] == 'e' && b[5] == 'D' && b[6] == 'a' &&
            b[7] == 't' && b[8] == 'a' && b[9] == 'S' && b[10] == 'e' &&
            b[11] == 'q') 
          {
            StringBuffer sb = new StringBuffer();
            int pt = 13;
            while (b[pt] != '!') {
              sb.append((char) b[pt]);
              pt++;
            }
            int ndx = Integer.parseInt(sb.toString());
            if (core.sizeC[0] == 0) {
              core.sizeC[0] = len / (core.sizeX[0] * core.sizeY[0] *
                FormatTools.getBytesPerPixel(core.pixelType[0]));
            }
            offsets[0][ndx] = in.getFilePointer() - len + sb.length() + 21;
            while (offsets[0][ndx] - in.getFilePointer() +
              len - 14 - sb.length() < 8)
            {
              offsets[0][ndx]++;
            }
          }
          else if (len >= 5 && b[0] == 'I' && b[1] == 'm' && b[2] == 'a' &&
            b[3] == 'g' && b[4] == 'e') 
          {
            ND2Handler handler = new ND2Handler();
            int off = 0;
            for (int i=0; i<len; i++) {
              char c = (char) b[i];
              if (off == 0 && c == '!') off = i + 1;
              if (Character.isISOControl(c) || !Character.isDefined(c)) {
                b[i] = (byte) ' ';
              }
            }
            if (len - off >= 5 && b[off] == '<' && b[off + 1] == '?' &&
              b[off + 2] == 'x' && b[off + 3] == 'm' &&
              b[off + 4] == 'l') 
            {
              ByteArrayInputStream s =
                new ByteArrayInputStream(b, off, len - off);
              try {
                SAXParser parser = SAX_FACTORY.newSAXParser();
                parser.parse(s, handler);
              }
              catch (ParserConfigurationException exc) {
                throw new FormatException(exc);
              }
              catch (SAXException exc) {
                throw new FormatException(exc);
              }
            }
          }
          if (core.imageCount[0] > 0 && offsets == null) {
            offsets = new long[1][core.imageCount[0]];
          }
          if (in.getFilePointer() < in.length() - 1) {
            if (in.read() != -38) in.skipBytes(15);
            else in.seek(in.getFilePointer() - 1);
          }
        }
      }
      if (core.sizeC[0] == 0) core.sizeC[0] = 1;
      core.currentOrder[0] = "XYCZT";
      core.rgb[0] = core.sizeC[0] > 1;
      if (core.sizeC[0] > 1 && adjustImageCount) {
        core.imageCount[0] /= 3;
        core.sizeT[0] /= 3;
      }
      core.littleEndian[0] = true;
      core.interleaved[0] = true;
      core.indexed[0] = false;
      core.falseColor[0] = false;
      core.metadataComplete[0] = true;
      MetadataStore store = getMetadataStore();
      store.setImage(currentId, null, null, null);
      FormatTools.populatePixels(store, this);
      for (int i=0; i<core.sizeC[0]; i++) {
        store.setLogicalChannel(i, null, null, null, null, null, null, null,
          null, null, null, null, null, null, null, null, null, null, null,
          null, null, null, null, null, null);
      }
      return;
    }
    else in.seek(0);
    isJPEG = true;
    status("Calculating image offsets");
    Vector vs = new Vector();
    long pos = in.getFilePointer();
    boolean lastBoxFound = false;
    int length = 0;
    int box = 0;
    while (!lastBoxFound) {
      pos = in.getFilePointer();
      length = in.readInt();
      if (pos + length >= in.length() || length == 0) lastBoxFound = true;
      box = in.readInt();
      pos = in.getFilePointer();
      length -= 8;
      if (box == 0x6a703263) {
        vs.add(new Long(in.getFilePointer()));
      }
      if (!lastBoxFound) in.seek(pos + length);
    }
    status("Finding XML metadata");
    in.seek(((Long) vs.get(vs.size() - 1)).longValue());
    boolean found = false;
    long off = -1;
    byte[] buf = new byte[2048];
    while (!found && in.getFilePointer() < in.length()) {
      int read = 0;
      if (in.getFilePointer() == ((Long) vs.get(vs.size() - 1)).longValue()) {
        read = in.read(buf);
      }
      else {
        System.arraycopy(buf, buf.length - 10, buf, 0, 10);
        read = in.read(buf, 10, buf.length - 10);
      }
      if (read == buf.length) read -= 10;
      for (int i=0; i<read+9; i++) {
        if (buf[i] == (byte) 0xff && buf[i+1] == (byte) 0xd9) {
          found = true;
          off = in.getFilePointer() - (read + 10) + i;
          i = buf.length;
          break;
        }
      }
    }
    buf = null;
    status("Parsing XML");
    if (off > 0 && off < in.length() - 5) {
      in.seek(off + 5);
      byte[] b = new byte[(int) (in.length() - off - 5)];
      in.readFully(b);
      String xml = new String(b);
      xml = xml.substring(0, xml.lastIndexOf("</MetadataSeq>") + 14);
      xml = xml.replaceAll("<!--*-->", "");
      StringTokenizer st = new StringTokenizer(xml, "\r\n");
      while (st.hasMoreTokens()) {
        String token = st.nextToken().trim();
        if (token.indexOf("<") != -1) {
          String prefix = token.substring(1, token.indexOf(">")).trim();
          token = token.substring(token.indexOf(">") + 1);
          while (token.indexOf("<") != -1) {
            int start = token.indexOf("<");
            String s = token.substring(start + 1, token.indexOf(">", start));
            token = token.substring(token.indexOf(">", start));
            if (s.indexOf(" ") != -1) {
              String pre = s.substring(0, s.indexOf(" ")).trim();
              s = s.substring(s.indexOf(" ") + 1);
              while (s.indexOf("=") != -1) {
                int eq = s.indexOf("=");
                String key = s.substring(0, eq).trim();
                String value =
                  s.substring(eq + 2, s.indexOf("\"", eq + 2)).trim();
                if (key.indexOf("runtype") == -1) {
                  if (prefix.startsWith("Metadata_V1.2")) {
                    prefix = "";
                  }
                  String effectiveKey = prefix + " " + pre + " " + key;
                  if (!metadata.containsKey(effectiveKey)) {
                    addMeta(effectiveKey, value);
                    if (effectiveKey.endsWith("dTimeMSec value")) {
                      long v = (long) Double.parseDouble(value);
                      if (!ts.contains(new Long(v))) {
                        ts.add(new Long(v));
                      }
                    }
                    else if (effectiveKey.endsWith("dZPos value")) {
                      long v = (long) Double.parseDouble(value);
                      if (!zs.contains(new Long(v))) {
                        zs.add(new Long(v));
                      }
                    }
                    else if (effectiveKey.endsWith("uiComp value")) {
                      if (core.sizeC[0] == 0) {
                        core.sizeC[0] = Integer.parseInt(value);
                      }
                    }
                    else if (effectiveKey.endsWith("uiCount value")) {
                      if (core.sizeT[0] == 0) {
                        core.sizeT[0] = Integer.parseInt(value);
                      }
                    }
                    else if (effectiveKey.endsWith("TextInfoItem Text")) {
                      value = value.replaceAll("&#x000d;&#x000a;", "\n");
                      StringTokenizer tokens = new StringTokenizer(value, "\n");
                      while (tokens.hasMoreTokens()) {
                        String t = tokens.nextToken().trim();
                        if (t.startsWith("Dimensions:")) {
                          t = t.substring(11);
                          StringTokenizer dims = new StringTokenizer(t, " x ");
                          while (dims.hasMoreTokens()) {
                            String dim = dims.nextToken().trim();
                            int idx = dim.indexOf("(");
                            int v = Integer.parseInt(dim.substring(idx + 1,
                              dim.indexOf(")", idx)));
                            if (dim.startsWith("XY")) {
                              numSeries = v;
                              if (numSeries > 1) {
                                int x = core.sizeX[0];
                                int y = core.sizeY[0];
                                int z = core.sizeZ[0];
                                int tSize = core.sizeT[0];
                                int c = core.sizeC[0];
                                core = new CoreMetadata(numSeries);
                                Arrays.fill(core.sizeX, x);
                                Arrays.fill(core.sizeY, y);
                                Arrays.fill(core.sizeZ, z);
                                Arrays.fill(core.sizeC, c);
                                Arrays.fill(core.sizeT, tSize);
                              }
                            }
                            else if (dim.startsWith("T")) {
                              Arrays.fill(core.sizeT, v);
                            }
                            else if (dim.startsWith("Z")) {
                              Arrays.fill(core.sizeZ, v);
                            }
                            else {
                              Arrays.fill(core.sizeC, v);
                            }
                          }
                          if (core.sizeZ[0] == 0) Arrays.fill(core.sizeZ, 1);
                          if (core.sizeC[0] == 0) Arrays.fill(core.sizeC, 1);
                          if (core.sizeT[0] == 0) Arrays.fill(core.sizeT, 1);
                          int count =
                            core.sizeZ[0] * core.sizeC[0] * core.sizeT[0];
                          Arrays.fill(core.imageCount, count);
                          Arrays.fill(core.currentOrder, "XYCZT");
                        }
                      }
                    }
                  }
                  else {
                    String v = (String) getMeta(effectiveKey);
                    boolean parse = v != null;
                    if (parse) {
                      for (int i=0; i<v.length(); i++) {
                        if (Character.isLetter(v.charAt(i)) ||
                          Character.isWhitespace(v.charAt(i)))
                        {
                          parse = false;
                          break;
                        }
                      }
                    }
                    if (parse) {
                      addMeta(effectiveKey, value);
                    }
                  }
                }
                s = s.substring(s.indexOf("\"", eq + 2) + 1);
              }
            }
          }
        }
      }
      b = null;
      xml = null;
      st = null;
    }
    status("Populating metadata");
    if (core.imageCount[0] == 0) {
      core.sizeZ[0] = zs.size() == 0 ? 1 : zs.size();
      core.sizeT[0] = ts.size() == 0 ? 1 : ts.size();
      core.sizeC[0] = (vs.size() + 1) / (core.sizeT[0] * core.sizeZ[0]);
      core.imageCount[0] = vs.size();
      while (core.imageCount[0] % core.sizeC[0] != 0) core.imageCount[0]--;
      while (core.sizeC[0] * core.sizeZ[0] * core.sizeT[0] > core.imageCount[0])
      {
        if (core.sizeZ[0] < core.sizeT[0]) core.sizeT[0]--;
        else core.sizeZ[0]--;
      }
    }
    if (core.sizeC[0] * core.sizeZ[0] * core.sizeT[0] != core.imageCount[0]) {
      core.sizeZ[0] = zs.size();
      core.sizeT[0] = ts.size();
      core.imageCount[0] = core.sizeC[0] * core.sizeZ[0] * core.sizeT[0];
    }
    core.pixelType[0] = FormatTools.UINT8;
    offsets = new long[1][2];
    offsets[0][0] = ((Long) vs.get(0)).longValue();
    offsets[0][1] = ((Long) vs.get(1)).longValue();
    BufferedImage img = openImage(0);
    Arrays.fill(core.sizeX, img.getWidth());
    Arrays.fill(core.sizeY, img.getHeight());
    if (core.sizeC[0] == 0) core.sizeC[0] = 1;
    int c = img.getRaster().getNumBands() * core.sizeC[0];
    Arrays.fill(core.sizeC, c);
    Arrays.fill(core.rgb, img.getRaster().getNumBands() > 1);
    Arrays.fill(core.pixelType, ImageTools.getPixelType(img));
    if (vs.size() < core.imageCount[0]) {
      Arrays.fill(core.imageCount, vs.size());
    }
    if (numSeries == 0) numSeries = 1;
    offsets = new long[numSeries][core.imageCount[0]];
    for (int i=0; i<core.sizeZ[0]*core.sizeT[0]; i++) {
      for (int j=0; j<numSeries; j++) {
        for (int k=0; k<core.sizeC[0]; k++) {
          offsets[j][i*core.sizeC[0] + k] = ((Long) vs.remove(0)).longValue();
        }
      }
    }
    String pixX = (String)
      getMeta("CalibrationSeq _SEQUENCE_INDEX=\"0\" dCalibration value");
    String pixZ = (String)
      getMeta("CalibrationSeq _SEQUENCE_INDEX=\"0\" dAspect value");
    float pixSizeX = 0f;
    float pixSizeZ = 0f;
    if (pixX != null && pixX.length() > 0) {
      pixSizeX = Float.parseFloat(pixX.trim());
    }
    if (pixZ != null && pixZ.length() > 0) {
      pixSizeZ = Float.parseFloat(pixZ.trim());
    }
    Arrays.fill(core.interleaved, false);
    Arrays.fill(core.littleEndian, true);
    Arrays.fill(core.metadataComplete, true);
    MetadataStore store = getMetadataStore();
    FormatTools.populatePixels(store, this);
    for (int i=0; i<numSeries; i++) {
      Integer ii = new Integer(i);
      store.setImage(currentId, null, null, ii);
      store.setDimensions(new Float(pixSizeX), new Float(pixSizeX),
        new Float(pixSizeZ), null, null, ii);
      for (int j=0; j<core.sizeC[0]; j++) {
        store.setLogicalChannel(j, null, null, null, null, null, null, null,
          null, null, null, null, null, null, null, null, null, null, null,
          null, null, null, null, null, ii);
      }
    }
    String prefix = "MetadataSeq _SEQUENCE_INDEX=\"0\" ";
    String gain = (String) getMeta(prefix + "dGain value");
    String voltage = (String) getMeta(prefix + "dLampVoltage value");
    String mag = (String) getMeta(prefix + "dObjectiveMag value");
    String na = (String) getMeta(prefix + "dObjectiveNA value");
    store.setDetector(null, null, null, null,
      gain == null ? null : new Float(gain),
      voltage == null ? null : new Float(voltage), null, null, null);
    store.setObjective(null, null, null, na == null ? null : new Float(na),
      mag == null ? null : new Float(mag), null, null);
  }

  protected void initFile(String id) throws FormatException, IOException {
    if (debug) debug("ND2Reader.initFile(" + id + ")");
    if (noJ2k) throw new FormatException(NO_J2K_MSG);
    super.initFile(id);
    in = new RandomAccessStream(id);
    if (in.read() == -38 && in.read() == -50) {
      isJPEG = false;
      in.seek(0);
      in.order(true);
      byte[] b = new byte[1024 * 1024];
      while (in.getFilePointer() < in.length()) {
        if (in.read() == -38 && in.read() == -50 && in.read() == -66 &&
          in.read() == 10)
        {
          int len = in.readInt() + in.readInt();
          if (len > b.length) {
            int size = b.length + b.length;
            if (size < len) size = len;
            b = new byte[size];
          }
          in.skipBytes(4);
          if (debug) {
            debug("Reading chunk of size " + len +
              " at position " + in.getFilePointer());
          }
          in.readFully(b, 0, len);
          if (len >= 12 && b[0] == 'I' && b[1] == 'm' && b[2] == 'a' &&
            b[3] == 'g' && b[4] == 'e' && b[5] == 'D' && b[6] == 'a' &&
            b[7] == 't' && b[8] == 'a' && b[9] == 'S' && b[10] == 'e' &&
            b[11] == 'q') 
          {
            StringBuffer sb = new StringBuffer();
            int pt = 13;
            while (b[pt] != '!') {
              sb.append((char) b[pt]);
              pt++;
            }
            int ndx = Integer.parseInt(sb.toString());
            if (core.sizeC[0] == 0) {
              core.sizeC[0] = len / (core.sizeX[0] * core.sizeY[0] *
                FormatTools.getBytesPerPixel(core.pixelType[0]));
            }
            offsets[0][ndx] = in.getFilePointer() - len + sb.length() + 21;
            while (offsets[0][ndx] - in.getFilePointer() +
              len - 14 - sb.length() < 8)
            {
              offsets[0][ndx]++;
            }
          }
          else if (len >= 5 && b[0] == 'I' && b[1] == 'm' && b[2] == 'a' &&
            b[3] == 'g' && b[4] == 'e') 
          {
            ND2Handler handler = new ND2Handler();
            int off = 0;
            for (int i=0; i<len; i++) {
              char c = (char) b[i];
              if (off == 0 && c == '!') off = i + 1;
              if (Character.isISOControl(c) || !Character.isDefined(c)) {
                b[i] = (byte) ' ';
              }
            }
            if (len - off >= 5 && b[off] == '<' && b[off + 1] == '?' &&
              b[off + 2] == 'x' && b[off + 3] == 'm' &&
              b[off + 4] == 'l') 
            {
              ByteArrayInputStream s =
                new ByteArrayInputStream(b, off, len - off);
              try {
                SAXParser parser = SAX_FACTORY.newSAXParser();
                parser.parse(s, handler);
              }
              catch (ParserConfigurationException exc) {
                throw new FormatException(exc);
              }
              catch (SAXException exc) {
                throw new FormatException(exc);
              }
            }
          }
          if (core.imageCount[0] > 0 && offsets == null) {
            offsets = new long[1][core.imageCount[0]];
          }
          if (in.getFilePointer() < in.length() - 1) {
            if (in.read() != -38) in.skipBytes(15);
            else in.seek(in.getFilePointer() - 1);
          }
        }
      }
      if (core.sizeC[0] == 0) core.sizeC[0] = 1;
      core.currentOrder[0] = "XYCZT";
      core.rgb[0] = core.sizeC[0] > 1;
      if (core.sizeC[0] > 1 && adjustImageCount) {
        core.imageCount[0] /= 3;
        core.sizeT[0] /= 3;
      }
      core.littleEndian[0] = true;
      core.interleaved[0] = true;
      core.indexed[0] = false;
      core.falseColor[0] = false;
      core.metadataComplete[0] = true;
      MetadataStore store = getMetadataStore();
      store.setImage(currentId, null, null, null);
      FormatTools.populatePixels(store, this);
      for (int i=0; i<core.sizeC[0]; i++) {
        store.setLogicalChannel(i, null, null, null, null, null, null, null,
          null, null, null, null, null, null, null, null, null, null, null,
          null, null, null, null, null, null);
      }
      return;
    }
    else in.seek(0);
    isJPEG = true;
    status("Calculating image offsets");
    Vector vs = new Vector();
    long pos = in.getFilePointer();
    boolean lastBoxFound = false;
    int length = 0;
    int box = 0;
    while (!lastBoxFound) {
      pos = in.getFilePointer();
      length = in.readInt();
      if (pos + length >= in.length() || length == 0) lastBoxFound = true;
      box = in.readInt();
      pos = in.getFilePointer();
      length -= 8;
      if (box == 0x6a703263) {
        vs.add(new Long(in.getFilePointer()));
      }
      if (!lastBoxFound) in.seek(pos + length);
    }
    status("Finding XML metadata");
    in.seek(((Long) vs.get(vs.size() - 1)).longValue());
    boolean found = false;
    long off = -1;
    byte[] buf = new byte[2048];
    while (!found && in.getFilePointer() < in.length()) {
      int read = 0;
      if (in.getFilePointer() == ((Long) vs.get(vs.size() - 1)).longValue()) {
        read = in.read(buf);
      }
      else {
        System.arraycopy(buf, buf.length - 10, buf, 0, 10);
        read = in.read(buf, 10, buf.length - 10);
      }
      if (read == buf.length) read -= 10;
      for (int i=0; i<read+9; i++) {
        if (buf[i] == (byte) 0xff && buf[i+1] == (byte) 0xd9) {
          found = true;
          off = in.getFilePointer() - (read + 10) + i;
          i = buf.length;
          break;
        }
      }
    }
    buf = null;
    status("Parsing XML");
    if (off > 0 && off < in.length() - 5) {
      in.seek(off + 5);
      byte[] b = new byte[(int) (in.length() - off - 5)];
      in.readFully(b);
      String xml = new String(b);
      xml = xml.substring(0, xml.lastIndexOf("</MetadataSeq>") + 14);
      xml = xml.replaceAll("<!--*-->", "");
      StringTokenizer st = new StringTokenizer(xml, "\r\n");
      while (st.hasMoreTokens()) {
        String token = st.nextToken().trim();
        if (token.indexOf("<") != -1) {
          String prefix = token.substring(1, token.indexOf(">")).trim();
          token = token.substring(token.indexOf(">") + 1);
          while (token.indexOf("<") != -1) {
            int start = token.indexOf("<");
            String s = token.substring(start + 1, token.indexOf(">", start));
            token = token.substring(token.indexOf(">", start));
            if (s.indexOf(" ") != -1) {
              String pre = s.substring(0, s.indexOf(" ")).trim();
              s = s.substring(s.indexOf(" ") + 1);
              while (s.indexOf("=") != -1) {
                int eq = s.indexOf("=");
                String key = s.substring(0, eq).trim();
                String value =
                  s.substring(eq + 2, s.indexOf("\"", eq + 2)).trim();
                if (key.indexOf("runtype") == -1) {
                  if (prefix.startsWith("Metadata_V1.2")) {
                    prefix = "";
                  }
                  String effectiveKey = prefix + " " + pre + " " + key;
                  if (!metadata.containsKey(effectiveKey)) {
                    addMeta(effectiveKey, value);
                    if (effectiveKey.endsWith("dTimeMSec value")) {
                      long v = (long) Double.parseDouble(value);
                      if (!ts.contains(new Long(v))) {
                        ts.add(new Long(v));
                      }
                    }
                    else if (effectiveKey.endsWith("dZPos value")) {
                      long v = (long) Double.parseDouble(value);
                      if (!zs.contains(new Long(v))) {
                        zs.add(new Long(v));
                      }
                    }
                    else if (effectiveKey.endsWith("uiComp value")) {
                      if (core.sizeC[0] == 0) {
                        core.sizeC[0] = Integer.parseInt(value);
                      }
                    }
                    else if (effectiveKey.endsWith("uiCount value")) {
                      if (core.sizeT[0] == 0) {
                        core.sizeT[0] = Integer.parseInt(value);
                      }
                    }
                    else if (effectiveKey.endsWith("TextInfoItem Text")) {
                      value = value.replaceAll("&#x000d;&#x000a;", "\n");
                      StringTokenizer tokens = new StringTokenizer(value, "\n");
                      while (tokens.hasMoreTokens()) {
                        String t = tokens.nextToken().trim();
                        if (t.startsWith("Dimensions:")) {
                          t = t.substring(11);
                          StringTokenizer dims = new StringTokenizer(t, " x ");
                          while (dims.hasMoreTokens()) {
                            String dim = dims.nextToken().trim();
                            int idx = dim.indexOf("(");
                            int v = Integer.parseInt(dim.substring(idx + 1,
                              dim.indexOf(")", idx)));
                            if (dim.startsWith("XY")) {
                              numSeries = v;
                              if (numSeries > 1) {
                                int x = core.sizeX[0];
                                int y = core.sizeY[0];
                                int z = core.sizeZ[0];
                                int tSize = core.sizeT[0];
                                int c = core.sizeC[0];
                                core = new CoreMetadata(numSeries);
                                Arrays.fill(core.sizeX, x);
                                Arrays.fill(core.sizeY, y);
                                Arrays.fill(core.sizeZ, z);
                                Arrays.fill(core.sizeC, c);
                                Arrays.fill(core.sizeT, tSize);
                              }
                            }
                            else if (dim.startsWith("T")) {
                              Arrays.fill(core.sizeT, v);
                            }
                            else if (dim.startsWith("Z")) {
                              Arrays.fill(core.sizeZ, v);
                            }
                            else {
                              Arrays.fill(core.sizeC, v);
                            }
                          }
                          if (core.sizeZ[0] == 0) Arrays.fill(core.sizeZ, 1);
                          if (core.sizeC[0] == 0) Arrays.fill(core.sizeC, 1);
                          if (core.sizeT[0] == 0) Arrays.fill(core.sizeT, 1);
                          int count =
                            core.sizeZ[0] * core.sizeC[0] * core.sizeT[0];
                          Arrays.fill(core.imageCount, count);
                          Arrays.fill(core.currentOrder, "XYCZT");
                        }
                      }
                    }
                  }
                  else {
                    String v = (String) getMeta(effectiveKey);
                    boolean parse = v != null;
                    if (parse) {
                      for (int i=0; i<v.length(); i++) {
                        if (Character.isLetter(v.charAt(i)) ||
                          Character.isWhitespace(v.charAt(i)))
                        {
                          parse = false;
                          break;
                        }
                      }
                    }
                    if (parse) {
                      addMeta(effectiveKey, value);
                    }
                  }
                }
                s = s.substring(s.indexOf("\"", eq + 2) + 1);
              }
            }
          }
        }
      }
      b = null;
      xml = null;
      st = null;
    }
    status("Populating metadata");
    if (core.imageCount[0] == 0) {
      core.sizeZ[0] = zs.size() == 0 ? 1 : zs.size();
      core.sizeT[0] = ts.size() == 0 ? 1 : ts.size();
      core.sizeC[0] = (vs.size() + 1) / (core.sizeT[0] * core.sizeZ[0]);
      core.imageCount[0] = vs.size();
      while (core.imageCount[0] % core.sizeC[0] != 0) core.imageCount[0]--;
      while (core.sizeC[0] * core.sizeZ[0] * core.sizeT[0] > core.imageCount[0])
      {
        if (core.sizeZ[0] < core.sizeT[0]) core.sizeT[0]--;
        else core.sizeZ[0]--;
      }
    }
    if (core.sizeC[0] * core.sizeZ[0] * core.sizeT[0] != core.imageCount[0]) {
      core.sizeZ[0] = zs.size();
      core.sizeT[0] = ts.size();
      core.imageCount[0] = core.sizeC[0] * core.sizeZ[0] * core.sizeT[0];
    }
    core.pixelType[0] = FormatTools.UINT8;
    offsets = new long[1][2];
    offsets[0][0] = ((Long) vs.get(0)).longValue();
    offsets[0][1] = ((Long) vs.get(1)).longValue();
    BufferedImage img = openImage(0);
    Arrays.fill(core.sizeX, img.getWidth());
    Arrays.fill(core.sizeY, img.getHeight());
    if (core.sizeC[0] == 0) core.sizeC[0] = 1;
    int c = img.getRaster().getNumBands() * core.sizeC[0];
    Arrays.fill(core.sizeC, c);
    Arrays.fill(core.rgb, img.getRaster().getNumBands() > 1);
    Arrays.fill(core.pixelType, ImageTools.getPixelType(img));
    if (vs.size() < core.imageCount[0]) {
      Arrays.fill(core.imageCount, vs.size());
    }
    if (numSeries == 0) numSeries = 1;
    offsets = new long[numSeries][core.imageCount[0]];
    for (int i=0; i<core.sizeZ[0]*core.sizeT[0]; i++) {
      for (int j=0; j<numSeries; j++) {
        for (int k=0; k<core.sizeC[0]; k++) {
          offsets[j][i*core.sizeC[0] + k] = ((Long) vs.remove(0)).longValue();
        }
      }
    }
    String pixX = (String)
      getMeta("CalibrationSeq _SEQUENCE_INDEX=\"0\" dCalibration value");
    String pixZ = (String)
      getMeta("CalibrationSeq _SEQUENCE_INDEX=\"0\" dAspect value");
    float pixSizeX = 0f;
    float pixSizeZ = 0f;
    if (pixX != null && pixX.length() > 0) {
      pixSizeX = Float.parseFloat(pixX.trim());
    }
    if (pixZ != null && pixZ.length() > 0) {
      pixSizeZ = Float.parseFloat(pixZ.trim());
    }
    Arrays.fill(core.interleaved, false);
    Arrays.fill(core.littleEndian, false);
    Arrays.fill(core.metadataComplete, true);
    MetadataStore store = getMetadataStore();
    FormatTools.populatePixels(store, this);
    for (int i=0; i<numSeries; i++) {
      Integer ii = new Integer(i);
      store.setImage(currentId, null, null, ii);
      store.setDimensions(new Float(pixSizeX), new Float(pixSizeX),
        new Float(pixSizeZ), null, null, ii);
      for (int j=0; j<core.sizeC[0]; j++) {
        store.setLogicalChannel(j, null, null, null, null, null, null, null,
          null, null, null, null, null, null, null, null, null, null, null,
          null, null, null, null, null, ii);
      }
    }
    String prefix = "MetadataSeq _SEQUENCE_INDEX=\"0\" ";
    String gain = (String) getMeta(prefix + "dGain value");
    String voltage = (String) getMeta(prefix + "dLampVoltage value");
    String mag = (String) getMeta(prefix + "dObjectiveMag value");
    String na = (String) getMeta(prefix + "dObjectiveNA value");
    store.setDetector(null, null, null, null,
      gain == null ? null : new Float(gain),
      voltage == null ? null : new Float(voltage), null, null, null);
    store.setObjective(null, null, null, na == null ? null : new Float(na),
      mag == null ? null : new Float(mag), null, null);
  }
