Representation of an unsigned rational value
コード例 #1
0
		public void Rational3 ()
		{
			Rational r3 = new Rational (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);
		}
コード例 #2
0
		public void Rational2 ()
		{
			Rational r2 = new Rational (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);
		}
コード例 #3
0
		public void Rational1 ()
		{
			Rational r1 = new Rational (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);
		}
コード例 #4
0
ファイル: IFDReader.cs プロジェクト: JohnThomson/taglib-sharp
		/// <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="base_offset">
		///    A <see cref="System.Int64"/> with the base offset which every
		///    offsets in the IFD are relative to.
		/// </param>
		/// <param name="offset_data">
		///    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="max_offset">
		///    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>
		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);

			// 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, base_offset, 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, 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, (short) 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));
			}


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

			// then handle data referenced by the offset
			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) {
				// Invalid type
				file.MarkAsCorrupt ("Invalid item type");
				return null;
			}

			// TODO: We should ignore unreadable values, erroring for now until we have sufficient coverage.
			throw new NotImplementedException (String.Format ("Unknown type/count {0}/{1} ({2})", type, count, offset));
		}
コード例 #5
0
        /// <summary>
        ///    Adds a <see cref="Entries.RationalIFDEntry"/> to the directory with tag
        ///    given by <paramref name="entry_tag"/> and value given by <paramref name="value"/>
        /// </summary>
        /// <param name="directory">
        ///    A <see cref="System.Int32"/> with the number of the directory
        ///    to add the entry to.
        /// </param>
        /// <param name="entry_tag">
        ///    A <see cref="System.UInt16"/> with the tag of the entry
        /// </param>
        /// <param name="value">
        ///    A <see cref="System.Double"/> with the value to add. It must be possible to
        ///    represent the value by a <see cref="Entries.Rational"/>.
        /// </param>
        public void SetRationalValue(int directory, ushort entry_tag, double value)
        {
            if (value < 0.0d || value > (double)UInt32.MaxValue)
                throw new ArgumentException ("value");

            uint scale = (value >= 1.0d) ? 1 : UInt32.MaxValue;

            Rational rational = new Rational ((uint) (scale * value), scale);

            SetEntry (directory, new RationalIFDEntry (entry_tag, rational));
        }
コード例 #6
0
ファイル: IFDTag.cs プロジェクト: JohnThomson/taglib-sharp
		/// <summary>
		///    Converts a given (positive) angle value to three rationals like they
		///    are used to store an angle for GPS data.
		/// </summary>
		/// <param name="angle">
		///    A <see cref="System.Double"/> between 0.0d and 180.0d with the angle
		///    in degrees
		/// </param>
		/// <returns>
		///    A <see cref="Rational"/> representing the same angle by degree, minutes
		///    and seconds of the angle.
		/// </returns>
		private Rational[] DegreeToRationals (double angle)
		{
			if (angle < 0.0 || angle > 180.0)
				throw new ArgumentException ("angle");

			uint deg = (uint) Math.Floor (angle);
			uint min = (uint) ((angle - Math.Floor (angle)) * 60.0);
			uint sec = (uint) ((angle - Math.Floor (angle) - (min / 60.0))  * 360000000.0);

			Rational[] rationals = new Rational [] {
				new Rational (deg, 1),
				new Rational (min, 1),
				new Rational (sec, 100000)
			};

			return rationals;
		}
コード例 #7
0
        public string ToString(string format, IFormatProvider provider)
        {
            Rational reduced = Reduce();

            return(String.Format("{0}/{1}", reduced.Numerator, reduced.Denominator));
        }