diff --git a/ExifLibrary/ExifBitConverter.cs b/ExifLibrary/ExifBitConverter.cs
index a2027d8..f8c1bbd 100644
--- a/ExifLibrary/ExifBitConverter.cs
+++ b/ExifLibrary/ExifBitConverter.cs
@@ -216,6 +216,24 @@ public static MathEx.Fraction32[] ToSRationalArray(byte[] data, int count, ByteO
return numbers;
}
+
+ ///
+ /// Returns an array of 16-bit signed integers converted from
+ /// the given byte array.
+ /// Numbers are converted from the given byte-order to platform byte-order.
+ ///
+ public static short[] ToSShortArray(byte[] data, int count, ByteOrder frombyteorder)
+ {
+ short[] numbers = new short[count];
+ for (int i = 0; i < count; i++)
+ {
+ byte[] num = new byte[2];
+ Array.Copy(data, i * 2, num, 0, 2);
+ numbers[i] = ToInt16(num, 0, frombyteorder, BitConverterEx.SystemByteOrder);
+ }
+ return numbers;
+ }
+
///
/// Converts the given ascii string to an array of bytes optionally adding a null terminator.
///
@@ -352,6 +370,21 @@ public static byte[] GetBytes(MathEx.Fraction32[] value, ByteOrder tobyteorder)
}
return data;
}
+
+ ///
+ /// Converts the given array of 16-bit signed integers to an array of bytes.
+ /// Numbers are converted from the platform byte-order to the given byte-order.
+ ///
+ public static byte[] GetBytes(short[] value, ByteOrder tobyteorder)
+ {
+ byte[] data = new byte[2 * value.Length];
+ for (int i = 0; i < value.Length; i++)
+ {
+ byte[] num = GetBytes(value[i], BitConverterEx.SystemByteOrder, tobyteorder);
+ Array.Copy(num, 0, data, i * 2, 2);
+ }
+ return data;
+ }
#endregion
}
}
diff --git a/ExifLibrary/ExifProperty.cs b/ExifLibrary/ExifProperty.cs
index 5b6558a..18eb624 100644
--- a/ExifLibrary/ExifProperty.cs
+++ b/ExifLibrary/ExifProperty.cs
@@ -130,7 +130,7 @@ public class ExifAscii : ExifProperty
protected string mValue;
protected override object _Value { get { return Value; } set { Value = (string)value; } }
public new string Value { get { return mValue; } set { mValue = value; } }
-
+
public Encoding Encoding { get; private set; }
static public implicit operator string(ExifAscii obj) { return obj.mValue; }
@@ -260,7 +260,7 @@ public class ExifUIntArray : ExifProperty
protected override object _Value { get { return Value; } set { Value = (uint[])value; } }
public new uint[] Value { get { return mValue; } set { mValue = value; } }
- static public implicit operator uint[] (ExifUIntArray obj) { return obj.mValue; }
+ static public implicit operator uint[](ExifUIntArray obj) { return obj.mValue; }
public override string ToString()
{
@@ -575,4 +575,73 @@ public override ExifInterOperability Interoperability
}
}
}
+
+ ///
+ /// Represents a 16-bit signed integer. (EXIF Specification: SHORT)
+ ///
+ public class ExifSShort : ExifProperty
+ {
+ protected short mValue;
+ protected override object _Value { get { return Value; } set { Value = Convert.ToInt16(value); } }
+ public new short Value { get { return mValue; } set { mValue = value; } }
+
+ static public implicit operator short(ExifSShort obj) { return obj.mValue; }
+
+ public override string ToString() { return mValue.ToString(); }
+
+ public ExifSShort(ExifTag tag, short value)
+ : base(tag)
+ {
+ mValue = value;
+ }
+
+ public override ExifInterOperability Interoperability
+ {
+ get
+ {
+ return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), InterOpType.SSHORT, 1, ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder, BitConverterEx.SystemByteOrder));
+ }
+ }
+ }
+
+ ///
+ /// Represents an array of 16-bit signed integers.
+ /// (EXIF Specification: SHORT with count > 1)
+ ///
+ public class ExifSShortArray : ExifProperty
+ {
+ protected short[] mValue;
+ protected override object _Value { get { return Value; } set { Value = (short[])value; } }
+ public new short[] Value { get { return mValue; } set { mValue = value; } }
+
+ static public implicit operator short[] (ExifSShortArray obj) { return obj.mValue; }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append('[');
+ foreach (ushort b in mValue)
+ {
+ sb.Append(b);
+ sb.Append(' ');
+ }
+ sb.Remove(sb.Length - 1, 1);
+ sb.Append(']');
+ return sb.ToString();
+ }
+
+ public ExifSShortArray(ExifTag tag, short[] value)
+ : base(tag)
+ {
+ mValue = value;
+ }
+
+ public override ExifInterOperability Interoperability
+ {
+ get
+ {
+ return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), InterOpType.SSHORT, (uint)mValue.Length, ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
+ }
+ }
+ }
}
diff --git a/ExifLibrary/ExifPropertyFactory.cs b/ExifLibrary/ExifPropertyFactory.cs
index 7fefbe3..16d0aea 100644
--- a/ExifLibrary/ExifPropertyFactory.cs
+++ b/ExifLibrary/ExifPropertyFactory.cs
@@ -134,7 +134,7 @@ public static ExifProperty Get(ushort tag, ushort type, uint count, byte[] value
else if (ifd == IFD.GPS)
{
if (tag == 0) // GPSVersionID
- return new VersionID(ExifTag.GPSVersionID, value);
+ return new ExifVersion(ExifTag.GPSVersionID, ExifBitConverter.ToString(value));
else if (tag == 1) // GPSLatitudeRef
return new ExifEnumProperty(ExifTag.GPSLatitudeRef, (GPSLatitudeRef)value[0]);
else if (tag == 2) // GPSLatitude
@@ -233,6 +233,13 @@ public static ExifProperty Get(ushort tag, ushort type, uint count, byte[] value
}
else if (type == 7) // 7 = UNDEFINED An 8-bit byte that can take any value depending on the field definition.
return new ExifUndefined(etag, value);
+ else if (type == 8) // 8 = SSHORT A 16-bit (2-byte) signed integer.
+ {
+ if (count == 1)
+ return new ExifSShort(etag, conv.ToInt16(value, 0));
+ else
+ return new ExifSShortArray(etag, ExifBitConverter.ToSShortArray(value, (int)count, byteOrder));
+ }
else if (type == 9) // 9 = SLONG A 32-bit (4-byte) signed integer (2's complement notation).
{
if (count == 1)
diff --git a/ExifLibrary/JPEGFile.cs b/ExifLibrary/JPEGFile.cs
index d79ab01..0e3c13e 100644
--- a/ExifLibrary/JPEGFile.cs
+++ b/ExifLibrary/JPEGFile.cs
@@ -495,6 +495,8 @@ private void ReadExifAPP1()
int thumboffset = -1;
int thumblength = 0;
int thumbtype = -1;
+
+
// Read IFDs
while (ifdqueue.Count != 0)
{
@@ -539,12 +541,14 @@ private void ReadExifAPP1()
uint baselength = 0;
if (type == 1 || type == 2 || type == 7)
baselength = 1;
- else if (type == 3)
+ else if (type == 3 || type == 8)
baselength = 2;
else if (type == 4 || type == 9)
baselength = 4;
else if (type == 5 || type == 10)
baselength = 8;
+ else // Unknown or invalid type
+ continue; // Skip and keep going
uint totallength = count * baselength;
// If field value does not fit in 4 bytes
@@ -596,11 +600,13 @@ private void ReadExifAPP1()
// 1st IFD pointer
int firstifdoffset = ifdoffset + 2 + 12 * fieldcount;
- if (firstifdoffset + 4 <= header.Length)
+ if (firstifdoffset + 4 <= header.Length && currentifd == IFD.Zeroth)
{
int firstifdpointer = (int)conv.ToUInt32(header, firstifdoffset);
if (firstifdpointer != 0 && firstifdpointer + 2 <= header.Length)
+ {
ifdqueue.Add(firstifdpointer, IFD.First);
+ }
}
// Read thumbnail
if (thumboffset != -1 && thumblength != 0 && Thumbnail == null)