  protected void initFile(String id) throws FormatException, IOException {
    super.initFile(id);
    in = new RandomAccessInputStream(id);
    core[0].littleEndian = false;
    if (!in.readString(4).equals("8BPS")) {
      throw new FormatException("Not a valid Photoshop file.");
    }
    addGlobalMeta("Version", in.readShort());
    in.skipBytes(6); 
    core[0].sizeC = in.readShort();
    core[0].sizeY = in.readInt();
    core[0].sizeX = in.readInt();
    int bits = in.readShort();
    addGlobalMeta("Bits per pixel", bits);
    core[0].pixelType = FormatTools.pixelTypeFromBytes(bits / 8, false, false);
    int colorMode = in.readShort();
    String modeString = null;
    switch (colorMode) {
      case 0:
        modeString = "monochrome";
        break;
      case 1:
        modeString = "gray-scale";
        break;
      case 2:
        modeString = "palette color";
        break;
      case 3:
        modeString = "RGB";
        break;
      case 4:
        modeString = "CMYK";
        break;
      case 6:
        modeString = "Duotone";
        break;
      case 7:
        modeString = "Multichannel color";
        break;
      case 8:
        modeString = "Duotone";
        break;
      case 9:
        modeString = "LAB color";
        break;
    }
    addGlobalMeta("Color mode", modeString);
    int modeDataLength = in.readInt();
    long fp = in.getFilePointer();
    if (modeDataLength != 0) {
      if (colorMode == 2) {
        lut = new byte[3][256];
        for (int i=0; i<lut.length; i++) {
          in.read(lut[i]);
        }
      }
      in.seek(fp + modeDataLength);
    }
    in.skipBytes(4);
    while (in.readString(4).equals("8BIM")) {
      int tag = in.readShort();
      int read = 1;
      while (in.read() != 0) read++;
      if (read % 2 == 1) in.skipBytes(1);
      int size = in.readInt();
      if (size % 2 == 1) size++;
      in.skipBytes(size);
    }
    in.seek(in.getFilePointer() - 4);
    int blockLen = in.readInt();
    if (blockLen == 0) {
      offset = in.getFilePointer();
    }
    else {
      int layerLen = in.readInt();
      int layerCount = in.readShort();
      if (layerCount < 0) {
        throw new FormatException("Vector data is not supported.");
      }
      int[] w = new int[layerCount];
      int[] h = new int[layerCount];
      int[] c = new int[layerCount];
      for (int i=0; i<layerCount; i++) {
        int top = in.readInt();
        int left = in.readInt();
        int bottom = in.readInt();
        int right = in.readInt();
        w[i] = right - left;
        h[i] = bottom - top;
        c[i] = in.readShort();
        in.skipBytes(c[i] * 6 + 12);
        int len = in.readInt();
        if (len % 2 == 1) len++;
        in.skipBytes(len);
      }
      for (int i=0; i<layerCount; i++) {
        int[] lens = new int[h[i]];
        for (int cc=0; cc<c[i]; cc++) {
          boolean compressed = in.readShort() == 1;
          if (!compressed) in.skipBytes(w[i] * h[i]);
          else {
            for (int y=0; y<h[i]; y++) {
              lens[y] = in.readShort();
            }
            for (int y=0; y<h[i]; y++) {
              in.skipBytes(lens[y]);
            }
          }
        }
      }
      while (in.read() != '8');
      in.skipBytes(7);
      int len = in.readInt();
      if ((len % 4) != 0) len += 4 - (len % 4);
      in.skipBytes(len);
      String s = in.readString(4);
      while (s.equals("8BIM")) {
        in.skipBytes(4);
        len = in.readInt();
        if ((len % 4) != 0) len += 4 - (len % 4);
        in.skipBytes(len);
        s = in.readString(4);
      }
      offset = in.getFilePointer() - 4;
    }
    core[0].sizeZ = 1;
    core[0].sizeT = 1;
    core[0].rgb = modeString.equals("RGB");
    core[0].imageCount = getSizeC() / (isRGB() ? 3 : 1);
    core[0].indexed = modeString.equals("palette color");
    core[0].falseColor = false;
    core[0].dimensionOrder = "XYCZT";
    core[0].interleaved = false;
    core[0].metadataComplete = true;
    MetadataStore store = makeFilterMetadata();
    MetadataTools.populatePixels(store, this);
    MetadataTools.setDefaultCreationDate(store, id, 0);
  }

  protected void initFile(String id) throws FormatException, IOException {
    super.initFile(id);
    in = new RandomAccessInputStream(id);
    core[0].littleEndian = false;
    if (!in.readString(4).equals("8BPS")) {
      throw new FormatException("Not a valid Photoshop file.");
    }
    addGlobalMeta("Version", in.readShort());
    in.skipBytes(6); 
    core[0].sizeC = in.readShort();
    core[0].sizeY = in.readInt();
    core[0].sizeX = in.readInt();
    int bits = in.readShort();
    addGlobalMeta("Bits per pixel", bits);
    core[0].pixelType = FormatTools.pixelTypeFromBytes(bits / 8, false, false);
    int colorMode = in.readShort();
    String modeString = null;
    switch (colorMode) {
      case 0:
        modeString = "monochrome";
        break;
      case 1:
        modeString = "gray-scale";
        break;
      case 2:
        modeString = "palette color";
        break;
      case 3:
        modeString = "RGB";
        break;
      case 4:
        modeString = "CMYK";
        break;
      case 6:
        modeString = "Duotone";
        break;
      case 7:
        modeString = "Multichannel color";
        break;
      case 8:
        modeString = "Duotone";
        break;
      case 9:
        modeString = "LAB color";
        break;
    }
    addGlobalMeta("Color mode", modeString);
    int modeDataLength = in.readInt();
    long fp = in.getFilePointer();
    if (modeDataLength != 0) {
      if (colorMode == 2) {
        lut = new byte[3][256];
        for (int i=0; i<lut.length; i++) {
          in.read(lut[i]);
        }
      }
      in.seek(fp + modeDataLength);
    }
    in.skipBytes(4);
    while (in.readString(4).equals("8BIM")) {
      int tag = in.readShort();
      int read = 1;
      while (in.read() != 0) read++;
      if (read % 2 == 1) in.skipBytes(1);
      int size = in.readInt();
      if (size % 2 == 1) size++;
      in.skipBytes(size);
    }
    in.seek(in.getFilePointer() - 4);
    int blockLen = in.readInt();
    if (blockLen == 0) {
      offset = in.getFilePointer();
    }
    else {
      int layerLen = in.readInt();
      int layerCount = in.readShort();
      if (layerCount < 0) {
        throw new FormatException("Vector data is not supported.");
      }
      int[] w = new int[layerCount];
      int[] h = new int[layerCount];
      int[] c = new int[layerCount];
      for (int i=0; i<layerCount; i++) {
        int top = in.readInt();
        int left = in.readInt();
        int bottom = in.readInt();
        int right = in.readInt();
        w[i] = right - left;
        h[i] = bottom - top;
        c[i] = in.readShort();
        in.skipBytes(c[i] * 6 + 12);
        int len = in.readInt();
        if (len % 2 == 1) len++;
        in.skipBytes(len);
      }
      for (int i=0; i<layerCount; i++) {
        int[] lens = new int[h[i]];
        for (int cc=0; cc<c[i]; cc++) {
          boolean compressed = in.readShort() == 1;
          if (!compressed) in.skipBytes(w[i] * h[i]);
          else {
            for (int y=0; y<h[i]; y++) {
              lens[y] = in.readShort();
            }
            for (int y=0; y<h[i]; y++) {
              in.skipBytes(lens[y]);
            }
          }
        }
      }
      if (layerCount > 0) {
        while (in.read() != '8');
        in.skipBytes(7);
      }
      int len = in.readInt();
      if ((len % 4) != 0) len += 4 - (len % 4);
      in.skipBytes(len);
      String s = in.readString(4);
      while (s.equals("8BIM")) {
        in.skipBytes(4);
        len = in.readInt();
        if ((len % 4) != 0) len += 4 - (len % 4);
        in.skipBytes(len);
        s = in.readString(4);
      }
      offset = in.getFilePointer() - 4;
    }
    core[0].sizeZ = 1;
    core[0].sizeT = 1;
    core[0].rgb = modeString.equals("RGB");
    core[0].imageCount = getSizeC() / (isRGB() ? 3 : 1);
    core[0].indexed = modeString.equals("palette color");
    core[0].falseColor = false;
    core[0].dimensionOrder = "XYCZT";
    core[0].interleaved = false;
    core[0].metadataComplete = true;
    MetadataStore store = makeFilterMetadata();
    MetadataTools.populatePixels(store, this);
    MetadataTools.setDefaultCreationDate(store, id, 0);
  }
