Beispiel #1
0
        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
            }
        }
Beispiel #2
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);
        }
Beispiel #3
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());
        }
Beispiel #4
0
        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);
        }