private double readValue(BinaryReaderMixedEndian reader, int type) { switch (type) { case SHORT: case USHORT: return(reader.ReadInt16()); case INT: case UINT: if (adjustEndianness) { reader.SetEndian(!reader.IsLittleEndian); } int i = reader.ReadInt32(); if (adjustEndianness) { reader.SetEndian(!reader.IsLittleEndian); } return(i); case FLOAT: if (adjustEndianness) { reader.SetEndian(!reader.IsLittleEndian); } float f = reader.ReadSingle(); if (adjustEndianness) { reader.SetEndian(!reader.IsLittleEndian); } return(f); case DOUBLE: if (adjustEndianness) { reader.SetEndian(!reader.IsLittleEndian); } double dbl = reader.ReadDouble(); if (adjustEndianness) { reader.SetEndian(!reader.IsLittleEndian); } return(dbl); case BYTE: case UBYTE: case CHAR: return(reader.ReadByte()); case UNKNOWN: case UNKNOWN2: return(reader.ReadInt64()); } return(0); }
private void parseTags(BinaryReaderMixedEndian reader, int numTags, string parent, string indent) { for (int i = 0; i < numTags; i++) { if (reader.BaseStream.Position + 3 >= reader.BaseStream.Length) { break; } byte type = reader.ReadByte(); // can be 21 (data) or 20 (tag group) int length = reader.ReadInt16(); // image data is in tag with type 21 and label 'Data' // image dimensions are in type 20 tag with 2 type 15 tags // bytes per pixel is in type 21 tag with label 'PixelDepth' String labelString = null; String value = null; if (type == VALUE) { labelString = FromByteArray(reader, length); skipPadding(reader); skipPadding(reader); int skip = reader.ReadInt32(); // equal to '%%%%' / 623191333 skipPadding(reader); int n = reader.ReadInt32(); skipPadding(reader); int dataType = reader.ReadInt32(); string sb = labelString; if (sb.Length > 32) { sb = sb.Substring(0, 20) + "... (" + sb.Length + ")"; } //LOGGER.debug("{}{}: n={}, dataType={}, label={}", // new Object[] // { // indent, // i, // n, // dataType, // sb // }); if (skip != 623191333) { Debug.WriteLine("Skip mismatch: {}", skip); } if (n == 1) { if ("Dimensions".Equals(parent) && labelString.Length == 0) { if (adjustEndianness) { Reader.SetEndian(!Reader.IsLittleEndian); } if (i == 0) { Dimensions.X = reader.ReadInt32(); } else if (i == 1) { Dimensions.Y = reader.ReadInt32(); } else if (i == 2) { Dimensions.Z = reader.ReadInt32(); } if (adjustEndianness) { Reader.SetEndian(!Reader.IsLittleEndian); } } else { value = readValue(reader, dataType).ToString(CultureInfo.InvariantCulture); } } else if (n == 2) { if (dataType == 18) { // this should always be true length = reader.ReadInt32(); } else { //LOGGER.warn("dataType mismatch: {}", dataType); } value = FromByteArray(reader, length); } else if (n == 3) { if (dataType == GROUP) { // this should always be true skipPadding(reader); dataType = reader.ReadInt32(); long dataLength = 0; if (version == 4) { dataLength = reader.ReadInt64(); } else { dataLength = reader.ReadInt32(); } length = (int)(dataLength & 0xffffffff); if (labelString.Equals("Data")) { if (dataLength > 0) { pixelOffset = reader.BaseStream.Position; reader.BaseStream.Seek(reader.BaseStream.Position + getNumBytes(dataType) * dataLength, SeekOrigin.Begin); numPixelBytes = reader.BaseStream.Position - pixelOffset; } } else { if (dataType == 10) { reader.ReadBytes(length); } else { value = FromByteArray(reader, length * 2); } } } else { //LOGGER.warn("dataType mismatch: {}", dataType); } } else { // this is a normal struct of simple types if (dataType == ARRAY) { reader.ReadBytes(4); skipPadding(reader); skipPadding(reader); int numFields = reader.ReadInt32(); long startFP = reader.BaseStream.Position; StringBuilder s = new StringBuilder(); reader.ReadBytes(4); skipPadding(reader); long baseFP = reader.BaseStream.Position; if (version == 4) { baseFP += 4; } int width = version == 4 ? 16 : 8; for (int j = 0; j < numFields; j++) { reader.BaseStream.Seek(baseFP + j * width, SeekOrigin.Begin); dataType = reader.ReadInt32(); reader.BaseStream.Seek(startFP + numFields * width + j * getNumBytes(dataType), SeekOrigin.Begin); s.Append(readValue(reader, dataType)); if (j < numFields - 1) { s.Append(", "); } } value = s.ToString(); } else if (dataType == GROUP) { // this is an array of structs skipPadding(reader); dataType = reader.ReadInt32(); if (dataType == ARRAY) { // should always be true reader.ReadBytes(4); skipPadding(reader); skipPadding(reader); int numFields = reader.ReadInt32(); int[] dataTypes = new int[numFields]; long baseFP = reader.BaseStream.Position + 12; for (int j = 0; j < numFields; j++) { reader.ReadBytes(4); if (version == 4) { reader.BaseStream.Seek(baseFP + j * 16, SeekOrigin.Begin); } dataTypes[j] = reader.ReadInt32(); } skipPadding(reader); int len = reader.ReadInt32(); double[][] values = Helper.ArrayOfFunction(a => new double[len], numFields); for (int k = 0; k < len; k++) { for (int q = 0; q < numFields; q++) { values[q][k] = readValue(reader, dataTypes[q]); } } } else { //LOGGER.warn("dataType mismatch: {}", dataType); } } } } else if (type == GROUP) { labelString = FromByteArray(reader, length); reader.ReadBytes(2); skipPadding(reader); skipPadding(reader); skipPadding(reader); int num = reader.ReadInt32(); //LOGGER.debug("{}{}: group({}) {} {", new Object[] { indent, i, num, labelString }); parseTags(reader, num, string.IsNullOrEmpty(labelString) ? parent : labelString, indent + " "); //LOGGER.debug("{}}", indent); } else { //LOGGER.debug("{}{}: unknown type: {}", new Object[] { indent, i, type }); } if (value != null) { bool validPhysicalSize = parent != null && (parent.Equals("Dimension") || ((pixelSizes.Count() == 4 || units.Count() == 4) && parent.Equals("2"))); if (labelString.Equals("Scale") && validPhysicalSize) { if (value.IndexOf(',') == -1) { pixelSizes.Add(double.Parse(value, CultureInfo.InvariantCulture)); } } else if (labelString.Equals("Units") && validPhysicalSize) { // make sure that we don't add more units than sizes if (pixelSizes.Count() == units.Count() + 1) { units.Add(value); } } else if (labelString.Equals("LowLimit")) { signed = double.Parse(value, CultureInfo.InvariantCulture) < 0; } else if (labelString.Equals("Acquisition Start Time (epoch)")) { timestamp = long.Parse(value, CultureInfo.InvariantCulture); } else if (labelString.Equals("Voltage")) { voltage = double.Parse(value, CultureInfo.InvariantCulture); } else if (labelString.Equals("Microscope Info")) { info = value; } else if (labelString.Equals("Indicated Magnification")) { mag = double.Parse(value, CultureInfo.InvariantCulture); } else if (labelString.Equals("Gamma")) { gamma = double.Parse(value, CultureInfo.InvariantCulture); } else if (labelString.StartsWith("xPos")) { double number = double.Parse(value, CultureInfo.InvariantCulture); posX = number; } else if (labelString.StartsWith("yPos")) { double number = double.Parse(value, CultureInfo.InvariantCulture); posY = number; } else if (labelString.StartsWith("Specimen position")) { double number = double.Parse(value, CultureInfo.InvariantCulture); posZ = number; } else if (labelString == "Sample Time") { sampleTime = double.Parse(value, CultureInfo.InvariantCulture); } else if (labelString == "DataType") { int pixelType = int.Parse(value); switch (pixelType) { case 1: ValueType = typeof(short); break; case 10: ValueType = typeof(ushort); break; case 2: ValueType = typeof(float); break; case 12: ValueType = typeof(double); break; case 9: ValueType = typeof(byte); break; case 6: ValueType = typeof(byte); break; case 7: ValueType = typeof(int); break; case 11: ValueType = typeof(uint); break; } } value = null; } } }