Exemplo n.º 1
0
		public void SRational3 ()
		{
			SRational 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);
		}
Exemplo n.º 2
0
		public void SRational2 ()
		{
			SRational 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);
		}
Exemplo n.º 3
0
		public void SRational1 ()
		{
			SRational 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);
		}
Exemplo n.º 4
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="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));
		}
Exemplo n.º 5
0
        /// <summary>
        ///    Formatprovider to allow formatting of a value. <see cref="IFormattable"/>
        /// </summary>
        /// <param name="format">
        ///    A <see cref="System.String"/>. <see cref="IFormattable"/>
        /// </param>
        /// <param name="provider">
        ///    A <see cref="IFormatProvider"/>. <see cref="IFormattable"/>
        /// </param>
        /// <returns>
        ///    A <see cref="System.String"/> formated according to the given parameter
        /// </returns>
        public string ToString(string format, IFormatProvider provider)
        {
            SRational reduced = Reduce();

            return($"{reduced.Numerator}/{reduced.Denominator}");
        }
Exemplo n.º 6
0
        /// <summary>
        ///    Formatprovider to allow formatting of a value. <see cref="IFormattable"/>
        /// </summary>
        /// <param name="format">
        ///    A <see cref="System.String"/>. <see cref="IFormattable"/>
        /// </param>
        /// <param name="provider">
        ///    A <see cref="IFormatProvider"/>. <see cref="IFormattable"/>
        /// </param>
        /// <returns>
        ///    A <see cref="System.String"/> formated according to the given parameter
        /// </returns>
        public string ToString(string format, IFormatProvider provider)
        {
            SRational reduced = Reduce();

            return(String.Format("{0}/{1}", reduced.Numerator, reduced.Denominator));
        }
Exemplo n.º 7
0
		public void SRational4 ()
		{
			SRational 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);
		}
Exemplo n.º 8
0
		public void SRational5 ()
		{
			SRational 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);
		}