diff --git a/src/ImageProcessorCore/Numerics/Rational.cs b/src/ImageProcessorCore/Numerics/Rational.cs
index fd578dc7c..0b66d8367 100644
--- a/src/ImageProcessorCore/Numerics/Rational.cs
+++ b/src/ImageProcessorCore/Numerics/Rational.cs
@@ -8,27 +8,25 @@ namespace ImageProcessorCore
using System;
using System.Globalization;
using System.Numerics;
- using System.Runtime.InteropServices;
using System.Text;
///
/// Represents a number that can be expressed as a fraction
///
///
- /// This is a very simplified implimentation of a rational number designed for use with
- /// metadata only.
+ /// This is a very simplified implimentation of a rational number designed for use with metadata only.
///
public struct Rational : IEquatable
{
///
- /// Represents a rational object that is not a number.
+ /// Represents a rational object that is not a number. NaN
///
- public static Rational Indeterminate = new Rational(0, 0);
+ public static Rational Indeterminate = new Rational(3, 0);
///
/// Represents a rational object that is equal to 0.
///
- public static Rational Zero = new Rational(0, 1);
+ public static Rational Zero = new Rational(0, 0);
///
/// Represents a rational object that is equal to 1.
@@ -127,17 +125,20 @@ namespace ImageProcessorCore
this = Indeterminate;
return;
}
- else if (double.IsPositiveInfinity(value))
+
+ if (double.IsPositiveInfinity(value))
{
this = PositiveInfinity;
return;
}
- else if (double.IsNegativeInfinity(value))
+
+ if (double.IsNegativeInfinity(value))
{
this = NegativeInfinity;
return;
}
+ // TODO: Not happy with parsing a string like this. I should be able to use maths but maths is HARD!
this = Parse(value.ToString("R", CultureInfo.InvariantCulture));
}
@@ -154,32 +155,87 @@ namespace ImageProcessorCore
///
/// Gets a value indicating whether this instance is indeterminate.
///
- public bool IsIndeterminate => (this.Equals(Indeterminate));
+ public bool IsIndeterminate
+ {
+ get
+ {
+ if (this.Denominator != 0)
+ {
+ return false;
+ }
+
+ return this.Numerator == 3;
+ }
+ }
///
/// Gets a value indicating whether this instance is an integer.
///
- public bool IsInteger => (this.Denominator == 1);
+ public bool IsInteger => this.Denominator == 1;
///
/// Gets a value indicating whether this instance is equal to 0
///
- public bool IsZero => (this.Equals(Zero));
+ public bool IsZero
+ {
+ get
+ {
+ if (this.Denominator != 0)
+ {
+ return false;
+ }
+
+ return this.Numerator == 0;
+ }
+ }
///
/// Gets a value indicating whether this instance is equal to 1.
///
- public bool IsOne => (this.Equals(One));
+ public bool IsOne
+ {
+ get
+ {
+ if (this.Denominator != 1)
+ {
+ return false;
+ }
+
+ return this.Numerator == 1;
+ }
+ }
///
/// Gets a value indicating whether this instance is equal to negative infinity (-1, 0).
///
- public bool IsNegativeInfinity => (this.Equals(NegativeInfinity));
+ public bool IsNegativeInfinity
+ {
+ get
+ {
+ if (this.Denominator != 0)
+ {
+ return false;
+ }
+
+ return this.Numerator == -1;
+ }
+ }
///
- /// Gets a value indicating whether this instance is equal to positive infinity (1, 0).
+ /// Gets a value indicating whether this instance is equal to positive infinity (+1, 0).
///
- public bool IsPositiveInfinity => (this.Equals(PositiveInfinity));
+ public bool IsPositiveInfinity
+ {
+ get
+ {
+ if (this.Denominator != 0)
+ {
+ return false;
+ }
+
+ return this.Numerator == 1;
+ }
+ }
///
/// Converts a rational number to the nearest double.
@@ -226,31 +282,31 @@ namespace ImageProcessorCore
///
public bool Equals(Rational other)
{
+ // Standard: a/b = c/d
if (this.Denominator == other.Denominator)
{
return this.Numerator == other.Numerator;
}
- else if (this.Numerator == BigInteger.Zero && this.Denominator == BigInteger.Zero)
- {
- return other.Numerator == BigInteger.Zero && other.Denominator == BigInteger.Zero;
- }
- else if (other.Numerator == BigInteger.Zero && other.Denominator == BigInteger.Zero)
+
+ // Indeterminate
+ if (this.Numerator == 3 && this.Denominator == 0)
{
- return this.Numerator == BigInteger.Zero && this.Denominator == BigInteger.Zero;
+ return other.Numerator == 3 && other.Denominator == 0;
}
- else
+
+ if (other.Numerator == 3 && other.Denominator == 0)
{
- return (this.Numerator * other.Denominator) == (this.Denominator * other.Numerator);
+ return this.Numerator == 3 && this.Denominator == 0;
}
+
+ // ad = bc
+ return (this.Numerator * other.Denominator) == (this.Denominator * other.Numerator);
}
///
public override int GetHashCode()
{
- unchecked
- {
- return ((int)this.Numerator * 397) ^ (int)this.Denominator;
- }
+ return this.GetHashCode(this);
}
///
@@ -268,7 +324,6 @@ namespace ImageProcessorCore
///
///
public string ToString(IFormatProvider provider)
-
{
if (this.IsIndeterminate)
{
@@ -285,6 +340,11 @@ namespace ImageProcessorCore
return "[ NegativeInfinity ]";
}
+ if (this.IsZero)
+ {
+ return "[ Zero ]";
+ }
+
if (this.IsInteger)
{
return this.Numerator.ToString(provider);
@@ -322,16 +382,16 @@ namespace ImageProcessorCore
return;
}
- if (this.Numerator == BigInteger.Zero)
+ if (this.Numerator == 0)
{
- Denominator = BigInteger.One;
+ this.Denominator = 1;
return;
}
if (this.Numerator == this.Denominator)
{
- this.Numerator = BigInteger.One;
- this.Denominator = BigInteger.One;
+ this.Numerator = 1;
+ this.Denominator = 1;
return;
}
@@ -350,36 +410,36 @@ namespace ImageProcessorCore
/// The
internal static Rational Parse(string value)
{
- int periodIndex = value.IndexOf(".");
- int eIndeix = value.IndexOf("E");
- int slashIndex = value.IndexOf("/");
+ int periodIndex = value.IndexOf(".", StringComparison.Ordinal);
+ int eIndex = value.IndexOf("E", StringComparison.Ordinal);
+ int slashIndex = value.IndexOf("/", StringComparison.Ordinal);
// An integer such as 7
- if (periodIndex == -1 && eIndeix == -1 && slashIndex == -1)
+ if (periodIndex == -1 && eIndex == -1 && slashIndex == -1)
{
return new Rational(BigInteger.Parse(value));
}
// A fraction such as 3/7
- if (periodIndex == -1 && eIndeix == -1 && slashIndex != -1)
+ if (periodIndex == -1 && eIndex == -1 && slashIndex != -1)
{
return new Rational(BigInteger.Parse(value.Substring(0, slashIndex)),
BigInteger.Parse(value.Substring(slashIndex + 1)));
}
// No scientific Notation such as 5.997
- if (eIndeix == -1)
+ if (eIndex == -1)
{
- BigInteger n = BigInteger.Parse(value.Replace(".", ""));
+ BigInteger n = BigInteger.Parse(value.Replace(".", string.Empty));
BigInteger d = (BigInteger)Math.Pow(10, value.Length - periodIndex - 1);
return new Rational(n, d);
}
// Scientific notation such as 2.4556E-2
- int characteristic = int.Parse(value.Substring(eIndeix + 1));
+ int characteristic = int.Parse(value.Substring(eIndex + 1));
BigInteger ten = 10;
- BigInteger numerator = BigInteger.Parse(value.Substring(0, eIndeix).Replace(".", ""));
- BigInteger denominator = new BigInteger(Math.Pow(10, eIndeix - periodIndex - 1));
+ BigInteger numerator = BigInteger.Parse(value.Substring(0, eIndex).Replace(".", string.Empty));
+ BigInteger denominator = new BigInteger(Math.Pow(10, eIndex - periodIndex - 1));
BigInteger charPower = BigInteger.Pow(ten, Math.Abs(characteristic));
if (characteristic > 0)
@@ -393,5 +453,19 @@ namespace ImageProcessorCore
return new Rational(numerator, denominator);
}
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ ///
+ /// The instance of to return the hash code for.
+ ///
+ ///
+ /// A 32-bit signed integer that is the hash code for this instance.
+ ///
+ private int GetHashCode(Rational rational)
+ {
+ return ((rational.Numerator * 397) ^ rational.Denominator).GetHashCode();
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifDataType.cs b/src/ImageProcessorCore/Profiles/Exif/ExifDataType.cs
index 517b76011..15a66bebe 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifDataType.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifDataType.cs
@@ -5,9 +5,9 @@
namespace ImageProcessorCore
{
- ///
+ ///
/// Specifies exif data types.
- ///
+ ///
public enum ExifDataType
{
///
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifParts.cs b/src/ImageProcessorCore/Profiles/Exif/ExifParts.cs
index 3ad53430b..0684904f0 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifParts.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifParts.cs
@@ -7,13 +7,12 @@ namespace ImageProcessorCore
{
using System;
- ///
+ ///
/// Specifies which parts will be written when the profile is added to an image.
- ///
+ ///
[Flags]
public enum ExifParts
{
-
///
/// None
///
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs b/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs
index 5db095f09..86b90d76f 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs
@@ -2,9 +2,9 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
namespace ImageProcessorCore
{
+ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
@@ -54,7 +54,6 @@ namespace ImageProcessorCore
public ExifProfile(byte[] data)
{
this.Parts = ExifParts.All;
- this.BestPrecision = false;
this.data = data;
this.invalidTags = new List();
}
@@ -70,8 +69,6 @@ namespace ImageProcessorCore
Guard.NotNull(other, nameof(other));
this.Parts = other.Parts;
- this.BestPrecision = other.BestPrecision;
-
this.thumbnailLength = other.thumbnailLength;
this.thumbnailOffset = other.thumbnailOffset;
this.invalidTags = new List(other.invalidTags);
@@ -89,17 +86,6 @@ namespace ImageProcessorCore
}
}
- ///
- /// Gets or sets a value indicating whether rational numbers should be stored with the best
- /// precision possible. This is disabled by default, setting this to true will have an
- /// impact on the performance.
- ///
- public bool BestPrecision
- {
- get;
- set;
- }
-
///
/// Gets or sets which parts will be written when the profile is added to an image.
///
@@ -121,7 +107,7 @@ namespace ImageProcessorCore
{
get
{
- InitializeValues();
+ this.InitializeValues();
return this.values;
}
}
@@ -135,7 +121,7 @@ namespace ImageProcessorCore
where T : IPackedVector
where TP : struct
{
- InitializeValues();
+ this.InitializeValues();
if (this.thumbnailOffset == 0 || this.thumbnailLength == 0)
{
@@ -159,7 +145,7 @@ namespace ImageProcessorCore
/// The tag of the EXIF value.
public ExifValue GetValue(ExifTag tag)
{
- foreach (ExifValue exifValue in Values)
+ foreach (ExifValue exifValue in this.Values)
{
if (exifValue.Tag == tag)
return exifValue;
@@ -174,7 +160,7 @@ namespace ImageProcessorCore
/// The tag of the EXIF value.
public bool RemoveValue(ExifTag tag)
{
- InitializeValues();
+ this.InitializeValues();
for (int i = 0; i < this.values.Count; i++)
{
@@ -224,7 +210,7 @@ namespace ImageProcessorCore
return null;
}
- ExifWriter writer = new ExifWriter(this.values, this.Parts, this.BestPrecision);
+ ExifWriter writer = new ExifWriter(this.values, this.Parts);
return writer.GetData();
}
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs b/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs
index 1ebb9c9e9..333a00d0a 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs
@@ -2,7 +2,6 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
namespace ImageProcessorCore
{
using System;
@@ -118,11 +117,11 @@ namespace ImageProcessorCore
private void AddValues(Collection values, uint index)
{
this.currentIndex = this.startIndex + index;
- ushort count = GetShort();
+ ushort count = this.GetShort();
for (ushort i = 0; i < count; i++)
{
- ExifValue value = CreateValue();
+ ExifValue value = this.CreateValue();
if (value == null)
{
continue;
@@ -197,7 +196,7 @@ namespace ImageProcessorCore
return this.ToLong(data);
}
- return ToArray(dataType, data, ToLong);
+ return ToArray(dataType, data, this.ToLong);
case ExifDataType.Rational:
if (numberOfComponents == 1)
{
@@ -243,10 +242,10 @@ namespace ImageProcessorCore
case ExifDataType.SingleFloat:
if (numberOfComponents == 1)
{
- return ToSingle(data);
+ return this.ToSingle(data);
}
- return ToArray(dataType, data, ToSingle);
+ return ToArray(dataType, data, this.ToSingle);
case ExifDataType.Undefined:
if (numberOfComponents == 1)
{
@@ -261,13 +260,13 @@ namespace ImageProcessorCore
private ExifValue CreateValue()
{
- if (RemainingLength < 12)
+ if (this.RemainingLength < 12)
{
return null;
}
- ExifTag tag = ToEnum(this.GetShort(), ExifTag.Unknown);
- ExifDataType dataType = ToEnum(this.GetShort(), ExifDataType.Unknown);
+ ExifTag tag = this.ToEnum(this.GetShort(), ExifTag.Unknown);
+ ExifDataType dataType = this.ToEnum(this.GetShort(), ExifDataType.Unknown);
object value;
if (dataType == ExifDataType.Unknown)
@@ -278,25 +277,25 @@ namespace ImageProcessorCore
uint numberOfComponents = this.GetLong();
uint size = numberOfComponents * ExifValue.GetSize(dataType);
- byte[] data = GetBytes(4);
+ byte[] data = this.GetBytes(4);
if (size > 4)
{
uint oldIndex = this.currentIndex;
- this.currentIndex = ToLong(data) + this.startIndex;
- if (RemainingLength < size)
+ this.currentIndex = this.ToLong(data) + this.startIndex;
+ if (this.RemainingLength < size)
{
this.invalidTags.Add(tag);
this.currentIndex = oldIndex;
return null;
}
- value = ConvertValue(dataType, this.GetBytes(size), numberOfComponents);
+ value = this.ConvertValue(dataType, this.GetBytes(size), numberOfComponents);
this.currentIndex = oldIndex;
}
else
{
- value = ConvertValue(dataType, data, numberOfComponents);
+ value = this.ConvertValue(dataType, data, numberOfComponents);
}
bool isArray = value != null && numberOfComponents > 1;
@@ -331,38 +330,38 @@ namespace ImageProcessorCore
private uint GetLong()
{
- return ToLong(GetBytes(4));
+ return this.ToLong(this.GetBytes(4));
}
private ushort GetShort()
{
- return ToShort(GetBytes(2));
+ return this.ToShort(this.GetBytes(2));
}
private string GetString(uint length)
{
- return ToString(GetBytes(length));
+ return ToString(this.GetBytes(length));
}
private void GetThumbnail(uint offset)
{
Collection values = new Collection();
- AddValues(values, offset);
+ this.AddValues(values, offset);
foreach (ExifValue value in values)
{
if (value.Tag == ExifTag.JPEGInterchangeFormat && (value.DataType == ExifDataType.Long))
{
- ThumbnailOffset = (uint)value.Value + this.startIndex;
+ this.ThumbnailOffset = (uint)value.Value + this.startIndex;
}
else if (value.Tag == ExifTag.JPEGInterchangeFormatLength && value.DataType == ExifDataType.Long)
{
- ThumbnailLength = (uint)value.Value;
+ this.ThumbnailLength = (uint)value.Value;
}
}
}
- private static TDataType[] ToArray(ExifDataType dataType, Byte[] data,
+ private static TDataType[] ToArray(ExifDataType dataType, byte[] data,
ConverterMethod converter)
{
int dataTypeSize = (int)ExifValue.GetSize(dataType);
@@ -388,7 +387,7 @@ namespace ImageProcessorCore
private double ToDouble(byte[] data)
{
- if (!ValidateArray(data, 8))
+ if (!this.ValidateArray(data, 8))
{
return default(double);
}
@@ -398,7 +397,7 @@ namespace ImageProcessorCore
private uint ToLong(byte[] data)
{
- if (!ValidateArray(data, 4))
+ if (!this.ValidateArray(data, 4))
{
return default(uint);
}
@@ -409,7 +408,7 @@ namespace ImageProcessorCore
private ushort ToShort(byte[] data)
{
- if (!ValidateArray(data, 2))
+ if (!this.ValidateArray(data, 2))
{
return default(ushort);
}
@@ -419,7 +418,7 @@ namespace ImageProcessorCore
private float ToSingle(byte[] data)
{
- if (!ValidateArray(data, 4))
+ if (!this.ValidateArray(data, 4))
{
return default(float);
}
@@ -441,7 +440,7 @@ namespace ImageProcessorCore
private Rational ToRational(byte[] data)
{
- if (!ValidateArray(data, 8, 4))
+ if (!this.ValidateArray(data, 8, 4))
{
return Rational.Zero;
}
@@ -449,24 +448,9 @@ namespace ImageProcessorCore
uint numerator = BitConverter.ToUInt32(data, 0);
uint denominator = BitConverter.ToUInt32(data, 4);
- // TODO: investigate the possibility of a Rational struct
return new Rational(numerator, denominator);
}
- //private double ToRational(byte[] data)
- //{
- // if (!ValidateArray(data, 8, 4))
- // {
- // return default(double);
- // }
-
- // uint numerator = BitConverter.ToUInt32(data, 0);
- // uint denominator = BitConverter.ToUInt32(data, 4);
-
- // // TODO: investigate the possibility of a Rational struct
- // return numerator / (double)denominator;
- //}
-
private sbyte ToSignedByte(byte[] data)
{
return unchecked((sbyte)data[0]);
@@ -474,7 +458,7 @@ namespace ImageProcessorCore
private int ToSignedLong(byte[] data)
{
- if (!ValidateArray(data, 4))
+ if (!this.ValidateArray(data, 4))
{
return default(int);
}
@@ -484,7 +468,7 @@ namespace ImageProcessorCore
private Rational ToSignedRational(byte[] data)
{
- if (!ValidateArray(data, 8, 4))
+ if (!this.ValidateArray(data, 8, 4))
{
return Rational.Zero;
}
@@ -495,22 +479,9 @@ namespace ImageProcessorCore
return new Rational(numerator, denominator);
}
- //private double ToSignedRational(byte[] data)
- //{
- // if (!ValidateArray(data, 8, 4))
- // {
- // return default(double);
- // }
-
- // int numerator = BitConverter.ToInt32(data, 0);
- // int denominator = BitConverter.ToInt32(data, 4);
-
- // return numerator / (double)denominator;
- //}
-
private short ToSignedShort(byte[] data)
{
- if (!ValidateArray(data, 2))
+ if (!this.ValidateArray(data, 2))
{
return default(short);
}
@@ -520,7 +491,7 @@ namespace ImageProcessorCore
private bool ValidateArray(byte[] data, int size)
{
- return ValidateArray(data, size, size);
+ return this.ValidateArray(data, size, size);
}
private bool ValidateArray(byte[] data, int size, int stepSize)
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs b/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs
index 9609ff366..23441cf0e 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs
@@ -14,7 +14,7 @@ namespace ImageProcessorCore
///
public sealed class ExifValue : IEquatable
{
- private object value;
+ private object exifValue;
///
/// Initializes a new instance of the class
@@ -26,18 +26,18 @@ namespace ImageProcessorCore
{
Guard.NotNull(other, nameof(other));
- DataType = other.DataType;
- IsArray = other.IsArray;
- Tag = other.Tag;
+ this.DataType = other.DataType;
+ this.IsArray = other.IsArray;
+ this.Tag = other.Tag;
if (!other.IsArray)
{
- value = other.value;
+ this.exifValue = other.exifValue;
}
else
{
- Array array = (Array)other.value;
- value = array.Clone();
+ Array array = (Array)other.exifValue;
+ this.exifValue = array.Clone();
}
}
@@ -47,7 +47,6 @@ namespace ImageProcessorCore
public ExifDataType DataType
{
get;
- private set;
}
///
@@ -56,7 +55,6 @@ namespace ImageProcessorCore
public bool IsArray
{
get;
- private set;
}
///
@@ -65,7 +63,6 @@ namespace ImageProcessorCore
public ExifTag Tag
{
get;
- private set;
}
///
@@ -75,12 +72,12 @@ namespace ImageProcessorCore
{
get
{
- return this.value;
+ return this.exifValue;
}
set
{
- CheckValue(value);
- this.value = value;
+ this.CheckValue(value);
+ this.exifValue = value;
}
}
@@ -113,9 +110,11 @@ namespace ImageProcessorCore
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
+ {
return true;
+ }
- return Equals(obj as ExifValue);
+ return this.Equals(obj as ExifValue);
}
///
@@ -125,45 +124,50 @@ namespace ImageProcessorCore
public bool Equals(ExifValue other)
{
if (ReferenceEquals(other, null))
+ {
return false;
+ }
if (ReferenceEquals(this, other))
+ {
return true;
+ }
return
- Tag == other.Tag &&
- DataType == other.DataType &&
- object.Equals(this.value, other.value);
+ this.Tag == other.Tag &&
+ this.DataType == other.DataType &&
+ Equals(this.exifValue, other.exifValue);
}
- ///
- /// Serves as a hash of this type.
- ///
+ ///
public override int GetHashCode()
{
- int hashCode = Tag.GetHashCode() ^ DataType.GetHashCode();
- return this.value != null ? hashCode ^ this.value.GetHashCode() : hashCode;
+ return this.GetHashCode(this);
}
- ///
- /// Returns a string that represents the current value.
- ///
+ ///
public override string ToString()
{
- if (this.value == null)
+ if (this.exifValue == null)
+ {
return null;
+ }
- if (DataType == ExifDataType.Ascii)
- return (string)this.value;
+ if (this.DataType == ExifDataType.Ascii)
+ {
+ return (string)this.exifValue;
+ }
- if (!IsArray)
- return ToString(this.value);
+ if (!this.IsArray)
+ {
+ return this.ToString(this.exifValue);
+ }
StringBuilder sb = new StringBuilder();
- foreach (object value in (Array)this.value)
+ foreach (object value in (Array)this.exifValue)
{
- sb.Append(ToString(value));
+ sb.Append(this.ToString(value));
sb.Append(" ");
}
@@ -174,11 +178,15 @@ namespace ImageProcessorCore
{
get
{
- if (this.value == null)
+ if (this.exifValue == null)
+ {
return false;
+ }
- if (DataType == ExifDataType.Ascii)
- return ((string)this.value).Length > 0;
+ if (this.DataType == ExifDataType.Ascii)
+ {
+ return ((string)this.exifValue).Length > 0;
+ }
return true;
}
@@ -188,10 +196,12 @@ namespace ImageProcessorCore
{
get
{
- if (this.value == null)
+ if (this.exifValue == null)
+ {
return 4;
+ }
- int size = (int)(GetSize(DataType) * NumberOfComponents);
+ int size = (int)(GetSize(this.DataType) * this.NumberOfComponents);
return size < 4 ? 4 : size;
}
@@ -201,11 +211,15 @@ namespace ImageProcessorCore
{
get
{
- if (DataType == ExifDataType.Ascii)
- return Encoding.UTF8.GetBytes((string)this.value).Length;
+ if (this.DataType == ExifDataType.Ascii)
+ {
+ return Encoding.UTF8.GetBytes((string)this.exifValue).Length;
+ }
- if (IsArray)
- return ((Array)this.value).Length;
+ if (this.IsArray)
+ {
+ return ((Array)this.exifValue).Length;
+ }
return 1;
}
@@ -213,28 +227,32 @@ namespace ImageProcessorCore
internal ExifValue(ExifTag tag, ExifDataType dataType, bool isArray)
{
- Tag = tag;
- DataType = dataType;
- IsArray = isArray;
+ this.Tag = tag;
+ this.DataType = dataType;
+ this.IsArray = isArray;
if (dataType == ExifDataType.Ascii)
- IsArray = false;
+ {
+ this.IsArray = false;
+ }
}
internal ExifValue(ExifTag tag, ExifDataType dataType, object value, bool isArray)
: this(tag, dataType, isArray)
{
- this.value = value;
+ this.exifValue = value;
}
internal static ExifValue Create(ExifTag tag, object value)
{
Guard.IsFalse(tag == ExifTag.Unknown, nameof(tag), "Invalid Tag");
- ExifValue exifValue = null;
- Type type = value != null ? value.GetType() : null;
+ ExifValue exifValue;
+ Type type = value?.GetType();
if (type != null && type.IsArray)
+ {
type = type.GetElementType();
+ }
switch (tag)
{
@@ -456,7 +474,7 @@ namespace ImageProcessorCore
break;
default:
- throw new NotImplementedException();
+ throw new NotSupportedException();
}
exifValue.Value = value;
@@ -484,18 +502,20 @@ namespace ImageProcessorCore
case ExifDataType.SignedRational:
return 8;
default:
- throw new NotImplementedException(dataType.ToString());
+ throw new NotSupportedException(dataType.ToString());
}
}
private void CheckValue(object value)
{
if (value == null)
+ {
return;
+ }
Type type = value.GetType();
- if (DataType == ExifDataType.Ascii)
+ if (this.DataType == ExifDataType.Ascii)
{
Guard.IsTrue(type == typeof(string), nameof(value), "Value should be a string.");
return;
@@ -503,45 +523,43 @@ namespace ImageProcessorCore
if (type.IsArray)
{
- Guard.IsTrue(IsArray, nameof(value), "Value should not be an array.");
+ Guard.IsTrue(this.IsArray, nameof(value), "Value should not be an array.");
type = type.GetElementType();
}
else
{
- Guard.IsFalse(IsArray, nameof(value), "Value should not be an array.");
+ Guard.IsFalse(this.IsArray, nameof(value), "Value should not be an array.");
}
- switch (DataType)
+ switch (this.DataType)
{
case ExifDataType.Byte:
- Guard.IsTrue(type == typeof(byte), nameof(value), $"Value should be a byte{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(byte), nameof(value), $"Value should be a byte{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.DoubleFloat:
- //case ExifDataType.Rational:
- //case ExifDataType.SignedRational:
- Guard.IsTrue(type == typeof(double), nameof(value), $"Value should be a double{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(double), nameof(value), $"Value should be a double{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.Rational:
case ExifDataType.SignedRational:
- Guard.IsTrue(type == typeof(Rational), nameof(value), $"Value should be a Rational{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(Rational), nameof(value), $"Value should be a Rational{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.Long:
- Guard.IsTrue(type == typeof(uint), nameof(value), $"Value should be an unsigned int{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(uint), nameof(value), $"Value should be an unsigned int{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.Short:
- Guard.IsTrue(type == typeof(ushort), nameof(value), $"Value should be an unsigned short{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(ushort), nameof(value), $"Value should be an unsigned short{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.SignedByte:
- Guard.IsTrue(type == typeof(sbyte), nameof(value), $"Value should be a signed byte{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(sbyte), nameof(value), $"Value should be a signed byte{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.SignedLong:
- Guard.IsTrue(type == typeof(int), nameof(value), $"Value should be an int{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(int), nameof(value), $"Value should be an int{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.SignedShort:
- Guard.IsTrue(type == typeof(short), nameof(value), $"Value should be a short{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(short), nameof(value), $"Value should be a short{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.SingleFloat:
- Guard.IsTrue(type == typeof(float), nameof(value), $"Value should be a float{(IsArray ? " array." : ".")}");
+ Guard.IsTrue(type == typeof(float), nameof(value), $"Value should be a float{(this.IsArray ? " array." : ".")}");
break;
case ExifDataType.Undefined:
Guard.IsTrue(type == typeof(byte), nameof(value), "Value should be a byte array.");
@@ -554,22 +572,32 @@ namespace ImageProcessorCore
private static ExifValue CreateNumber(ExifTag tag, Type type, bool isArray)
{
if (type == null || type == typeof(ushort))
+ {
return new ExifValue(tag, ExifDataType.Short, isArray);
- else if (type == typeof(short))
+ }
+
+ if (type == typeof(short))
+ {
return new ExifValue(tag, ExifDataType.SignedShort, isArray);
- else if (type == typeof(uint))
+ }
+
+ if (type == typeof(uint))
+ {
return new ExifValue(tag, ExifDataType.Long, isArray);
- else
- return new ExifValue(tag, ExifDataType.SignedLong, isArray);
+ }
+
+ return new ExifValue(tag, ExifDataType.SignedLong, isArray);
}
private string ToString(object value)
{
- string description = ExifTagDescriptionAttribute.GetDescription(Tag, value);
+ string description = ExifTagDescriptionAttribute.GetDescription(this.Tag, value);
if (description != null)
- return description;
+ {
+ return description;
+ }
- switch (DataType)
+ switch (this.DataType)
{
case ExifDataType.Ascii:
return (string)value;
@@ -580,7 +608,6 @@ namespace ImageProcessorCore
case ExifDataType.Long:
return ((uint)value).ToString(CultureInfo.InvariantCulture);
case ExifDataType.Rational:
- //return ((double)value).ToString(CultureInfo.InvariantCulture);
return ((Rational)value).ToString(CultureInfo.InvariantCulture);
case ExifDataType.Short:
return ((ushort)value).ToString(CultureInfo.InvariantCulture);
@@ -589,7 +616,6 @@ namespace ImageProcessorCore
case ExifDataType.SignedLong:
return ((int)value).ToString(CultureInfo.InvariantCulture);
case ExifDataType.SignedRational:
- //return ((double)value).ToString(CultureInfo.InvariantCulture);
return ((Rational)value).ToString(CultureInfo.InvariantCulture);
case ExifDataType.SignedShort:
return ((short)value).ToString(CultureInfo.InvariantCulture);
@@ -598,8 +624,23 @@ namespace ImageProcessorCore
case ExifDataType.Undefined:
return ((byte)value).ToString("X2", CultureInfo.InvariantCulture);
default:
- throw new NotImplementedException();
+ throw new NotSupportedException();
}
}
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ ///
+ /// The instance of to return the hash code for.
+ ///
+ ///
+ /// A 32-bit signed integer that is the hash code for this instance.
+ ///
+ private int GetHashCode(ExifValue exif)
+ {
+ int hashCode = exif.Tag.GetHashCode() ^ exif.DataType.GetHashCode();
+ return hashCode ^ exif.exifValue?.GetHashCode() ?? hashCode;
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs b/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs
index f41668a58..5fc9721f9 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs
@@ -82,22 +82,19 @@ namespace ImageProcessorCore
private const int StartIndex = 6;
private ExifParts allowedParts;
- private bool bestPrecision;
private Collection values;
private Collection dataOffsets;
private Collection ifdIndexes;
private Collection exifIndexes;
private Collection gpsIndexes;
- public ExifWriter(Collection values, ExifParts allowedParts, bool bestPrecision)
+ public ExifWriter(Collection values, ExifParts allowedParts)
{
this.values = values;
this.allowedParts = allowedParts;
- this.bestPrecision = bestPrecision;
-
- this.ifdIndexes = GetIndexes(ExifParts.IfdTags, IfdTags);
- this.exifIndexes = GetIndexes(ExifParts.ExifTags, ExifTags);
- this.gpsIndexes = GetIndexes(ExifParts.GPSTags, GPSTags);
+ this.ifdIndexes = this.GetIndexes(ExifParts.IfdTags, IfdTags);
+ this.exifIndexes = this.GetIndexes(ExifParts.ExifTags, ExifTags);
+ this.gpsIndexes = this.GetIndexes(ExifParts.GPSTags, GPSTags);
}
public byte[] GetData()
@@ -107,25 +104,35 @@ namespace ImageProcessorCore
int gpsIndex = -1;
if (this.exifIndexes.Count > 0)
- exifIndex = (int)GetIndex(this.ifdIndexes, ExifTag.SubIFDOffset);
+ {
+ exifIndex = (int)this.GetIndex(this.ifdIndexes, ExifTag.SubIFDOffset);
+ }
if (this.gpsIndexes.Count > 0)
- gpsIndex = (int)GetIndex(this.ifdIndexes, ExifTag.GPSIFDOffset);
+ {
+ gpsIndex = (int)this.GetIndex(this.ifdIndexes, ExifTag.GPSIFDOffset);
+ }
- uint ifdLength = 2 + GetLength(this.ifdIndexes) + 4;
- uint exifLength = GetLength(this.exifIndexes);
- uint gpsLength = GetLength(this.gpsIndexes);
+ uint ifdLength = 2 + this.GetLength(this.ifdIndexes) + 4;
+ uint exifLength = this.GetLength(this.exifIndexes);
+ uint gpsLength = this.GetLength(this.gpsIndexes);
if (exifLength > 0)
+ {
exifLength += 2;
+ }
if (gpsLength > 0)
+ {
gpsLength += 2;
+ }
length = ifdLength + exifLength + gpsLength;
if (length == 6)
+ {
return null;
+ }
length += 10 + 4 + 2;
@@ -146,26 +153,30 @@ namespace ImageProcessorCore
uint thumbnailOffset = ifdOffset + ifdLength + exifLength + gpsLength;
if (exifLength > 0)
- this.values[exifIndex].Value = (ifdOffset + ifdLength);
+ {
+ this.values[exifIndex].Value = ifdOffset + ifdLength;
+ }
if (gpsLength > 0)
- this.values[gpsIndex].Value = (ifdOffset + ifdLength + exifLength);
+ {
+ this.values[gpsIndex].Value = ifdOffset + ifdLength + exifLength;
+ }
i = Write(BitConverter.GetBytes(ifdOffset), result, i);
- i = WriteHeaders(this.ifdIndexes, result, i);
+ i = this.WriteHeaders(this.ifdIndexes, result, i);
i = Write(BitConverter.GetBytes(thumbnailOffset), result, i);
- i = WriteData(this.ifdIndexes, result, i);
+ i = this.WriteData(this.ifdIndexes, result, i);
if (exifLength > 0)
{
- i = WriteHeaders(this.exifIndexes, result, i);
- i = WriteData(this.exifIndexes, result, i);
+ i = this.WriteHeaders(this.exifIndexes, result, i);
+ i = this.WriteData(this.exifIndexes, result, i);
}
if (gpsLength > 0)
{
- i = WriteHeaders(this.gpsIndexes, result, i);
- i = WriteData(this.gpsIndexes, result, i);
+ i = this.WriteHeaders(this.gpsIndexes, result, i);
+ i = this.WriteData(this.gpsIndexes, result, i);
}
Write(BitConverter.GetBytes((ushort)0), result, i);
@@ -178,7 +189,9 @@ namespace ImageProcessorCore
foreach (int index in indexes)
{
if (this.values[index].Tag == tag)
+ {
return index;
+ }
}
int newIndex = this.values.Count;
@@ -190,7 +203,9 @@ namespace ImageProcessorCore
private Collection GetIndexes(ExifParts part, ExifTag[] tags)
{
if (((int)this.allowedParts & (int)part) == 0)
+ {
return new Collection();
+ }
Collection result = new Collection();
for (int i = 0; i < this.values.Count; i++)
@@ -198,11 +213,15 @@ namespace ImageProcessorCore
ExifValue value = this.values[i];
if (!value.HasValue)
+ {
continue;
+ }
int index = Array.IndexOf(tags, value.Tag);
if (index > -1)
+ {
result.Add(i);
+ }
}
return result;
@@ -217,9 +236,13 @@ namespace ImageProcessorCore
uint valueLength = (uint)this.values[index].Length;
if (valueLength > 4)
+ {
length += 12 + valueLength;
+ }
else
+ {
length += 12;
+ }
}
return length;
@@ -235,11 +258,15 @@ namespace ImageProcessorCore
private int WriteArray(ExifValue value, byte[] destination, int offset)
{
if (value.DataType == ExifDataType.Ascii)
- return WriteValue(ExifDataType.Ascii, value.Value, destination, offset);
+ {
+ return this.WriteValue(ExifDataType.Ascii, value.Value, destination, offset);
+ }
int newOffset = offset;
foreach (object obj in (Array)value.Value)
- newOffset = WriteValue(value.DataType, obj, destination, newOffset);
+ {
+ newOffset = this.WriteValue(value.DataType, obj, destination, newOffset);
+ }
return newOffset;
}
@@ -247,7 +274,9 @@ namespace ImageProcessorCore
private int WriteData(Collection indexes, byte[] destination, int offset)
{
if (this.dataOffsets.Count == 0)
+ {
return offset;
+ }
int newOffset = offset;
@@ -258,7 +287,7 @@ namespace ImageProcessorCore
if (value.Length > 4)
{
Write(BitConverter.GetBytes(newOffset - StartIndex), destination, this.dataOffsets[i++]);
- newOffset = WriteValue(value, destination, newOffset);
+ newOffset = this.WriteValue(value, destination, newOffset);
}
}
@@ -272,7 +301,9 @@ namespace ImageProcessorCore
int newOffset = Write(BitConverter.GetBytes((ushort)indexes.Count), destination, offset);
if (indexes.Count == 0)
+ {
return newOffset;
+ }
foreach (int index in indexes)
{
@@ -282,9 +313,13 @@ namespace ImageProcessorCore
newOffset = Write(BitConverter.GetBytes((uint)value.NumberOfComponents), destination, newOffset);
if (value.Length > 4)
+ {
this.dataOffsets.Add(newOffset);
+ }
else
- WriteValue(value, destination, newOffset);
+ {
+ this.WriteValue(value, destination, newOffset);
+ }
newOffset += 4;
}
@@ -294,91 +329,21 @@ namespace ImageProcessorCore
private int WriteRational(Rational value, byte[] destination, int offset)
{
+ // Ensure no overflow
Write(BitConverter.GetBytes((uint)(value.Numerator * (value.ToDouble() < 0.0 ? -1 : 1))), destination, offset);
Write(BitConverter.GetBytes((uint)value.Denominator), destination, offset + 4);
return offset + 8;
}
- //private int WriteRational(double value, byte[] destination, int offset)
- //{
- // uint numerator = 1;
- // uint denominator = 1;
-
- // if (double.IsPositiveInfinity(value))
- // denominator = 0;
- // else if (double.IsNegativeInfinity(value))
- // denominator = 0;
- // else
- // {
- // double val = Math.Abs(value);
- // double df = numerator / denominator;
- // double epsilon = this.bestPrecision ? double.Epsilon : .000001;
-
- // while (Math.Abs(df - val) > epsilon)
- // {
- // if (df < val)
- // numerator++;
- // else
- // {
- // denominator++;
- // numerator = (uint)(val * denominator);
- // }
-
- // df = numerator / (double)denominator;
- // }
- // }
-
- // Write(BitConverter.GetBytes(numerator), destination, offset);
- // Write(BitConverter.GetBytes(denominator), destination, offset + 4);
-
- // return offset + 8;
- //}
-
private int WriteSignedRational(Rational value, byte[] destination, int offset)
{
- // TODO: Check this.
Write(BitConverter.GetBytes((int)value.Numerator), destination, offset);
Write(BitConverter.GetBytes((int)value.Denominator), destination, offset + 4);
return offset + 8;
}
- //private int WriteSignedRational(double value, byte[] destination, int offset)
- //{
- // int numerator = 1;
- // int denominator = 1;
-
- // if (double.IsPositiveInfinity(value))
- // denominator = 0;
- // else if (double.IsNegativeInfinity(value))
- // denominator = 0;
- // else
- // {
- // double val = Math.Abs(value);
- // double df = numerator / denominator;
- // double epsilon = this.bestPrecision ? double.Epsilon : .000001;
-
- // while (Math.Abs(df - val) > epsilon)
- // {
- // if (df < val)
- // numerator++;
- // else
- // {
- // denominator++;
- // numerator = (int)(val * denominator);
- // }
-
- // df = numerator / (double)denominator;
- // }
- // }
-
- // Write(BitConverter.GetBytes(numerator * (value < 0.0 ? -1 : 1)), destination, offset);
- // Write(BitConverter.GetBytes(denominator), destination, offset + 4);
-
- // return offset + 8;
- //}
-
private int WriteValue(ExifDataType dataType, object value, byte[] destination, int offset)
{
switch (dataType)
@@ -396,7 +361,7 @@ namespace ImageProcessorCore
case ExifDataType.Long:
return Write(BitConverter.GetBytes((uint)value), destination, offset);
case ExifDataType.Rational:
- return WriteRational((Rational)value, destination, offset);
+ return this.WriteRational((Rational)value, destination, offset);
case ExifDataType.SignedByte:
destination[offset] = unchecked((byte)((sbyte)value));
return offset + 1;
@@ -405,7 +370,7 @@ namespace ImageProcessorCore
case ExifDataType.SignedShort:
return Write(BitConverter.GetBytes((short)value), destination, offset);
case ExifDataType.SignedRational:
- return WriteSignedRational((Rational)value, destination, offset);
+ return this.WriteSignedRational((Rational)value, destination, offset);
case ExifDataType.SingleFloat:
return Write(BitConverter.GetBytes((float)value), destination, offset);
default:
@@ -416,9 +381,11 @@ namespace ImageProcessorCore
private int WriteValue(ExifValue value, byte[] destination, int offset)
{
if (value.IsArray && value.DataType != ExifDataType.Ascii)
- return WriteArray(value, destination, offset);
- else
- return WriteValue(value.DataType, value.Value, destination, offset);
+ {
+ return this.WriteArray(value, destination, offset);
+ }
+
+ return this.WriteValue(value.DataType, value.Value, destination, offset);
}
}
}
\ No newline at end of file
diff --git a/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs b/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs
index 31307f2cf..438e90336 100644
--- a/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs
+++ b/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs
@@ -90,7 +90,6 @@ namespace ImageProcessorCore.Tests
profile = GetExifProfile();
profile.SetValue(ExifTag.ExposureTime, exposureTime);
- profile.BestPrecision = true;
image.ExifProfile = profile;
image.SaveAsJpeg(memStream);