private string ReadAsciiField(BinaryReader2 reader, int numValues) { var array = reader.ReadBytes(numValues - 1); string text = Encoding.ASCII.GetString(array); return(text.Replace("\0", Environment.NewLine)); }
public TiffReader(Stream stream) { _stream = stream; _reader = new BinaryReader2(_stream, true); ReadImageFileHeader(); ImageFileDirectories = ReadImageFileDirectories(); }
private long ReadFieldOffset(BinaryReader2 reader) { if (_bigTiff) { return(reader.ReadInt64()); } else { return(reader.ReadUInt32()); } }
private T ReadFieldValue <T>(BinaryReader2 reader, FieldType fieldType) { object value = ReadFieldValueAsObject(reader, fieldType); var typeT = typeof(T); if (typeT.IsEnum) { return((T)Enum.ToObject(typeT, value)); } // if(typeT == typeof(Rational) || typeT == typeof(SRational)) // return (T)value; return((T)Convert.ChangeType(value, typeT)); }
private T[] ReadFieldValues <T>(BinaryReader2 reader, FieldType fieldType, int numValues) { var array = ReadFieldValuesAsObjects(reader, fieldType, numValues); var typeofT = typeof(T); return(array.Select(value => { if (typeofT.IsEnum) { return (T)Enum.ToObject(typeofT, value); } // if(typeofT == typeof(Rational) || typeofT == typeof(SRational)) // return (T)value; return (T)Convert.ChangeType(value, typeofT); }).ToArray()); }
private object ReadFieldValueAsObject(BinaryReader2 reader, FieldType fieldType) { switch (fieldType) { case FieldType.Int64: return(reader.ReadInt64()); case FieldType.UInt64: return(reader.ReadInt64()); case FieldType.Int32: return(reader.ReadInt32()); case FieldType.UInt32: return(reader.ReadUInt32()); case FieldType.Int16: return(reader.ReadInt16()); case FieldType.UInt16: return(reader.ReadUInt16()); case FieldType.Byte: return(reader.ReadByte()); case FieldType.SByte: return(reader.ReadSByte()); case FieldType.Float: return(reader.ReadSingle()); case FieldType.Double: return(reader.ReadDouble()); case FieldType.Rational: return(new Rational(reader.ReadUInt32(), reader.ReadUInt32())); case FieldType.SRational: return(new SRational(reader.ReadInt32(), reader.ReadInt32())); } Console.WriteLine($"Unknown field type {fieldType}"); return(0); }
private ImageFileDirectory[] ReadImageFileDirectories() { var ifdList = new List <ImageFileDirectory>(); long ifdOffset = _bigTiff ? _reader.ReadInt64() : _reader.ReadUInt32(); while (ifdOffset > 0) { _reader.Stream.Position = ifdOffset; var ifd = new ImageFileDirectory(); long numFields = _bigTiff ? _reader.ReadInt64() : _reader.ReadUInt16(); int sizeInBytes = (int)numFields * (2 + 2 + 2 * (_bigTiff ? 8 : 4)) + (_bigTiff ? 8 : 4); using (var ifdReader = new BinaryReader2(new MemoryStream(_reader.ReadBytes(sizeInBytes)))) { ifdReader.StreamIsLittleEndian = _reader.StreamIsLittleEndian; for (int i = 0; i < numFields; i++) { IfdTag tag = (IfdTag)ifdReader.ReadUInt16(); FieldType fieldType = (FieldType)ifdReader.ReadUInt16(); int numValues = _bigTiff ? (int)ifdReader.ReadInt64() : (int)ifdReader.ReadUInt32(); long pos = ifdReader.Stream.Position; switch (tag) { case IfdTag.ImageWidth: { ifd.ImageWidth = ReadFieldValue <int>(ifdReader, fieldType); } break; case IfdTag.ImageHeight: { ifd.ImageHeight = ReadFieldValue <int>(ifdReader, fieldType); } break; case IfdTag.BitsPerSample: { if (numValues == 1) { ifd.BitsPerSample = ReadFieldValue <ushort>(ifdReader, fieldType); } else { _reader.Stream.Position = ReadFieldOffset(ifdReader); var bitsPerSamples = ReadFieldValues <ushort>(_reader, fieldType, numValues); ifd.BitsPerSample = (ushort)bitsPerSamples[0]; if (bitsPerSamples.Any(bps => bps != ifd.BitsPerSample)) { throw new NotSupportedException($"BitsPerSample must be the same for all samples: {string.Join(", ", bitsPerSamples)}"); } } } break; case IfdTag.PhotometricInterpretation: { ifd.PhotometricInterpretation = ReadFieldValue <PhotometricInterpretation>(ifdReader, fieldType); } break; case IfdTag.Compression: { ifd.Compression = ReadFieldValue <Compression>(ifdReader, fieldType); } break; case IfdTag.SamplesPerPixel: { ifd.SamplesPerPixel = ReadFieldValue <ushort>(ifdReader, fieldType); } break; case IfdTag.RowsPerStrip: { ifd.RowsPerStrip = ReadFieldValue <uint>(ifdReader, fieldType); } break; case IfdTag.PlanarConfiguration: { ifd.PlanarConfiguration = ReadFieldValue <PlanarConfiguration>(ifdReader, fieldType); } break; case IfdTag.SampleFormat: { ifd.SampleFormat = ReadFieldValue <SampleFormat>(ifdReader, fieldType); } break; case IfdTag.StripOffsets: { if (numValues == 1) { ifd.StripOffsets = new[] { ReadFieldValue <long>(ifdReader, fieldType) }; } else { _reader.Stream.Position = ReadFieldValue <long>(ifdReader, fieldType); ifd.StripOffsets = ReadFieldValues <long>(_reader, fieldType, numValues); } } break; case IfdTag.StripByteCounts: { if (numValues == 1) { ifd.StripByteCounts = new[] { ReadFieldValue <long>(ifdReader, fieldType) }; } else { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.StripByteCounts = ReadFieldValues <long>(_reader, fieldType, numValues); } } break; case IfdTag.Artist: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.Artist = ReadAsciiField(_reader, numValues); } break; case IfdTag.Copyright: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.Copyright = ReadAsciiField(_reader, numValues); } break; case IfdTag.DateTime: { _reader.Stream.Position = ReadFieldOffset(ifdReader); string text = ReadAsciiField(_reader, numValues); DateTime.TryParseExact(text, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out ifd.DateTime); } break; case IfdTag.ExtraSamples: { ifd.ExtraSamples = ReadFieldValue <ushort>(ifdReader, fieldType); } break; case IfdTag.HostComputer: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.HostComputer = ReadAsciiField(_reader, numValues); } break; case IfdTag.ImageDescription: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.ImageDescription = ReadAsciiField(_reader, numValues); } break; case IfdTag.Make: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.Make = ReadAsciiField(_reader, numValues); } break; case IfdTag.Model: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.Model = ReadAsciiField(_reader, numValues); } break; case IfdTag.Orientation: { ifd.Orientation = ReadFieldValue <ushort>(ifdReader, fieldType); } break; case IfdTag.Software: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.Software = ReadAsciiField(_reader, numValues); } break; case IfdTag.DocumentName: { _reader.Stream.Position = ReadFieldOffset(ifdReader); ifd.DocumentName = ReadAsciiField(_reader, numValues); } break; case IfdTag.FillOrder: { ifd.FillOrder = ReadFieldValue <ushort>(ifdReader, fieldType); } break; default: { if (numValues == 1) { object value = ReadFieldValueAsObject(ifdReader, fieldType); ifd.Entries[tag] = new IfdEntry { Tag = tag, FieldType = fieldType, Value = value }; Console.WriteLine($"Tag: {tag} Type: {fieldType} NumValues: {numValues} Value: {value}"); } else { long offset = ReadFieldOffset(ifdReader); ifd.Entries[tag] = new IfdEntry { Tag = tag, FieldType = fieldType, Offset = offset }; Console.WriteLine($"Tag: {tag} Type: {fieldType} NumValues: {numValues} Offset: {offset}"); } } break; } ifdReader.Stream.Position = pos + (_bigTiff ? 8 : 4); } if (_bigTiff) { ifdOffset = ifdReader.ReadInt64(); } else { ifdOffset = ifdReader.ReadUInt32(); } } ifdList.Add(ifd); } return(ifdList.ToArray()); }
private object[] ReadFieldValuesAsObjects(BinaryReader2 reader, FieldType fieldType, int numValues) { var array = new object[numValues]; switch (fieldType) { case FieldType.Int64: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadInt64(); } } break; case FieldType.UInt64: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadInt64(); } } break; case FieldType.Int32: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadInt32(); } } break; case FieldType.UInt32: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadUInt32(); } } break; case FieldType.Int16: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadInt16(); } } break; case FieldType.UInt16: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadUInt16(); } } break; case FieldType.SByte: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadSByte(); } } break; case FieldType.Byte: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadByte(); } } break; case FieldType.Float: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadSingle(); } } break; case FieldType.Double: { for (int i = 0; i < numValues; i++) { array[i] = reader.ReadDouble(); } } break; case FieldType.Rational: { for (int i = 0; i < numValues; i++) { array[i] = new Rational(reader.ReadUInt32(), reader.ReadUInt32()); } } break; case FieldType.SRational: { for (int i = 0; i < numValues; i++) { array[i] = new SRational(reader.ReadInt32(), reader.ReadInt32()); } } break; default: throw new Exception($"Unknown field type {fieldType}"); } return(array); }