private void ReadImageFileHeader() { _reader.Stream.Position = 0; short byteOrder = _reader.ReadInt16(); if (byteOrder == 0x4949) { _reader.StreamIsLittleEndian = true; } else if (byteOrder == 0x4d4d) { _reader.StreamIsLittleEndian = false; } else { throw new Exception($"Not a TIFF file: {byteOrder}"); } short meaningOfLife = _reader.ReadInt16(); if (meaningOfLife == 42) { _bigTiff = false; } else if (meaningOfLife == 43) { _bigTiff = true; } else { throw new Exception($"Not a TIFF file. Life: {meaningOfLife}"); } if (_bigTiff) { if (_reader.ReadUInt16() != 8) { throw new Exception("Offset should be size 8 in BigTIFF"); } _reader.ReadUInt16(); // always 0 } }
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); }