public virtual void TestGetInt16()
        {
            Sharpen.Tests.AreEqual(-1, CreateReader(new sbyte[] { unchecked ((sbyte)unchecked ((int)(0xff))), unchecked ((sbyte)unchecked ((int)(0xff))) }).GetInt16(0));
            sbyte[]            buffer = new sbyte[] { unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((sbyte)unchecked ((int)(0x7F))), unchecked ((sbyte)unchecked ((int)(0xFF))) };
            RandomAccessReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual((short)unchecked ((int)(0x0001)), reader.GetInt16(0));
            Sharpen.Tests.AreEqual((short)unchecked ((int)(0x017F)), reader.GetInt16(1));
            Sharpen.Tests.AreEqual((short)unchecked ((int)(0x7FFF)), reader.GetInt16(2));
            reader.SetMotorolaByteOrder(false);
            Sharpen.Tests.AreEqual((short)unchecked ((int)(0x0100)), reader.GetInt16(0));
            Sharpen.Tests.AreEqual((short)unchecked ((int)(0x7F01)), reader.GetInt16(1));
            Sharpen.Tests.AreEqual(unchecked ((short)(0xFF7F)), reader.GetInt16(2));
        }
		/// <summary>Processes a TIFF data sequence.</summary>
		/// <param name="reader">
		/// the
		/// <see cref="Com.Drew.Lang.RandomAccessReader"/>
		/// from which the data should be read
		/// </param>
		/// <param name="handler">
		/// the
		/// <see cref="TiffHandler"/>
		/// that will coordinate processing and accept read values
		/// </param>
		/// <param name="tiffHeaderOffset">the offset within <code>reader</code> at which the TIFF header starts</param>
		/// <exception cref="TiffProcessingException">
		/// if an error occurred during the processing of TIFF data that could not be
		/// ignored or recovered from
		/// </exception>
		/// <exception cref="System.IO.IOException">an error occurred while accessing the required data</exception>
		/// <exception cref="Com.Drew.Imaging.Tiff.TiffProcessingException"/>
		public virtual void ProcessTiff(RandomAccessReader reader, TiffHandler handler, int tiffHeaderOffset)
		{
			// This must be either "MM" or "II".
			short byteOrderIdentifier = reader.GetInt16(tiffHeaderOffset);
			if (byteOrderIdentifier == unchecked((int)(0x4d4d)))
			{
				// "MM"
				reader.SetMotorolaByteOrder(true);
			}
			else
			{
				if (byteOrderIdentifier == unchecked((int)(0x4949)))
				{
					// "II"
					reader.SetMotorolaByteOrder(false);
				}
				else
				{
					throw new TiffProcessingException("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier);
				}
			}
			// Check the next two values for correctness.
			int tiffMarker = reader.GetUInt16(2 + tiffHeaderOffset);
			handler.SetTiffMarker(tiffMarker);
			int firstIfdOffset = reader.GetInt32(4 + tiffHeaderOffset) + tiffHeaderOffset;
			// David Ekholm sent a digital camera image that has this problem
			// TODO getLength should be avoided as it causes RandomAccessStreamReader to read to the end of the stream
			if (firstIfdOffset >= reader.GetLength() - 1)
			{
				handler.Warn("First IFD offset is beyond the end of the TIFF data segment -- trying default offset");
				// First directory normally starts immediately after the offset bytes, so try that
				firstIfdOffset = tiffHeaderOffset + 2 + 2 + 4;
			}
			ICollection<int> processedIfdOffsets = new HashSet<int>();
			ProcessIfd(handler, reader, processedIfdOffsets, firstIfdOffset, tiffHeaderOffset);
			handler.Completed(reader, tiffHeaderOffset);
		}
		private static void ProcessTag(Com.Drew.Metadata.Directory directory, int tagType, int tagValueOffset, int componentCount, int formatCode, RandomAccessReader reader)
		{
			switch (formatCode)
			{
				case FmtUndefined:
				{
					// Directory simply stores raw values
					// The display side uses a Descriptor class per directory to turn the raw values into 'pretty' descriptions
					// this includes exif user comments
					directory.SetByteArray(tagType, reader.GetBytes(tagValueOffset, componentCount));
					break;
				}

				case FmtString:
				{
					string @string = reader.GetNullTerminatedString(tagValueOffset, componentCount);
					directory.SetString(tagType, @string);
					break;
				}

				case FmtSrational:
				{
					if (componentCount == 1)
					{
						directory.SetRational(tagType, new Rational(reader.GetInt32(tagValueOffset), reader.GetInt32(tagValueOffset + 4)));
					}
					else
					{
						if (componentCount > 1)
						{
							Rational[] rationals = new Rational[componentCount];
							for (int i = 0; i < componentCount; i++)
							{
								rationals[i] = new Rational(reader.GetInt32(tagValueOffset + (8 * i)), reader.GetInt32(tagValueOffset + 4 + (8 * i)));
							}
							directory.SetRationalArray(tagType, rationals);
						}
					}
					break;
				}

				case FmtUrational:
				{
					if (componentCount == 1)
					{
						directory.SetRational(tagType, new Rational(reader.GetUInt32(tagValueOffset), reader.GetUInt32(tagValueOffset + 4)));
					}
					else
					{
						if (componentCount > 1)
						{
							Rational[] rationals = new Rational[componentCount];
							for (int i = 0; i < componentCount; i++)
							{
								rationals[i] = new Rational(reader.GetUInt32(tagValueOffset + (8 * i)), reader.GetUInt32(tagValueOffset + 4 + (8 * i)));
							}
							directory.SetRationalArray(tagType, rationals);
						}
					}
					break;
				}

				case FmtSingle:
				{
					if (componentCount == 1)
					{
						directory.SetFloat(tagType, reader.GetFloat32(tagValueOffset));
					}
					else
					{
						float[] floats = new float[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							floats[i] = reader.GetFloat32(tagValueOffset + (i * 4));
						}
						directory.SetFloatArray(tagType, floats);
					}
					break;
				}

				case FmtDouble:
				{
					if (componentCount == 1)
					{
						directory.SetDouble(tagType, reader.GetDouble64(tagValueOffset));
					}
					else
					{
						double[] doubles = new double[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							doubles[i] = reader.GetDouble64(tagValueOffset + (i * 4));
						}
						directory.SetDoubleArray(tagType, doubles);
					}
					break;
				}

				case FmtSbyte:
				{
					//
					// Note that all integral types are stored as int32 internally (the largest supported by TIFF)
					//
					if (componentCount == 1)
					{
						directory.SetInt(tagType, reader.GetInt8(tagValueOffset));
					}
					else
					{
						int[] bytes = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							bytes[i] = reader.GetInt8(tagValueOffset + i);
						}
						directory.SetIntArray(tagType, bytes);
					}
					break;
				}

				case FmtByte:
				{
					if (componentCount == 1)
					{
						directory.SetInt(tagType, reader.GetUInt8(tagValueOffset));
					}
					else
					{
						int[] bytes = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							bytes[i] = reader.GetUInt8(tagValueOffset + i);
						}
						directory.SetIntArray(tagType, bytes);
					}
					break;
				}

				case FmtUshort:
				{
					if (componentCount == 1)
					{
						int i = reader.GetUInt16(tagValueOffset);
						directory.SetInt(tagType, i);
					}
					else
					{
						int[] ints = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							ints[i] = reader.GetUInt16(tagValueOffset + (i * 2));
						}
						directory.SetIntArray(tagType, ints);
					}
					break;
				}

				case FmtSshort:
				{
					if (componentCount == 1)
					{
						int i = reader.GetInt16(tagValueOffset);
						directory.SetInt(tagType, i);
					}
					else
					{
						int[] ints = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							ints[i] = reader.GetInt16(tagValueOffset + (i * 2));
						}
						directory.SetIntArray(tagType, ints);
					}
					break;
				}

				case FmtSlong:
				case FmtUlong:
				{
					// NOTE 'long' in this case means 32 bit, not 64
					if (componentCount == 1)
					{
						int i = reader.GetInt32(tagValueOffset);
						directory.SetInt(tagType, i);
					}
					else
					{
						int[] ints = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							ints[i] = reader.GetInt32(tagValueOffset + (i * 4));
						}
						directory.SetIntArray(tagType, ints);
					}
					break;
				}

				default:
				{
					directory.AddError("Unknown format code " + formatCode + " for tag " + tagType);
					break;
				}
			}
		}
		private static void ProcessKodakMakernote(KodakMakernoteDirectory directory, int tagValueOffset, RandomAccessReader reader)
		{
			// Kodak's makernote is not in IFD format. It has values at fixed offsets.
			int dataOffset = tagValueOffset + 8;
			try
			{
				directory.SetString(KodakMakernoteDirectory.TagKodakModel, reader.GetString(dataOffset, 8));
				directory.SetInt(KodakMakernoteDirectory.TagQuality, reader.GetUInt8(dataOffset + 9));
				directory.SetInt(KodakMakernoteDirectory.TagBurstMode, reader.GetUInt8(dataOffset + 10));
				directory.SetInt(KodakMakernoteDirectory.TagImageWidth, reader.GetUInt16(dataOffset + 12));
				directory.SetInt(KodakMakernoteDirectory.TagImageHeight, reader.GetUInt16(dataOffset + 14));
				directory.SetInt(KodakMakernoteDirectory.TagYearCreated, reader.GetUInt16(dataOffset + 16));
				directory.SetByteArray(KodakMakernoteDirectory.TagMonthDayCreated, reader.GetBytes(dataOffset + 18, 2));
				directory.SetByteArray(KodakMakernoteDirectory.TagTimeCreated, reader.GetBytes(dataOffset + 20, 4));
				directory.SetInt(KodakMakernoteDirectory.TagBurstMode2, reader.GetUInt16(dataOffset + 24));
				directory.SetInt(KodakMakernoteDirectory.TagShutterMode, reader.GetUInt8(dataOffset + 27));
				directory.SetInt(KodakMakernoteDirectory.TagMeteringMode, reader.GetUInt8(dataOffset + 28));
				directory.SetInt(KodakMakernoteDirectory.TagSequenceNumber, reader.GetUInt8(dataOffset + 29));
				directory.SetInt(KodakMakernoteDirectory.TagFNumber, reader.GetUInt16(dataOffset + 30));
				directory.SetLong(KodakMakernoteDirectory.TagExposureTime, reader.GetUInt32(dataOffset + 32));
				directory.SetInt(KodakMakernoteDirectory.TagExposureCompensation, reader.GetInt16(dataOffset + 36));
				directory.SetInt(KodakMakernoteDirectory.TagFocusMode, reader.GetUInt8(dataOffset + 56));
				directory.SetInt(KodakMakernoteDirectory.TagWhiteBalance, reader.GetUInt8(dataOffset + 64));
				directory.SetInt(KodakMakernoteDirectory.TagFlashMode, reader.GetUInt8(dataOffset + 92));
				directory.SetInt(KodakMakernoteDirectory.TagFlashFired, reader.GetUInt8(dataOffset + 93));
				directory.SetInt(KodakMakernoteDirectory.TagIsoSetting, reader.GetUInt16(dataOffset + 94));
				directory.SetInt(KodakMakernoteDirectory.TagIso, reader.GetUInt16(dataOffset + 96));
				directory.SetInt(KodakMakernoteDirectory.TagTotalZoom, reader.GetUInt16(dataOffset + 98));
				directory.SetInt(KodakMakernoteDirectory.TagDateTimeStamp, reader.GetUInt16(dataOffset + 100));
				directory.SetInt(KodakMakernoteDirectory.TagColorMode, reader.GetUInt16(dataOffset + 102));
				directory.SetInt(KodakMakernoteDirectory.TagDigitalZoom, reader.GetUInt16(dataOffset + 104));
				directory.SetInt(KodakMakernoteDirectory.TagSharpness, reader.GetInt8(dataOffset + 107));
			}
			catch (IOException ex)
			{
				directory.AddError("Error processing Kodak makernote data: " + ex.Message);
			}
		}
		/// <exception cref="System.IO.IOException"/>
		private static void ProcessTag(TiffHandler handler, int tagId, int tagValueOffset, int componentCount, int formatCode, RandomAccessReader reader)
		{
			switch (formatCode)
			{
				case TiffDataFormat.CodeUndefined:
				{
					// this includes exif user comments
					handler.SetByteArray(tagId, reader.GetBytes(tagValueOffset, componentCount));
					break;
				}

				case TiffDataFormat.CodeString:
				{
					handler.SetString(tagId, reader.GetNullTerminatedString(tagValueOffset, componentCount));
					break;
				}

				case TiffDataFormat.CodeRationalS:
				{
					if (componentCount == 1)
					{
						handler.SetRational(tagId, new Rational(reader.GetInt32(tagValueOffset), reader.GetInt32(tagValueOffset + 4)));
					}
					else
					{
						if (componentCount > 1)
						{
							Rational[] array = new Rational[componentCount];
							for (int i = 0; i < componentCount; i++)
							{
								array[i] = new Rational(reader.GetInt32(tagValueOffset + (8 * i)), reader.GetInt32(tagValueOffset + 4 + (8 * i)));
							}
							handler.SetRationalArray(tagId, array);
						}
					}
					break;
				}

				case TiffDataFormat.CodeRationalU:
				{
					if (componentCount == 1)
					{
						handler.SetRational(tagId, new Rational(reader.GetUInt32(tagValueOffset), reader.GetUInt32(tagValueOffset + 4)));
					}
					else
					{
						if (componentCount > 1)
						{
							Rational[] array = new Rational[componentCount];
							for (int i = 0; i < componentCount; i++)
							{
								array[i] = new Rational(reader.GetUInt32(tagValueOffset + (8 * i)), reader.GetUInt32(tagValueOffset + 4 + (8 * i)));
							}
							handler.SetRationalArray(tagId, array);
						}
					}
					break;
				}

				case TiffDataFormat.CodeSingle:
				{
					if (componentCount == 1)
					{
						handler.SetFloat(tagId, reader.GetFloat32(tagValueOffset));
					}
					else
					{
						float[] array = new float[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetFloat32(tagValueOffset + (i * 4));
						}
						handler.SetFloatArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeDouble:
				{
					if (componentCount == 1)
					{
						handler.SetDouble(tagId, reader.GetDouble64(tagValueOffset));
					}
					else
					{
						double[] array = new double[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetDouble64(tagValueOffset + (i * 4));
						}
						handler.SetDoubleArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeInt8S:
				{
					if (componentCount == 1)
					{
						handler.SetInt8s(tagId, reader.GetInt8(tagValueOffset));
					}
					else
					{
						sbyte[] array = new sbyte[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetInt8(tagValueOffset + i);
						}
						handler.SetInt8sArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeInt8U:
				{
					if (componentCount == 1)
					{
						handler.SetInt8u(tagId, reader.GetUInt8(tagValueOffset));
					}
					else
					{
						short[] array = new short[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetUInt8(tagValueOffset + i);
						}
						handler.SetInt8uArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeInt16S:
				{
					if (componentCount == 1)
					{
						handler.SetInt16s(tagId, (int)reader.GetInt16(tagValueOffset));
					}
					else
					{
						short[] array = new short[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetInt16(tagValueOffset + (i * 2));
						}
						handler.SetInt16sArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeInt16U:
				{
					if (componentCount == 1)
					{
						handler.SetInt16u(tagId, reader.GetUInt16(tagValueOffset));
					}
					else
					{
						int[] array = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetUInt16(tagValueOffset + (i * 2));
						}
						handler.SetInt16uArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeInt32S:
				{
					// NOTE 'long' in this case means 32 bit, not 64
					if (componentCount == 1)
					{
						handler.SetInt32s(tagId, reader.GetInt32(tagValueOffset));
					}
					else
					{
						int[] array = new int[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetInt32(tagValueOffset + (i * 4));
						}
						handler.SetInt32sArray(tagId, array);
					}
					break;
				}

				case TiffDataFormat.CodeInt32U:
				{
					// NOTE 'long' in this case means 32 bit, not 64
					if (componentCount == 1)
					{
						handler.SetInt32u(tagId, reader.GetUInt32(tagValueOffset));
					}
					else
					{
						long[] array = new long[componentCount];
						for (int i = 0; i < componentCount; i++)
						{
							array[i] = reader.GetUInt32(tagValueOffset + (i * 4));
						}
						handler.SetInt32uArray(tagId, array);
					}
					break;
				}

				default:
				{
					handler.Error(Sharpen.Extensions.StringFormat("Unknown format code %d for tag %d", formatCode, tagId));
					break;
				}
			}
		}