public void SRational3()
        {
            var r3 = new SRational(0, -17);

            Assert.AreEqual(0, r3.Numerator);
            Assert.AreEqual(-17, r3.Denominator);
            Assert.AreEqual(0.0d / -17.0d, (double)r3);
            Assert.AreEqual("0/1", r3.ToString());

            Assert.AreEqual(0, r3.Reduce().Numerator);
            Assert.AreEqual(1, r3.Reduce().Denominator);
        }
        public void SRational4()
        {
            var r4 = new SRational(-108, -46);

            Assert.AreEqual(-108, r4.Numerator);
            Assert.AreEqual(-46, r4.Denominator);
            Assert.AreEqual(-108.0d / -46.0d, (double)r4);
            Assert.AreEqual("54/23", r4.ToString());

            Assert.AreEqual(54, r4.Reduce().Numerator);
            Assert.AreEqual(23, r4.Reduce().Denominator);
        }
        public void SRational1()
        {
            var r1 = new SRational(5, 3);

            Assert.AreEqual(5, r1.Numerator);
            Assert.AreEqual(3, r1.Denominator);
            Assert.AreEqual(5.0d / 3.0d, (double)r1);
            Assert.AreEqual("5/3", r1.ToString());

            Assert.AreEqual(5, r1.Reduce().Numerator);
            Assert.AreEqual(3, r1.Reduce().Denominator);
        }
        public void SRational2()
        {
            var r2 = new SRational(48, 18);

            Assert.AreEqual(48, r2.Numerator);
            Assert.AreEqual(18, r2.Denominator);
            Assert.AreEqual(48.0d / 18.0d, (double)r2);
            Assert.AreEqual("8/3", r2.ToString());

            Assert.AreEqual(8, r2.Reduce().Numerator);
            Assert.AreEqual(3, r2.Reduce().Denominator);
        }
        public void SRational5()
        {
            var r5 = new SRational(-256, 96);

            Assert.AreEqual(-256, r5.Numerator);
            Assert.AreEqual(96, r5.Denominator);
            Assert.AreEqual(-256.0d / 96.0d, (double)r5);
            Assert.AreEqual("-8/3", r5.ToString());

            Assert.AreEqual(-8, r5.Reduce().Numerator);
            Assert.AreEqual(3, r5.Reduce().Denominator);
        }
Exemplo n.º 6
0
        /// <summary>
        ///    Creates an IFDEntry from the given values. This method is used for
        ///    every entry. Custom parsing can be hooked in by overriding the
        ///    <see cref="ParseIFDEntry(ushort,ushort,uint,long,uint)"/> method.
        /// </summary>
        /// <param name="tag">
        ///    A <see cref="System.UInt16"/> with the tag of the entry.
        /// </param>
        /// <param name="type">
        ///    A <see cref="System.UInt16"/> with the type of the entry.
        /// </param>
        /// <param name="count">
        ///    A <see cref="System.UInt32"/> with the data count of the entry.
        /// </param>
        /// <param name="baseOffset">
        ///    A <see cref="System.Int64"/> with the base offset which every
        ///    offsets in the IFD are relative to.
        /// </param>
        /// <param name="offsetData">
        ///    A <see cref="ByteVector"/> containing exactly 4 byte with the data
        ///    of the offset of the entry. Since this field isn't interpreted as
        ///    an offset if the data can be directly stored in the 4 byte, we
        ///    pass the <see cref="ByteVector"/> to easier interpret it.
        /// </param>
        /// <param name="maxOffset">
        ///    A <see cref="System.UInt32"/> with the maximal offset to consider for
        ///    the IFD.
        /// </param>
        /// <returns>
        ///    A <see cref="IFDEntry"/> with the given parameter.
        /// </returns>
        IFDEntry CreateIFDEntry(ushort tag, ushort type, uint count, long baseOffset, ByteVector offsetData, uint maxOffset)
        {
            uint offset = offsetData.ToUInt(is_bigendian);

            // Fix the type for the IPTC tag.
            // From http://www.awaresystems.be/imaging/tiff/tifftags/iptc.html
            // "Often times, the datatype is incorrectly specified as LONG. "
            if (tag == (ushort)IFDEntryTag.IPTC && type == (ushort)IFDEntryType.Long)
            {
                type = (ushort)IFDEntryType.Byte;
            }

            var ifd_entry = ParseIFDEntry(tag, type, count, baseOffset, offset);

            if (ifd_entry != null)
            {
                return(ifd_entry);
            }

            if (count > 0x10000000)
            {
                // Some Nikon files are known to exhibit this corruption (or "feature").
                file.MarkAsCorrupt("Impossibly large item count");
                return(null);
            }

            // then handle the values stored in the offset data itself
            if (count == 1)
            {
                if (type == (ushort)IFDEntryType.Byte)
                {
                    return(new ByteIFDEntry(tag, offsetData[0]));
                }

                if (type == (ushort)IFDEntryType.SByte)
                {
                    return(new SByteIFDEntry(tag, (sbyte)offsetData[0]));
                }

                if (type == (ushort)IFDEntryType.Short)
                {
                    return(new ShortIFDEntry(tag, offsetData.Mid(0, 2).ToUShort(is_bigendian)));
                }

                if (type == (ushort)IFDEntryType.SShort)
                {
                    return(new SShortIFDEntry(tag, offsetData.Mid(0, 2).ToUShort(is_bigendian)));
                }

                if (type == (ushort)IFDEntryType.Long)
                {
                    return(new LongIFDEntry(tag, offsetData.ToUInt(is_bigendian)));
                }

                if (type == (ushort)IFDEntryType.SLong)
                {
                    return(new SLongIFDEntry(tag, offsetData.ToInt(is_bigendian)));
                }
            }

            if (count == 2)
            {
                if (type == (ushort)IFDEntryType.Short)
                {
                    ushort[] data = new[] {
                        offsetData.Mid(0, 2).ToUShort(is_bigendian),
                        offsetData.Mid(2, 2).ToUShort(is_bigendian)
                    };

                    return(new ShortArrayIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.SShort)
                {
                    short[] data = new[] {
                        (short)offsetData.Mid(0, 2).ToUShort(is_bigendian),
                        (short)offsetData.Mid(2, 2).ToUShort(is_bigendian)
                    };

                    return(new SShortArrayIFDEntry(tag, data));
                }
            }

            if (count <= 4)
            {
                if (type == (ushort)IFDEntryType.Undefined)
                {
                    return(new UndefinedIFDEntry(tag, offsetData.Mid(0, (int)count)));
                }

                if (type == (ushort)IFDEntryType.Ascii)
                {
                    string data = offsetData.Mid(0, (int)count).ToString();
                    int    term = data.IndexOf('\0');

                    if (term > -1)
                    {
                        data = data.Substring(0, term);
                    }

                    return(new StringIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.Byte)
                {
                    return(new ByteVectorIFDEntry(tag, offsetData.Mid(0, (int)count)));
                }
            }


            // FIXME: create correct type.
            if (offset > maxOffset)
            {
                return(new UndefinedIFDEntry(tag, new ByteVector()));
            }

            // then handle data referenced by the offset
            file.Seek(baseOffset + offset, SeekOrigin.Begin);

            if (count == 1)
            {
                if (type == (ushort)IFDEntryType.Rational)
                {
                    return(new RationalIFDEntry(tag, ReadRational()));
                }

                if (type == (ushort)IFDEntryType.SRational)
                {
                    return(new SRationalIFDEntry(tag, ReadSRational()));
                }
            }

            if (count > 1)
            {
                if (type == (ushort)IFDEntryType.Long)
                {
                    uint[] data = ReadUIntArray(count);

                    return(new LongArrayIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.SLong)
                {
                    int[] data = ReadIntArray(count);

                    return(new SLongArrayIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.Rational)
                {
                    var entries = new Rational[count];

                    for (int i = 0; i < count; i++)
                    {
                        entries[i] = ReadRational();
                    }

                    return(new RationalArrayIFDEntry(tag, entries));
                }

                if (type == (ushort)IFDEntryType.SRational)
                {
                    var entries = new SRational[count];

                    for (int i = 0; i < count; i++)
                    {
                        entries[i] = ReadSRational();
                    }

                    return(new SRationalArrayIFDEntry(tag, entries));
                }
            }

            if (count > 2)
            {
                if (type == (ushort)IFDEntryType.Short)
                {
                    ushort[] data = ReadUShortArray(count);

                    return(new ShortArrayIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.SShort)
                {
                    short[] data = ReadShortArray(count);

                    return(new SShortArrayIFDEntry(tag, data));
                }
            }

            if (count > 4)
            {
                if (type == (ushort)IFDEntryType.Long)
                {
                    uint[] data = ReadUIntArray(count);

                    return(new LongArrayIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.Byte)
                {
                    ByteVector data = file.ReadBlock((int)count);

                    return(new ByteVectorIFDEntry(tag, data));
                }

                if (type == (ushort)IFDEntryType.Ascii)
                {
                    string data = ReadAsciiString((int)count);

                    return(new StringIFDEntry(tag, data));
                }

                if (tag == (ushort)ExifEntryTag.UserComment)
                {
                    ByteVector data = file.ReadBlock((int)count);

                    return(new UserCommentIFDEntry(tag, data, file));
                }

                if (type == (ushort)IFDEntryType.Undefined)
                {
                    ByteVector data = file.ReadBlock((int)count);

                    return(new UndefinedIFDEntry(tag, data));
                }
            }

            if (type == (ushort)IFDEntryType.Float)
            {
                return(null);
            }

            if (type == 0 || type > 12)
            {
                // Invalid type
                file.MarkAsCorrupt("Invalid item type");
                return(null);
            }

            throw new NotImplementedException($"Unknown type/count {type}/{count} ({offset})");
        }
Exemplo n.º 7
0
		/// <summary>
		///    Construcor.
		/// </summary>
		/// <param name="tag">
		///    A <see cref="System.UInt16"/> with the tag ID of the entry this instance
		///    represents
		/// </param>
		/// <param name="value">
		///    A <see cref="SRational"/> to be stored
		/// </param>
		public SRationalIFDEntry (ushort tag, SRational value)
		{
			Tag = tag;
			Value = value;
		}
Exemplo n.º 8
0
        public static T GetQuery <T>(this BitmapMetadata bitmapMetadata, string query)
        {
            // Return default if the BitmapMetadata doesn't contain the query
            // Would prefer to return null
            if (!bitmapMetadata.ContainsQuery(query))
            {
                return(default(T));
            }

            // Grab object
            object unknownObject = bitmapMetadata.GetQuery(query);

            if (unknownObject == null)
            {
                return(default(T));
            }
            else if (typeof(T) == typeof(SRational))
            {
                if (unknownObject.GetType() == bitmapMetadata.GetStorageType(typeof(SRational)))
                {
                    // Create new Rational, casting the unknownobject as an Int64
                    SRational rational = new SRational((Int64)unknownObject);

                    // Convert back to typeof(T)
                    return((T)Convert.ChangeType(rational, typeof(T)));
                }
                else
                {
                    return(default(T));
                }
            }
            else if (typeof(T) == typeof(URational))
            {
                if (unknownObject.GetType() == bitmapMetadata.GetStorageType(typeof(URational)))
                {
                    // Create new URational, casting the unknownobject as an UInt64
                    URational urational = new URational((UInt64)unknownObject);

                    // Convert back to typeof(T)
                    return((T)Convert.ChangeType(urational, typeof(T)));
                }
                else
                {
                    return(default(T));
                }
            }
            else if (typeof(T) == typeof(URationalTriplet))
            {
                if (unknownObject.GetType() == bitmapMetadata.GetStorageType(typeof(URationalTriplet)))
                {
                    // Create new GpsRational, casting the unknownobject as an Int64[]
                    URationalTriplet gpsRational = new URationalTriplet((UInt64[])unknownObject);

                    // Convert back to typeof(T)
                    return((T)Convert.ChangeType(gpsRational, typeof(T)));
                }
                else
                {
                    return(default(T));
                }
            }
            else if (typeof(T) == typeof(ExifDateTime))
            {
                // Create new ExifDateTime, casting the unknownobject as a string
                ExifDateTime exifDateTime = new ExifDateTime(unknownObject.ToString());

                // Convert back to typeof(T)
                return((T)Convert.ChangeType(exifDateTime, typeof(T)));
            }
            else if (typeof(T) == typeof(TimeSpan))
            {
                string timespanString = (unknownObject as string);

                if (!timespanString.EndsWith("+0000"))
                {
                    throw new NotImplementedException("Timespan contains timezone, need to implement the right code");
                }
                else if (timespanString.Length > 6)
                {
                    int hour   = Convert.ToInt32(timespanString.Substring(0, 2));
                    int minute = Convert.ToInt32(timespanString.Substring(2, 2));
                    int second = Convert.ToInt32(timespanString.Substring(4, 2));

                    TimeSpan timeSpan = new TimeSpan(hour, minute, second);

                    return((T)Convert.ChangeType(timeSpan, typeof(T)));
                }
                else
                {
                    return(default(T));
                }
            }
            else if (typeof(T) == typeof(DateTime))
            {
                // Split the string into date & time
                // Convert T to a space
                string[] dateTimeString = (unknownObject as string).Replace("T", " ").Split(' ');

                if (dateTimeString.Length == 1 && dateTimeString[0].Length == 8)
                {
                    int year  = Convert.ToInt32(dateTimeString[0].Substring(0, 4));
                    int month = Convert.ToInt32(dateTimeString[0].Substring(4, 2));
                    int day   = Convert.ToInt32(dateTimeString[0].Substring(6, 2));

                    DateTime dateTime = new DateTime(year, month, day);

                    return((T)Convert.ChangeType(dateTime, typeof(T)));
                }
                else if (dateTimeString.Length == 2)
                {
                    // Ensure seperate is dash for Date
                    dateTimeString[0] = dateTimeString[0].Replace(":", "-");

                    // Strip the Z from the Time
                    dateTimeString[1] = dateTimeString[1].TrimEnd('Z');

                    DateTime dateTime = DateTime.Parse(dateTimeString[0] + " " + dateTimeString[1]);

                    // Parse as local time
                    DateTime localDateTime = new DateTime(dateTime.Ticks, DateTimeKind.Local);

                    // Convert back to typeof(T)
                    return((T)Convert.ChangeType(localDateTime, typeof(T)));
                }

                return(default(T));
            }
            else if (typeof(T) == typeof(string))
            {
                // Trim the string
                return((T)Convert.ChangeType(unknownObject.ToString().Trim(), typeof(T)));
            }
            else if (!typeof(T).IsAssignableFrom(unknownObject.GetType()))
            {
                // Throw exception if the object is the wrong type
                throw new System.ArgumentException("Query \"" + query + "\" has type \"" + unknownObject.GetType().ToString() + "\" not expected type \"" + typeof(T).ToString() + "\"");
            }

            return((T)unknownObject);
        }
 /// <summary>
 ///    Construcor.
 /// </summary>
 /// <param name="tag">
 ///    A <see cref="System.UInt16"/> with the tag ID of the entry this instance
 ///    represents
 /// </param>
 /// <param name="value">
 ///    A <see cref="SRational"/> to be stored
 /// </param>
 public SRationalIFDEntry(ushort tag, SRational value)
 {
     Tag   = tag;
     Value = value;
 }
Exemplo n.º 10
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);
        }
Exemplo n.º 11
0
        private IFDEntry CreateIFDEntry(ushort tag, ushort type, uint count, long base_offset, ByteVector offset_data, uint max_offset)
        {
            uint offset = offset_data.ToUInt(is_bigendian);

            if (tag == (ushort)IFDEntryTag.IPTC && type == (ushort)IFDEntryType.Long)
            {
                type = (ushort)IFDEntryType.Byte;
            }
            var ifd_entry = ParseIFDEntry(tag, type, count, base_offset, offset);

            if (ifd_entry != null)
            {
                return(ifd_entry);
            }
            if (count > 0x10000000)
            {
                file.MarkAsCorrupt("Impossibly large item count");
                return(null);
            }
            if (count == 1)
            {
                if (type == (ushort)IFDEntryType.Byte)
                {
                    return(new ByteIFDEntry(tag, offset_data[0]));
                }
                if (type == (ushort)IFDEntryType.SByte)
                {
                    return(new SByteIFDEntry(tag, (sbyte)offset_data[0]));
                }
                if (type == (ushort)IFDEntryType.Short)
                {
                    return(new ShortIFDEntry(tag, offset_data.Mid(0, 2).ToUShort(is_bigendian)));
                }
                if (type == (ushort)IFDEntryType.SShort)
                {
                    return(new SShortIFDEntry(tag, (ushort)offset_data.Mid(0, 2).ToUShort(is_bigendian)));
                }
                if (type == (ushort)IFDEntryType.Long)
                {
                    return(new LongIFDEntry(tag, offset_data.ToUInt(is_bigendian)));
                }
                if (type == (ushort)IFDEntryType.SLong)
                {
                    return(new SLongIFDEntry(tag, offset_data.ToInt(is_bigendian)));
                }
            }
            if (count == 2)
            {
                if (type == (ushort)IFDEntryType.Short)
                {
                    ushort[] data = new ushort[]
                    {
                        offset_data.Mid(0, 2).ToUShort(is_bigendian), offset_data.Mid(2, 2).ToUShort(is_bigendian)
                    };
                    return(new ShortArrayIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.SShort)
                {
                    short[] data = new short[]
                    {
                        (short)offset_data.Mid(0, 2).ToUShort(is_bigendian), (short)offset_data.Mid(2, 2).ToUShort(is_bigendian)
                    };
                    return(new SShortArrayIFDEntry(tag, data));
                }
            }
            if (count <= 4)
            {
                if (type == (ushort)IFDEntryType.Undefined)
                {
                    return(new UndefinedIFDEntry(tag, offset_data.Mid(0, (int)count)));
                }
                if (type == (ushort)IFDEntryType.Ascii)
                {
                    string data = offset_data.Mid(0, (int)count).ToString();
                    int    term = data.IndexOf('\0');
                    if (term > -1)
                    {
                        data = data.Substring(0, term);
                    }
                    return(new StringIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.Byte)
                {
                    return(new ByteVectorIFDEntry(tag, offset_data.Mid(0, (int)count)));
                }
            }
            if (offset > max_offset)
            {
                return(new UndefinedIFDEntry(tag, new ByteVector()));
            }
            file.Seek(base_offset + offset, SeekOrigin.Begin);
            if (count == 1)
            {
                if (type == (ushort)IFDEntryType.Rational)
                {
                    return(new RationalIFDEntry(tag, ReadRational()));
                }
                if (type == (ushort)IFDEntryType.SRational)
                {
                    return(new SRationalIFDEntry(tag, ReadSRational()));
                }
            }
            if (count > 1)
            {
                if (type == (ushort)IFDEntryType.Long)
                {
                    uint[] data = ReadUIntArray(count);
                    return(new LongArrayIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.SLong)
                {
                    int[] data = ReadIntArray(count);
                    return(new SLongArrayIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.Rational)
                {
                    Rational[] entries = new Rational[count];
                    for (int i = 0; i < count; i++)
                    {
                        entries[i] = ReadRational();
                    }
                    return(new RationalArrayIFDEntry(tag, entries));
                }
                if (type == (ushort)IFDEntryType.SRational)
                {
                    SRational[] entries = new SRational[count];
                    for (int i = 0; i < count; i++)
                    {
                        entries[i] = ReadSRational();
                    }
                    return(new SRationalArrayIFDEntry(tag, entries));
                }
            }
            if (count > 2)
            {
                if (type == (ushort)IFDEntryType.Short)
                {
                    ushort[] data = ReadUShortArray(count);
                    return(new ShortArrayIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.SShort)
                {
                    short[] data = ReadShortArray(count);
                    return(new SShortArrayIFDEntry(tag, data));
                }
            }
            if (count > 4)
            {
                if (type == (ushort)IFDEntryType.Long)
                {
                    uint[] data = ReadUIntArray(count);
                    return(new LongArrayIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.Byte)
                {
                    ByteVector data = file.ReadBlock((int)count);
                    return(new ByteVectorIFDEntry(tag, data));
                }
                if (type == (ushort)IFDEntryType.Ascii)
                {
                    string data = ReadAsciiString((int)count);
                    return(new StringIFDEntry(tag, data));
                }
                if (tag == (ushort)ExifEntryTag.UserComment)
                {
                    ByteVector data = file.ReadBlock((int)count);
                    return(new UserCommentIFDEntry(tag, data, file));
                }
                if (type == (ushort)IFDEntryType.Undefined)
                {
                    ByteVector data = file.ReadBlock((int)count);
                    return(new UndefinedIFDEntry(tag, data));
                }
            }
            if (type == (ushort)IFDEntryType.Float)
            {
                return(null);
            }
            if (type == 0 || type > 12)
            {
                file.MarkAsCorrupt("Invalid item type");
                return(null);
            }
            throw new NotImplementedException(String.Format("Unknown type/count {0}/{1} ({2})", type, count, offset));
        }
Exemplo n.º 12
0
 private void WriteSRational(SRational value)
 {
     WriteLong(value.Numerator);
     WriteLong(value.Denominator);
 }