private void readTags(RandomAccessInputStream vsi) throws IOException { // read the VSI header long fp = vsi.getFilePointer(); if (fp + 24 >= vsi.length()) { return; } int headerSize = vsi.readShort(); // should always be 24 int version = vsi.readShort(); // always 21321 int volumeVersion = vsi.readInt(); long dataFieldOffset = vsi.readLong(); int flags = vsi.readInt(); vsi.skipBytes(4); int tagCount = flags & 0xfffffff; if (fp + dataFieldOffset < 0) { return; } vsi.seek(fp + dataFieldOffset); if (vsi.getFilePointer() >= vsi.length()) { return; } for (int i = 0; i < tagCount; i++) { if (vsi.getFilePointer() + 16 >= vsi.length()) { break; } // read the data field int fieldType = vsi.readInt(); int tag = vsi.readInt(); long nextField = vsi.readInt() & 0xffffffffL; int dataSize = vsi.readInt(); boolean extraTag = ((fieldType & 0x8000000) >> 27) == 1; boolean extendedField = ((fieldType & 0x10000000) >> 28) == 1; boolean inlineData = ((fieldType & 0x40000000) >> 30) == 1; boolean array = (!inlineData && !extendedField) && ((fieldType & 0x20000000) >> 29) == 1; boolean newVolume = ((fieldType & 0x80000000) >> 31) == 1; int realType = fieldType & 0xffffff; int secondTag = -1; if (extraTag) { secondTag = vsi.readInt(); } if (extendedField && realType == NEW_VOLUME_HEADER) { if (tag == 2007) { dimensionTag = secondTag; inDimensionProperties = true; } long endPointer = vsi.getFilePointer() + dataSize; while (vsi.getFilePointer() < endPointer && vsi.getFilePointer() < vsi.length()) { long start = vsi.getFilePointer(); readTags(vsi); long end = vsi.getFilePointer(); if (start == end) { break; } } if (tag == 2007) { inDimensionProperties = false; foundChannelTag = false; } } if (inDimensionProperties) { if (tag == 2012 && !dimensionOrdering.containsValue(dimensionTag)) { dimensionOrdering.put("Z", dimensionTag); } else if ((tag == 2100 || tag == 2027) && !dimensionOrdering.containsValue(dimensionTag)) { dimensionOrdering.put("T", dimensionTag); } else if (tag == 2039 && !dimensionOrdering.containsValue(dimensionTag)) { dimensionOrdering.put("L", dimensionTag); } else if (tag == 2008 && foundChannelTag && !dimensionOrdering.containsValue(dimensionTag)) { dimensionOrdering.put("C", dimensionTag); } else if (tag == 2008) { foundChannelTag = true; } } if (nextField == 0) { return; } if (fp + nextField < vsi.length() && fp + nextField >= 0) { vsi.seek(fp + nextField); } else break; } }
private void parseETSFile(String file, int s) throws FormatException, IOException { RandomAccessInputStream etsFile = new RandomAccessInputStream(file); etsFile.order(true); // read the volume header String magic = etsFile.readString(4).trim(); if (!magic.equals("SIS")) { throw new FormatException("Unknown magic bytes: " + magic); } int headerSize = etsFile.readInt(); int version = etsFile.readInt(); nDimensions[s] = etsFile.readInt(); long additionalHeaderOffset = etsFile.readLong(); int additionalHeaderSize = etsFile.readInt(); etsFile.skipBytes(4); // reserved long usedChunkOffset = etsFile.readLong(); int nUsedChunks = etsFile.readInt(); etsFile.skipBytes(4); // reserved // read the additional header etsFile.seek(additionalHeaderOffset); String moreMagic = etsFile.readString(4).trim(); if (!moreMagic.equals("ETS")) { throw new FormatException("Unknown magic bytes: " + moreMagic); } etsFile.skipBytes(4); // extra version number int pixelType = etsFile.readInt(); core[s].sizeC = etsFile.readInt(); int colorspace = etsFile.readInt(); compressionType[s] = etsFile.readInt(); int compressionQuality = etsFile.readInt(); tileX[s] = etsFile.readInt(); tileY[s] = etsFile.readInt(); int tileZ = etsFile.readInt(); core[s].rgb = core[s].sizeC > 1; // read the used chunks etsFile.seek(usedChunkOffset); tileOffsets[s] = new Long[nUsedChunks]; ArrayList<TileCoordinate> tmpTiles = new ArrayList<TileCoordinate>(); for (int chunk = 0; chunk < nUsedChunks; chunk++) { etsFile.skipBytes(4); TileCoordinate t = new TileCoordinate(nDimensions[s]); for (int i = 0; i < nDimensions[s]; i++) { t.coordinate[i] = etsFile.readInt(); } tileOffsets[s][chunk] = etsFile.readLong(); int nBytes = etsFile.readInt(); etsFile.skipBytes(4); tmpTiles.add(t); } int maxX = 0; int maxY = 0; int maxZ = 0; int maxC = 0; int maxT = 0; for (TileCoordinate t : tmpTiles) { Integer tv = dimensionOrdering.get("T"); Integer zv = dimensionOrdering.get("Z"); Integer cv = dimensionOrdering.get("C"); int tIndex = tv == null ? -1 : tv + 2; int zIndex = zv == null ? -1 : zv + 2; int cIndex = cv == null ? -1 : cv + 2; if (tv == null && zv == null) { if (t.coordinate.length > 4 && cv == null) { cIndex = 2; dimensionOrdering.put("C", cIndex - 2); } if (t.coordinate.length > 4) { if (cv == null) { tIndex = 3; } else { tIndex = cIndex + 2; } if (tIndex < t.coordinate.length) { dimensionOrdering.put("T", tIndex - 2); } else { tIndex = -1; } } if (t.coordinate.length > 5) { if (cv == null) { zIndex = 4; } else { zIndex = cIndex + 1; } if (zIndex < t.coordinate.length) { dimensionOrdering.put("Z", zIndex - 2); } else { zIndex = -1; } } } if (t.coordinate[0] > maxX) { maxX = t.coordinate[0]; } if (t.coordinate[1] > maxY) { maxY = t.coordinate[1]; } if (tIndex >= 0 && t.coordinate[tIndex] > maxT) { maxT = t.coordinate[tIndex]; } if (zIndex >= 0 && t.coordinate[zIndex] > maxZ) { maxZ = t.coordinate[zIndex]; } if (cIndex >= 0 && t.coordinate[cIndex] > maxC) { maxC = t.coordinate[cIndex]; } } if (maxX > 1) { core[s].sizeX = tileX[s] * (maxX + 1); } else { core[s].sizeX = tileX[s]; } if (maxY > 1) { core[s].sizeY = tileY[s] * (maxY + 1); } else { core[s].sizeY = tileY[s]; } core[s].sizeZ = maxZ + 1; if (maxC > 0) { core[s].sizeC *= (maxC + 1); } core[s].sizeT = maxT + 1; if (core[s].sizeZ == 0) { core[s].sizeZ = 1; } core[s].imageCount = core[s].sizeZ * core[s].sizeT; if (maxC > 0) { core[s].imageCount *= (maxC + 1); } if (maxY > 1) { rows[s] = maxY + 1; } else { rows[s] = 1; } if (maxX > 1) { cols[s] = maxX + 1; } else { cols[s] = 1; } for (int i = 0; i < tmpTiles.size(); i++) { tileMap[s].put(tmpTiles.get(i), i); } core[s].pixelType = convertPixelType(pixelType); etsFile.close(); }