/* @see IFormatHandler#setId(String) */ public void setId(String id) throws FormatException, IOException { try { super.setId(id); } catch (CMMException e) { // strip out all but the first application marker // ImageIO isn't too keen on supporting multiple application markers // in the same stream, as evidenced by: // // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6488904 in = new RandomAccessInputStream(id); ByteArrayOutputStream v = new ByteArrayOutputStream(); byte[] tag = new byte[2]; in.read(tag); v.write(tag); in.read(tag); int tagValue = DataTools.bytesToShort(tag, false) & 0xffff; boolean appNoteFound = false; while (tagValue != 0xffdb) { if (!appNoteFound || (tagValue < 0xffe0 && tagValue >= 0xfff0)) { v.write(tag); in.read(tag); int len = DataTools.bytesToShort(tag, false) & 0xffff; byte[] tagContents = new byte[len - 2]; in.read(tagContents); v.write(tag); v.write(tagContents); } else { in.read(tag); int len = DataTools.bytesToShort(tag, false) & 0xffff; in.skipBytes(len - 2); } if (tagValue >= 0xffe0 && tagValue < 0xfff0 && !appNoteFound) { appNoteFound = true; } in.read(tag); tagValue = DataTools.bytesToShort(tag, false) & 0xffff; } v.write(tag); byte[] remainder = new byte[(int) (in.length() - in.getFilePointer())]; in.read(remainder); v.write(remainder); ByteArrayHandle bytes = new ByteArrayHandle(v.toByteArray()); Location.mapFile(currentId + ".fixed", bytes); super.setId(currentId + ".fixed"); } if (getSizeX() > MAX_SIZE && getSizeY() > MAX_SIZE && !legacyReaderInitialized) { close(); useLegacy = true; super.setId(id); } currentId = id; }
private void writePixels(String chunk, byte[] stream, int x, int y, int width, int height) throws FormatException, IOException { MetadataRetrieve r = getMetadataRetrieve(); int sizeC = getSamplesPerPixel(); String type = r.getPixelsType(series).toString(); int pixelType = FormatTools.pixelTypeFromString(type); boolean signed = FormatTools.isSigned(pixelType); if (!isFullPlane(x, y, width, height)) { throw new FormatException("APNGWriter does not support writing tiles."); } ByteArrayOutputStream s = new ByteArrayOutputStream(); s.write(chunk.getBytes()); if (chunk.equals("fdAT")) { s.write(DataTools.intToBytes(nextSequenceNumber++, false)); } DeflaterOutputStream deflater = new DeflaterOutputStream(s); int planeSize = stream.length / sizeC; int rowLen = stream.length / height; int bytesPerPixel = stream.length / (width * height * sizeC); byte[] rowBuf = new byte[rowLen]; for (int i = 0; i < height; i++) { deflater.write(0); if (interleaved) { if (littleEndian) { for (int col = 0; col < width * sizeC; col++) { int offset = (i * sizeC * width + col) * bytesPerPixel; int pixel = DataTools.bytesToInt(stream, offset, bytesPerPixel, littleEndian); DataTools.unpackBytes(pixel, rowBuf, col * bytesPerPixel, bytesPerPixel, false); } } else System.arraycopy(stream, i * rowLen, rowBuf, 0, rowLen); } else { int max = (int) Math.pow(2, bytesPerPixel * 8 - 1); for (int col = 0; col < width; col++) { for (int c = 0; c < sizeC; c++) { int offset = c * planeSize + (i * width + col) * bytesPerPixel; int pixel = DataTools.bytesToInt(stream, offset, bytesPerPixel, littleEndian); if (signed) { if (pixel < max) pixel += max; else pixel -= max; } int output = (col * sizeC + c) * bytesPerPixel; DataTools.unpackBytes(pixel, rowBuf, output, bytesPerPixel, false); } } } deflater.write(rowBuf); } deflater.finish(); byte[] b = s.toByteArray(); // write chunk length out.writeInt(b.length - 4); out.write(b); // write checksum out.writeInt(crc(b)); }
/* @see loci.formats.IFormatHandler#setId(String) */ public void setId(String id) throws FormatException, IOException { super.setId(id); if (out.length() == 0) { MetadataRetrieve r = getMetadataRetrieve(); int width = r.getPixelsSizeX(series).getValue().intValue(); int height = r.getPixelsSizeY(series).getValue().intValue(); int bytesPerPixel = FormatTools.getBytesPerPixel(r.getPixelsType(series).toString()); int nChannels = getSamplesPerPixel(); boolean indexed = getColorModel() != null && (getColorModel() instanceof IndexColorModel); littleEndian = !r.getPixelsBinDataBigEndian(series, 0); // write 8-byte PNG signature out.write(PNG_SIG); // write IHDR chunk out.writeInt(13); byte[] b = new byte[17]; b[0] = 'I'; b[1] = 'H'; b[2] = 'D'; b[3] = 'R'; DataTools.unpackBytes(width, b, 4, 4, false); DataTools.unpackBytes(height, b, 8, 4, false); b[12] = (byte) (bytesPerPixel * 8); if (indexed) b[13] = (byte) 3; else if (nChannels == 1) b[13] = (byte) 0; else if (nChannels == 2) b[13] = (byte) 4; else if (nChannels == 3) b[13] = (byte) 2; else if (nChannels == 4) b[13] = (byte) 6; b[14] = (byte) 0; b[15] = (byte) 0; b[16] = (byte) 0; out.write(b); out.writeInt(crc(b)); // write acTL chunk out.writeInt(8); out.writeBytes("acTL"); numFramesPointer = out.getFilePointer(); out.writeInt(0); out.writeInt(0); out.writeInt(0); // save a place for the CRC } }
private void parsePosition(int posIndex) throws IOException, FormatException { Position p = positions.get(posIndex); String s = DataTools.readFile(p.metadataFile); parsePosition(s, posIndex); buildTIFFList(posIndex); }
private void parseROIs(MetadataStore store) throws IOException { if (roiFile == null) return; String roiData = DataTools.readFile(roiFile); String[] lines = roiData.split("\r\n"); int firstRow = 0; while (firstRow < lines.length && !lines[firstRow].startsWith("ROI")) { firstRow++; } firstRow += 2; if (firstRow >= lines.length) return; for (int i = firstRow; i < lines.length; i++) { String[] cols = lines[i].split("\t"); if (cols.length < 6) break; if (cols[2].trim().length() > 0) { String rectangleID = MetadataTools.createLSID("Shape", i - firstRow, 0); store.setRectangleID(rectangleID, i - firstRow, 0); store.setRectangleX(new Double(cols[2]), i - firstRow, 0); store.setRectangleY(new Double(cols[3]), i - firstRow, 0); store.setRectangleWidth(new Double(cols[4]), i - firstRow, 0); store.setRectangleHeight(new Double(cols[5]), i - firstRow, 0); String roiID = MetadataTools.createLSID("ROI", i - firstRow); store.setROIID(roiID, i - firstRow); for (int s = 0; s < getSeriesCount(); s++) { store.setImageROIRef(roiID, s, i - firstRow); } } } }
/** Parse metadata values from the Acqusition.xml file. */ private void parseXMLFile() throws IOException { Position p = positions.get(getSeries()); String xmlData = DataTools.readFile(p.xmlFile); xmlData = XMLTools.sanitizeXML(xmlData); DefaultHandler handler = new MicromanagerHandler(); XMLTools.parseXML(xmlData, handler); }
/** * Calculates a SHA-1 digest on a byte array. * * @param buf Byte array to calculate a SHA-1 digest for. * @return Hex string of the SHA-1 digest for <code>buf</code>. */ private String sha1(byte[] buf) { try { MessageDigest md = MessageDigest.getInstance("SHA-1"); return DataTools.bytesToHex(md.digest(buf)); } catch (Exception e) { throw new RuntimeException(e); } }
private void writeFooter() throws IOException { // write IEND chunk out.writeInt(0); out.writeBytes("IEND"); out.writeInt(crc("IEND".getBytes())); // update frame count out.seek(numFramesPointer); out.writeInt(numFrames); out.skipBytes(4); byte[] b = new byte[12]; b[0] = 'a'; b[1] = 'c'; b[2] = 'T'; b[3] = 'L'; DataTools.unpackBytes(numFrames, b, 4, 4, false); DataTools.unpackBytes(0, b, 8, 4, false); out.writeInt(crc(b)); }
private static double decodeWord(byte[] plane, int index, int pixelType, boolean little) { final double value; switch (pixelType) { case FormatTools.UINT8: value = plane[index] & 0xff; break; case FormatTools.INT8: value = plane[index]; break; case FormatTools.UINT16: value = DataTools.bytesToShort(plane, 2 * index, 2, little) & 0xffff; break; case FormatTools.INT16: value = DataTools.bytesToShort(plane, 2 * index, 2, little); break; case FormatTools.UINT32: value = DataTools.bytesToInt(plane, 4 * index, 4, little) & 0xffffffffL; break; case FormatTools.INT32: value = DataTools.bytesToInt(plane, 4 * index, 4, little); break; case FormatTools.FLOAT: value = DataTools.bytesToFloat(plane, 4 * index, 4, little); break; case FormatTools.DOUBLE: value = DataTools.bytesToDouble(plane, 8 * index, 8, little); break; default: value = Double.NaN; } return value; }
@SuppressWarnings({"rawtypes", "unchecked"}) private void populatePlane(IFormatReader r, int no, byte[] plane, PlanarAccess planarAccess) { final int pixelType = r.getPixelType(); final int bpp = FormatTools.getBytesPerPixel(pixelType); final boolean fp = FormatTools.isFloatingPoint(pixelType); final boolean little = r.isLittleEndian(); Object planeArray = DataTools.makeDataArray(plane, bpp, fp, little); if (planeArray == plane) { // array was returned by reference; make a copy final byte[] planeCopy = new byte[plane.length]; System.arraycopy(plane, 0, planeCopy, 0, plane.length); planeArray = planeCopy; } planarAccess.setPlane(no, makeArray(planeArray)); }
/* @see loci.formats.FormatReader#initFile(String) */ @Override protected void initFile(String id) throws FormatException, IOException { // read the pattern from the file // the file should just contain a single line with the relative or // absolute file pattern currentId = new Location(id).getAbsolutePath(); String pattern = DataTools.readFile(id).trim(); String dir = new Location(id).getAbsoluteFile().getParent(); if (new Location(pattern).getParent() == null) { pattern = dir + File.separator + pattern; } helper.setUsingPatternIds(true); helper.setCanChangePattern(false); helper.setId(pattern); core = helper.getCoreMetadataList(); }
/* @see loci.formats.FormatReader#initFile(String) */ protected void initFile(String id) throws FormatException, IOException { super.initFile(id); Location parent = new Location(id).getAbsoluteFile().getParentFile(); String[] lines = DataTools.readFile(currentId).split("\r\n"); for (String line : lines) { int eq = line.indexOf("="); if (eq < 0) { continue; } String key = line.substring(0, eq).trim(); String value = line.substring(eq + 1).trim(); if (key.equals("NoImages")) { ndpiFiles = new String[Integer.parseInt(value)]; readers = new ChannelSeparator[ndpiFiles.length]; } else if (key.startsWith("Image")) { int index = Integer.parseInt(key.replaceAll("Image", "")); ndpiFiles[index] = new Location(parent, value).getAbsolutePath(); readers[index] = new ChannelSeparator(new NDPIReader()); } } readers[0].setMetadataStore(getMetadataStore()); readers[0].setId(ndpiFiles[0]); core = readers[0].getCoreMetadata(); for (int i = 0; i < getSeriesCount(); i++) { core[i].sizeC = readers.length; core[i].rgb = false; core[i].imageCount = core[i].sizeC * core[i].sizeZ * core[i].sizeT; core[i].cLengths = new int[] {getSizeC()}; } MetadataStore store = makeFilterMetadata(); MetadataTools.populatePixels(store, this); }
private void writeFCTL(int width, int height) throws IOException { out.writeInt(26); byte[] b = new byte[30]; b[0] = 'f'; b[1] = 'c'; b[2] = 'T'; b[3] = 'L'; DataTools.unpackBytes(nextSequenceNumber++, b, 4, 4, false); DataTools.unpackBytes(width, b, 8, 4, false); DataTools.unpackBytes(height, b, 12, 4, false); DataTools.unpackBytes(0, b, 16, 4, false); DataTools.unpackBytes(0, b, 20, 4, false); DataTools.unpackBytes(1, b, 24, 2, false); DataTools.unpackBytes(fps, b, 26, 2, false); b[28] = (byte) 1; b[29] = (byte) 0; out.write(b); out.writeInt(crc(b)); }
private void parseROIs(MetadataStore store) throws FormatException, IOException { if (MetadataTools.isOMEXMLMetadata(store) || MetadataTools.isOMEXMLRoot(store.getRoot())) { return; } String roiID = MetadataTools.createLSID("ROI", 0, 0); String maskID = MetadataTools.createLSID("Shape", 0, 0); store.setROIID(roiID, 0); store.setMaskID(maskID, 0, 0); String positionData = DataTools.readFile(roiDrawFile); String[] coordinates = positionData.split("[ ,]"); double x1 = Double.parseDouble(coordinates[1]); double y1 = Double.parseDouble(coordinates[2]); double x2 = Double.parseDouble(coordinates[3]); double y2 = Double.parseDouble(coordinates[5]); store.setMaskX(x1, 0, 0); store.setMaskY(y1, 0, 0); store.setMaskWidth(x2 - x1, 0, 0); store.setMaskHeight(y2 - y1, 0, 0); store.setImageROIRef(roiID, 0, 0); ImageReader roiReader = new ImageReader(); roiReader.setId(roiFile); byte[] roiPixels = roiReader.openBytes(0); roiReader.close(); BitWriter bits = new BitWriter(roiPixels.length / 8); for (int i = 0; i < roiPixels.length; i++) { bits.write(roiPixels[i] == 0 ? 0 : 1, 1); } store.setMaskBinData(bits.toByteArray(), 0, 0); }
/* @see loci.formats.FormatReader#initFile(String) */ protected void initFile(String id) throws FormatException, IOException { // make sure we have the experiment file id = locateExperimentFile(id); super.initFile(id); Location dir = new Location(id).getAbsoluteFile().getParentFile(); for (String file : dir.list(true)) { Location f = new Location(dir, file); if (!f.isDirectory()) { if (checkSuffix(file, META_EXT)) { metadataFiles.add(f.getAbsolutePath()); } } } // parse Experiment metadata IniList experiment = readMetaData(id); if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) { objective = experiment.getTable("Geometry").get("Name"); IniTable camera = experiment.getTable("Camera"); binning = camera.get("BinX") + "x" + camera.get("BinY"); parseChannelData(dir); addGlobalMeta("Objective", objective); addGlobalMeta("Camera binning", binning); } Vector<String> uniqueRows = new Vector<String>(); Vector<String> uniqueColumns = new Vector<String>(); for (String well : wellLabels) { String row = well.substring(0, 1).trim(); String column = well.substring(1).trim(); if (!uniqueRows.contains(row) && row.length() > 0) uniqueRows.add(row); if (!uniqueColumns.contains(column) && column.length() > 0) { uniqueColumns.add(column); } } int nSlices = getSizeZ() == 0 ? 1 : getSizeZ(); int nTimepoints = getSizeT(); int nWells = wellLabels.size(); int nChannels = getSizeC() == 0 ? channelNames.size() : getSizeC(); if (nChannels == 0) nChannels = 1; tiffs = getTiffs(dir.getAbsolutePath()); reader = new MinimalTiffReader(); reader.setId(tiffs[0][0]); int sizeX = reader.getSizeX(); int sizeY = reader.getSizeY(); int pixelType = reader.getPixelType(); boolean rgb = reader.isRGB(); boolean interleaved = reader.isInterleaved(); boolean indexed = reader.isIndexed(); boolean littleEndian = reader.isLittleEndian(); if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) { IniParser parser = new IniParser(); for (String metadataFile : metadataFiles) { String filename = new Location(metadataFile).getName(); if (!checkSuffix(metadataFile, "txt")) { String data = DataTools.readFile(metadataFile); IniList ini = parser.parseINI(new BufferedReader(new StringReader(data))); HashMap<String, String> h = ini.flattenIntoHashMap(); for (String key : h.keySet()) { addGlobalMeta(filename + " " + key, h.get(key)); } } } } for (int i = 0; i < getSeriesCount(); i++) { core[i] = new CoreMetadata(); core[i].sizeC = nChannels; core[i].sizeZ = nSlices; core[i].sizeT = nTimepoints; core[i].sizeX = sizeX / fieldCols; core[i].sizeY = sizeY / fieldRows; core[i].pixelType = pixelType; core[i].rgb = rgb; core[i].interleaved = interleaved; core[i].indexed = indexed; core[i].littleEndian = littleEndian; core[i].dimensionOrder = "XYZTC"; core[i].imageCount = nSlices * nTimepoints * nChannels; } MetadataStore store = makeFilterMetadata(); boolean populatePlanes = getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM; MetadataTools.populatePixels(store, this, populatePlanes); String plateAcqID = MetadataTools.createLSID("PlateAcquisition", 0, 0); store.setPlateAcquisitionID(plateAcqID, 0, 0); if (fieldRows * fieldCols > 0) { store.setPlateAcquisitionMaximumFieldCount(new PositiveInteger(fieldRows * fieldCols), 0, 0); } else { LOGGER.warn("Expected positive value for MaximumFieldCount; got {}", fieldRows * fieldCols); } for (int row = 0; row < wellRows; row++) { for (int col = 0; col < wellCols; col++) { int index = row * wellCols + col; store.setWellID(MetadataTools.createLSID("Well", 0, index), 0, index); store.setWellRow(new NonNegativeInteger(row), 0, index); store.setWellColumn(new NonNegativeInteger(col), 0, index); } } for (int i = 0; i < getSeriesCount(); i++) { int well = i / (fieldRows * fieldCols); int field = i % (fieldRows * fieldCols); MetadataTools.setDefaultCreationDate(store, tiffs[well][0], i); String name = wellLabels.get(well); String row = name.substring(0, 1); Integer col = Integer.parseInt(name.substring(1)); int index = (row.charAt(0) - 'A') * wellCols + col - 1; String wellSampleID = MetadataTools.createLSID("WellSample", 0, index, field); store.setWellSampleID(wellSampleID, 0, index, field); store.setWellSampleIndex(new NonNegativeInteger(i), 0, index, field); String imageID = MetadataTools.createLSID("Image", i); store.setWellSampleImageRef(imageID, 0, index, field); store.setImageID(imageID, i); store.setImageName(name + " Field #" + (field + 1), i); store.setPlateAcquisitionWellSampleRef(wellSampleID, 0, 0, i); } MetadataLevel level = getMetadataOptions().getMetadataLevel(); if (level != MetadataLevel.MINIMUM) { String instrumentID = MetadataTools.createLSID("Instrument", 0); store.setInstrumentID(instrumentID, 0); String objectiveID = MetadataTools.createLSID("Objective", 0, 0); store.setObjectiveID(objectiveID, 0, 0); if (objective != null) { String[] tokens = objective.split(" "); String mag = tokens[0].replaceAll("[xX]", ""); String na = null; int naIndex = 0; for (int i = 0; i < tokens.length; i++) { if (tokens[i].equals("NA")) { naIndex = i + 1; na = tokens[naIndex]; break; } } Integer magnification = new Integer(mag); if (magnification > 0) { store.setObjectiveNominalMagnification(new PositiveInteger(magnification), 0, 0); } else { LOGGER.warn("Expected positive value for NominalMagnification; got {}", magnification); } if (na != null) { na = na.substring(0, 1) + "." + na.substring(1); store.setObjectiveLensNA(new Double(na), 0, 0); } if (naIndex + 1 < tokens.length) { store.setObjectiveManufacturer(tokens[naIndex + 1], 0, 0); } } // populate LogicalChannel data for (int i = 0; i < getSeriesCount(); i++) { store.setImageInstrumentRef(instrumentID, i); store.setObjectiveSettingsID(objectiveID, i); for (int c = 0; c < getSizeC(); c++) { store.setChannelName(channelNames.get(c), i, c); if (emWave[c] > 0) { store.setChannelEmissionWavelength(new PositiveInteger(emWave[c]), i, c); } else { LOGGER.warn("Expected positive value for EmissionWavelength; got {}", emWave[c]); } if (exWave[c] > 0) { store.setChannelExcitationWavelength(new PositiveInteger(exWave[c]), i, c); } else { LOGGER.warn("Expected positive value for ExcitationWavelength; got {}", exWave[c]); } String detectorID = MetadataTools.createLSID("Detector", 0, c); store.setDetectorID(detectorID, 0, c); store.setDetectorSettingsID(detectorID, i, c); store.setDetectorSettingsGain(gain[c], i, c); store.setDetectorSettingsOffset(offset[c], i, c); store.setDetectorSettingsBinning(getBinning(binning), i, c); } long firstPlane = 0; for (int p = 0; p < getImageCount(); p++) { int[] zct = getZCTCoords(p); store.setPlaneExposureTime(exposure[zct[1]], i, p); String file = getFilename(i, p); if (file != null) { long plane = getTimestamp(file); if (p == 0) { firstPlane = plane; } double timestamp = (plane - firstPlane) / 1000.0; store.setPlaneDeltaT(timestamp, i, p); } } } store.setPlateID(MetadataTools.createLSID("Plate", 0), 0); store.setPlateRowNamingConvention(getNamingConvention("Letter"), 0); store.setPlateColumnNamingConvention(getNamingConvention("Number"), 0); store.setPlateName(plateName, 0); store.setPlateDescription(plateDescription, 0); if (level != MetadataLevel.NO_OVERLAYS) { parseROIs(store); } } }