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)); }
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()); }