public virtual void TestTrySkipEOF()
        {
            Sharpen.Tests.IsTrue(CreateReader(new sbyte[1]).TrySkip(1));
            SequentialReader reader = CreateReader(new sbyte[2]);

            Sharpen.Tests.IsTrue(reader.TrySkip(1));
            Sharpen.Tests.IsTrue(reader.TrySkip(1));
            Sharpen.Tests.IsFalse(reader.TrySkip(1));
        }
Ejemplo n.º 2
0
        public virtual void TestGetFloat64()
        {
            long nanBits = unchecked ((long)(0xfff0000000000001L));

            Sharpen.Tests.IsTrue(double.IsNaN(Sharpen.Extensions.LongBitsToDouble(nanBits)));
            sbyte[]          buffer = new sbyte[] { unchecked ((sbyte)0xff), unchecked ((sbyte)0xf0), unchecked ((int)(0x00)), unchecked ((int)(0x00)), unchecked ((int)(0x00)), unchecked ((int)(0x00)), unchecked ((int)(0x00)), unchecked ((int)(0x01)) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.IsTrue(double.IsNaN(reader.GetDouble64()));
        }
        public virtual void TestGetFloat32()
        {
            int nanBits = unchecked ((int)(0x7fc00000));

            Sharpen.Tests.IsTrue(float.IsNaN(Sharpen.Extensions.IntBitsToFloat(nanBits)));
            sbyte[]          buffer = new sbyte[] { unchecked ((int)(0x7f)), unchecked ((sbyte)unchecked ((int)(0xc0))), unchecked ((int)(0x00)), unchecked ((int)(0x00)) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.IsTrue(float.IsNaN(reader.GetFloat32()));
        }
Ejemplo n.º 4
0
        public virtual void TestGetInt8()
        {
            sbyte[]          buffer = new sbyte[] { unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((sbyte)0x7F), unchecked ((sbyte)0xFF) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual(unchecked ((sbyte)0), reader.GetInt8());
            Sharpen.Tests.AreEqual(unchecked ((sbyte)1), reader.GetInt8());
            Sharpen.Tests.AreEqual(unchecked ((sbyte)127), reader.GetInt8());
            Sharpen.Tests.AreEqual(unchecked ((sbyte)255), reader.GetInt8());
        }
        public virtual void TestGetUInt8()
        {
            sbyte[]          buffer = new sbyte[] { unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((sbyte)unchecked ((int)(0x7F))), unchecked ((sbyte)unchecked ((int)(0xFF))) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual(0, reader.GetUInt8());
            Sharpen.Tests.AreEqual(1, reader.GetUInt8());
            Sharpen.Tests.AreEqual(127, reader.GetUInt8());
            Sharpen.Tests.AreEqual(255, reader.GetUInt8());
        }
        public virtual void TestGetInt64()
        {
            sbyte[] buffer          = new sbyte[] { unchecked ((sbyte)unchecked ((int)(0xFF))), unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((int)(0x02)), unchecked ((int)(0x03)), unchecked ((int)(0x04)), unchecked (
                                                        (int)(0x05)), unchecked ((int)(0x06)), unchecked ((int)(0x07)) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual(unchecked ((long)(0xFF00010203040506L)), reader.GetInt64());
            reader = CreateReader(buffer);
            reader.SetMotorolaByteOrder(false);
            Sharpen.Tests.AreEqual(unchecked ((long)(0x06050403020100FFL)), reader.GetInt64());
        }
        public virtual void TestGetUInt16()
        {
            sbyte[]          buffer = new sbyte[] { unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((sbyte)unchecked ((int)(0x7F))), unchecked ((sbyte)unchecked ((int)(0xFF))) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual(unchecked ((int)(0x0001)), reader.GetUInt16());
            Sharpen.Tests.AreEqual(unchecked ((int)(0x7FFF)), reader.GetUInt16());
            reader = CreateReader(buffer);
            reader.SetMotorolaByteOrder(false);
            Sharpen.Tests.AreEqual(unchecked ((int)(0x0100)), reader.GetUInt16());
            Sharpen.Tests.AreEqual(unchecked ((int)(0xFF7F)), reader.GetUInt16());
        }
        public virtual void TestOverflowBoundsCalculation()
        {
            SequentialReader reader = CreateReader(new sbyte[10]);

            try
            {
                reader.GetBytes(15);
            }
            catch (IOException e)
            {
                Sharpen.Tests.AreEqual("End of data reached.", e.Message);
            }
        }
Ejemplo n.º 9
0
        public virtual void TestGetInt32()
        {
            Sharpen.Tests.AreEqual(-1, CreateReader(new sbyte[] { unchecked ((sbyte)0xff), unchecked ((sbyte)0xff), unchecked ((sbyte)0xff), unchecked ((sbyte)0xff) }).GetInt32());
            sbyte[]          buffer = new sbyte[] { unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((int)(0x02)), unchecked ((int)(0x03)), unchecked ((int)(0x04)), unchecked ((int)(0x05)), unchecked ((int)(0x06)), unchecked ((int)(0x07)) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual(unchecked ((int)(0x00010203)), reader.GetInt32());
            Sharpen.Tests.AreEqual(unchecked ((int)(0x04050607)), reader.GetInt32());
            reader = CreateReader(buffer);
            reader.SetMotorolaByteOrder(false);
            Sharpen.Tests.AreEqual(unchecked ((int)(0x03020100)), reader.GetInt32());
            Sharpen.Tests.AreEqual(unchecked ((int)(0x07060504)), reader.GetInt32());
        }
Ejemplo n.º 10
0
        public virtual void TestGetInt16()
        {
            Sharpen.Tests.AreEqual(-1, CreateReader(new sbyte[] { unchecked ((sbyte)0xff), unchecked ((sbyte)0xff) }).GetInt16());
            sbyte[]          buffer = new sbyte[] { unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((sbyte)0x7F), unchecked ((sbyte)0xFF) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual((short)0x0001, reader.GetInt16());
            Sharpen.Tests.AreEqual((short)0x7FFF, reader.GetInt16());
            reader = CreateReader(buffer);
            reader.SetMotorolaByteOrder(false);
            Sharpen.Tests.AreEqual((short)0x0100, reader.GetInt16());
            Sharpen.Tests.AreEqual(unchecked ((short)(0xFF7F)), reader.GetInt16());
        }
 public virtual void TestGetBytes()
 {
     sbyte[] bytes = new sbyte[] { 0, 1, 2, 3, 4, 5 };
     for (int i = 0; i < bytes.Length; i++)
     {
         SequentialReader reader    = CreateReader(bytes);
         sbyte[]          readBytes = reader.GetBytes(i);
         for (int j = 0; j < i; j++)
         {
             Sharpen.Tests.AreEqual(bytes[j], readBytes[j]);
         }
     }
 }
 public virtual void TestGetInt64_OutOfBounds()
 {
     try
     {
         SequentialReader reader = CreateReader(new sbyte[7]);
         reader.GetInt64();
         NUnit.Framework.Assert.Fail("Exception expected");
     }
     catch (IOException ex)
     {
         Sharpen.Tests.AreEqual("End of data reached.", ex.Message);
     }
 }
Ejemplo n.º 13
0
        public virtual void TestGetUInt32()
        {
            Sharpen.Tests.AreEqual(4294967295L, CreateReader(new sbyte[] { unchecked ((sbyte)0xff), unchecked ((sbyte)0xff), unchecked ((sbyte)0xff), unchecked ((sbyte)0xff) }).GetUInt32());
            sbyte[]          buffer = new sbyte[] { unchecked ((sbyte)0xFF), unchecked ((int)(0x00)), unchecked ((int)(0x01)), unchecked ((int)(0x02)), unchecked ((int)(0x03)), unchecked ((int)(0x04)), unchecked ((int)(0x05)), unchecked ((int)(0x06)) };
            SequentialReader reader = CreateReader(buffer);

            Sharpen.Tests.AreEqual(unchecked ((long)(0xFF000102L)), reader.GetUInt32());
            Sharpen.Tests.AreEqual(unchecked ((long)(0x03040506L)), reader.GetUInt32());
            reader = CreateReader(buffer);
            reader.SetMotorolaByteOrder(false);
            Sharpen.Tests.AreEqual(unchecked ((long)(0x020100FFL)), reader.GetUInt32());
            // 0x0010200FF
            Sharpen.Tests.AreEqual(unchecked ((long)(0x06050403L)), reader.GetUInt32());
        }
        public virtual void TestGetBytesEOF()
        {
            CreateReader(new sbyte[50]).GetBytes(50);
            SequentialReader reader = CreateReader(new sbyte[50]);

            reader.GetBytes(25);
            reader.GetBytes(25);
            try
            {
                CreateReader(new sbyte[50]).GetBytes(51);
                NUnit.Framework.Assert.Fail("Expecting exception");
            }
            catch (EOFException)
            {
            }
        }
        public virtual void TestSkipEOF()
        {
            CreateReader(new sbyte[1]).Skip(1);
            SequentialReader reader = CreateReader(new sbyte[2]);

            reader.Skip(1);
            reader.Skip(1);
            try
            {
                reader = CreateReader(new sbyte[1]);
                reader.Skip(1);
                reader.Skip(1);
                NUnit.Framework.Assert.Fail("Expecting exception");
            }
            catch (EOFException)
            {
            }
        }
		public virtual void Extract(SequentialReader reader, Com.Drew.Metadata.Metadata metadata)
		{
			Com.Drew.Metadata.Directory directory = metadata.GetOrCreateDirectory<AdobeJpegDirectory>();
			try
			{
				reader.SetMotorolaByteOrder(false);
				if (!reader.GetString(5).Equals("Adobe"))
				{
					directory.AddError("Invalid Adobe JPEG data header.");
					return;
				}
				directory.SetInt(AdobeJpegDirectory.TagDctEncodeVersion, reader.GetUInt16());
				directory.SetInt(AdobeJpegDirectory.TagApp14Flags0, reader.GetUInt16());
				directory.SetInt(AdobeJpegDirectory.TagApp14Flags1, reader.GetUInt16());
				directory.SetInt(AdobeJpegDirectory.TagColorTransform, reader.GetInt8());
			}
			catch (IOException ex)
			{
				directory.AddError("IO exception processing data: " + ex.Message);
			}
		}
Ejemplo n.º 17
0
		/// <exception cref="Com.Drew.Imaging.Png.PngProcessingException"/>
		/// <exception cref="System.IO.IOException"/>
		public virtual Iterable<PngChunk> Extract(SequentialReader reader, ICollection<PngChunkType> desiredChunkTypes)
		{
			//
			// PNG DATA STREAM
			//
			// Starts with a PNG SIGNATURE, followed by a sequence of CHUNKS.
			//
			// PNG SIGNATURE
			//
			//   Always composed of these bytes: 89 50 4E 47 0D 0A 1A 0A
			//
			// CHUNK
			//
			//   4 - length of the data field (unsigned, but always within 31 bytes), may be zero
			//   4 - chunk type, restricted to [65,90] and [97,122] (A-Za-z)
			//   * - data field
			//   4 - CRC calculated from chunk type and chunk data, but not length
			//
			// CHUNK TYPES
			//
			//   Critical Chunk Types:
			//
			//     IHDR - image header, always the first chunk in the data stream
			//     PLTE - palette table, associated with indexed PNG images
			//     IDAT - image data chunk, of which there may be many
			//     IEND - image trailer, always the last chunk in the data stream
			//
			//   Ancillary Chunk Types:
			//
			//     Transparency information:  tRNS
			//     Colour space information:  cHRM, gAMA, iCCP, sBIT, sRGB
			//     Textual information:       iTXt, tEXt, zTXt
			//     Miscellaneous information: bKGD, hIST, pHYs, sPLT
			//     Time information:          tIME
			//
			reader.SetMotorolaByteOrder(true);
			// network byte order
			if (!Arrays.Equals(PngSignatureBytes, reader.GetBytes(PngSignatureBytes.Length)))
			{
				throw new PngProcessingException("PNG signature mismatch");
			}
			bool seenImageHeader = false;
			bool seenImageTrailer = false;
			IList<PngChunk> chunks = new AList<PngChunk>();
			ICollection<PngChunkType> seenChunkTypes = new HashSet<PngChunkType>();
			while (!seenImageTrailer)
			{
				// Process the next chunk.
				int chunkDataLength = reader.GetInt32();
				PngChunkType chunkType = new PngChunkType(reader.GetBytes(4));
				sbyte[] chunkData = reader.GetBytes(chunkDataLength);
				// Skip the CRC bytes at the end of the chunk
				// TODO consider verifying the CRC value to determine if we're processing bad data
				reader.Skip(4);
				if (seenChunkTypes.Contains(chunkType) && !chunkType.AreMultipleAllowed())
				{
					throw new PngProcessingException(Sharpen.Extensions.StringFormat("Observed multiple instances of PNG chunk '%s', for which multiples are not allowed", chunkType));
				}
				if (chunkType.Equals(PngChunkType.Ihdr))
				{
					seenImageHeader = true;
				}
				else
				{
					if (!seenImageHeader)
					{
						throw new PngProcessingException(Sharpen.Extensions.StringFormat("First chunk should be '%s', but '%s' was observed", PngChunkType.Ihdr, chunkType));
					}
				}
				if (chunkType.Equals(PngChunkType.Iend))
				{
					seenImageTrailer = true;
				}
				if (desiredChunkTypes == null || desiredChunkTypes.Contains(chunkType))
				{
					chunks.Add(new PngChunk(chunkType, chunkData));
				}
				seenChunkTypes.Add(chunkType);
			}
			return chunks.AsIterable();
		}
Ejemplo n.º 18
0
		public virtual void Extract(SequentialReader reader, Com.Drew.Metadata.Metadata metadata)
		{
			BmpHeaderDirectory directory = metadata.GetOrCreateDirectory<BmpHeaderDirectory>();
			// FILE HEADER
			//
			// 2 - magic number (0x42 0x4D = "BM")
			// 4 - size of BMP file in bytes
			// 2 - reserved
			// 2 - reserved
			// 4 - the offset of the pixel array
			//
			// BITMAP INFORMATION HEADER
			//
			// The first four bytes of the header give the size, which is a discriminator of the actual header format.
			// See this for more information http://en.wikipedia.org/wiki/BMP_file_format
			//
			// BITMAPINFOHEADER (size = 40)
			//
			// 4 - size of header
			// 4 - pixel width (signed)
			// 4 - pixel height (signed)
			// 2 - number of colour planes (must be set to 1)
			// 2 - number of bits per pixel
			// 4 - compression being used (needs decoding)
			// 4 - pixel data length (not total file size, just pixel array)
			// 4 - horizontal resolution, pixels/meter (signed)
			// 4 - vertical resolution, pixels/meter (signed)
			// 4 - number of colours in the palette (0 means no palette)
			// 4 - number of important colours (generally ignored)
			//
			// BITMAPCOREHEADER (size = 12)
			//
			// 4 - size of header
			// 2 - pixel width
			// 2 - pixel height
			// 2 - number of colour planes (must be set to 1)
			// 2 - number of bits per pixel
			//
			// COMPRESSION VALUES
			//
			// 0 = None
			// 1 = RLE 8-bit/pixel
			// 2 = RLE 4-bit/pixel
			// 3 = Bit field (or Huffman 1D if BITMAPCOREHEADER2 (size 64))
			// 4 = JPEG (or RLE-24 if BITMAPCOREHEADER2 (size 64))
			// 5 = PNG
			// 6 = Bit field
			reader.SetMotorolaByteOrder(false);
			try
			{
				int magicNumber = reader.GetUInt16();
				if (magicNumber != unchecked((int)(0x4D42)))
				{
					directory.AddError("Invalid BMP magic number");
					return;
				}
				// skip past the rest of the file header
				reader.Skip(4 + 2 + 2 + 4);
				int headerSize = reader.GetInt32();
				directory.SetInt(BmpHeaderDirectory.TagHeaderSize, headerSize);
				// We expect the header size to be either 40 (BITMAPINFOHEADER) or 12 (BITMAPCOREHEADER)
				if (headerSize == 40)
				{
					// BITMAPINFOHEADER
					directory.SetInt(BmpHeaderDirectory.TagImageWidth, reader.GetInt32());
					directory.SetInt(BmpHeaderDirectory.TagImageHeight, reader.GetInt32());
					directory.SetInt(BmpHeaderDirectory.TagColourPlanes, reader.GetInt16());
					directory.SetInt(BmpHeaderDirectory.TagBitsPerPixel, reader.GetInt16());
					directory.SetInt(BmpHeaderDirectory.TagCompression, reader.GetInt32());
					// skip the pixel data length
					reader.Skip(4);
					directory.SetInt(BmpHeaderDirectory.TagXPixelsPerMeter, reader.GetInt32());
					directory.SetInt(BmpHeaderDirectory.TagYPixelsPerMeter, reader.GetInt32());
					directory.SetInt(BmpHeaderDirectory.TagPaletteColourCount, reader.GetInt32());
					directory.SetInt(BmpHeaderDirectory.TagImportantColourCount, reader.GetInt32());
				}
				else
				{
					if (headerSize == 12)
					{
						directory.SetInt(BmpHeaderDirectory.TagImageWidth, reader.GetInt16());
						directory.SetInt(BmpHeaderDirectory.TagImageHeight, reader.GetInt16());
						directory.SetInt(BmpHeaderDirectory.TagColourPlanes, reader.GetInt16());
						directory.SetInt(BmpHeaderDirectory.TagBitsPerPixel, reader.GetInt16());
					}
					else
					{
						directory.AddError("Unexpected DIB header size: " + headerSize);
					}
				}
			}
			catch (IOException)
			{
				directory.AddError("Unable to read BMP header");
			}
		}
Ejemplo n.º 19
0
		/// <summary>
		/// Performs the IPTC data extraction, adding found values to the specified instance of
		/// <see cref="Com.Drew.Metadata.Metadata"/>
		/// .
		/// </summary>
		public virtual void Extract(SequentialReader reader, Com.Drew.Metadata.Metadata metadata, long length)
		{
			IptcDirectory directory = metadata.GetOrCreateDirectory<IptcDirectory>();
			int offset = 0;
			// for each tag
			while (offset < length)
			{
				// identifies start of a tag
				short startByte;
				try
				{
					startByte = reader.GetUInt8();
					offset++;
				}
				catch (IOException)
				{
					directory.AddError("Unable to read starting byte of IPTC tag");
					return;
				}
				if (startByte != unchecked((int)(0x1c)))
				{
					directory.AddError("Invalid start to IPTC tag");
					return;
				}
				// we need at least five bytes left to read a tag
				if (offset + 5 >= length)
				{
					directory.AddError("Too few bytes remain for a valid IPTC tag");
					return;
				}
				int directoryType;
				int tagType;
				int tagByteCount;
				try
				{
					directoryType = reader.GetUInt8();
					tagType = reader.GetUInt8();
					tagByteCount = reader.GetUInt16();
					offset += 4;
				}
				catch (IOException)
				{
					directory.AddError("IPTC data segment ended mid-way through tag descriptor");
					return;
				}
				if (offset + tagByteCount > length)
				{
					directory.AddError("Data for tag extends beyond end of IPTC segment");
					return;
				}
				try
				{
					ProcessTag(reader, directory, directoryType, tagType, tagByteCount);
				}
				catch (IOException)
				{
					directory.AddError("Error processing IPTC tag");
					return;
				}
				offset += tagByteCount;
			}
		}
Ejemplo n.º 20
0
		/// <exception cref="System.IO.IOException"/>
		private void ProcessTag(SequentialReader reader, Com.Drew.Metadata.Directory directory, int directoryType, int tagType, int tagByteCount)
		{
			int tagIdentifier = tagType | (directoryType << 8);
			string @string = null;
			switch (tagIdentifier)
			{
				case IptcDirectory.TagApplicationRecordVersion:
				{
					// short
					int shortValue = reader.GetUInt16();
					reader.Skip(tagByteCount - 2);
					directory.SetInt(tagIdentifier, shortValue);
					return;
				}

				case IptcDirectory.TagUrgency:
				{
					// byte
					directory.SetInt(tagIdentifier, reader.GetUInt8());
					reader.Skip(tagByteCount - 1);
					return;
				}

				case IptcDirectory.TagReleaseDate:
				case IptcDirectory.TagDateCreated:
				{
					// Date object
					if (tagByteCount >= 8)
					{
						@string = reader.GetString(tagByteCount);
						try
						{
							int year = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 0, 4));
							int month = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 4, 6)) - 1;
							int day = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 6, 8));
							DateTime date = new Sharpen.GregorianCalendar(year, month, day).GetTime();
							directory.SetDate(tagIdentifier, date);
							return;
						}
						catch (FormatException)
						{
						}
					}
					else
					{
						// fall through and we'll process the 'string' value below
						reader.Skip(tagByteCount);
					}
					goto case IptcDirectory.TagReleaseTime;
				}

				case IptcDirectory.TagReleaseTime:
				case IptcDirectory.TagTimeCreated:
				default:
				{
					break;
				}
			}
			// time...
			// fall through
			// If we haven't returned yet, treat it as a string
			// NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value
			if (@string == null)
			{
				@string = reader.GetString(tagByteCount, Runtime.GetProperty("file.encoding"));
			}
			// "ISO-8859-1"
			if (directory.ContainsTag(tagIdentifier))
			{
				// this fancy string[] business avoids using an ArrayList for performance reasons
				string[] oldStrings = directory.GetStringArray(tagIdentifier);
				string[] newStrings;
				if (oldStrings == null)
				{
					newStrings = new string[1];
				}
				else
				{
					newStrings = new string[oldStrings.Length + 1];
					System.Array.Copy(oldStrings, 0, newStrings, 0, oldStrings.Length);
				}
				newStrings[newStrings.Length - 1] = @string;
				directory.SetStringArray(tagIdentifier, newStrings);
			}
			else
			{
				directory.SetString(tagIdentifier, @string);
			}
		}
Ejemplo n.º 21
0
		public virtual void Extract(SequentialReader reader, Com.Drew.Metadata.Metadata metadata)
		{
			GifHeaderDirectory directory = metadata.GetOrCreateDirectory<GifHeaderDirectory>();
			// FILE HEADER
			//
			// 3 - signature: "GIF"
			// 3 - version: either "87a" or "89a"
			//
			// LOGICAL SCREEN DESCRIPTOR
			//
			// 2 - pixel width
			// 2 - pixel height
			// 1 - screen and color map information flags (0 is LSB)
			//       0-2  Size of the global color table
			//       3    Color table sort flag (89a only)
			//       4-6  Color resolution
			//       7    Global color table flag
			// 1 - background color index
			// 1 - pixel aspect ratio
			reader.SetMotorolaByteOrder(false);
			try
			{
				string signature = reader.GetString(3);
				if (!signature.Equals("GIF"))
				{
					directory.AddError("Invalid GIF file signature");
					return;
				}
				string version = reader.GetString(3);
				if (!version.Equals(Gif87aVersionIdentifier) && !version.Equals(Gif89aVersionIdentifier))
				{
					directory.AddError("Unexpected GIF version");
					return;
				}
				directory.SetString(GifHeaderDirectory.TagGifFormatVersion, version);
				directory.SetInt(GifHeaderDirectory.TagImageWidth, reader.GetUInt16());
				directory.SetInt(GifHeaderDirectory.TagImageHeight, reader.GetUInt16());
				short flags = reader.GetUInt8();
				// First three bits = (BPP - 1)
				int colorTableSize = 1 << ((flags & 7) + 1);
				directory.SetInt(GifHeaderDirectory.TagColorTableSize, colorTableSize);
				if (version.Equals(Gif89aVersionIdentifier))
				{
					bool isColorTableSorted = (flags & 8) != 0;
					directory.SetBoolean(GifHeaderDirectory.TagIsColorTableSorted, isColorTableSorted);
				}
				int bitsPerPixel = ((flags & unchecked((int)(0x70))) >> 4) + 1;
				directory.SetInt(GifHeaderDirectory.TagBitsPerPixel, bitsPerPixel);
				bool hasGlobalColorTable = (flags & unchecked((int)(0xf))) != 0;
				directory.SetBoolean(GifHeaderDirectory.TagHasGlobalColorTable, hasGlobalColorTable);
				directory.SetInt(GifHeaderDirectory.TagTransparentColorIndex, reader.GetUInt8());
				int aspectRatioByte = reader.GetUInt8();
				if (aspectRatioByte != 0)
				{
					float pixelAspectRatio = (float)((aspectRatioByte + 15d) / 64d);
					directory.SetFloat(GifHeaderDirectory.TagPixelAspectRatio, pixelAspectRatio);
				}
			}
			catch (IOException)
			{
				directory.AddError("Unable to read BMP header");
			}
		}
		public static JpegSegmentData ReadSegments(SequentialReader reader, Iterable<JpegSegmentType> segmentTypes)
		{
			// Must be big-endian
			System.Diagnostics.Debug.Assert((reader.IsMotorolaByteOrder()));
			// first two bytes should be JPEG magic number
			int magicNumber = reader.GetUInt16();
			if (magicNumber != unchecked((int)(0xFFD8)))
			{
				throw new JpegProcessingException("JPEG data is expected to begin with 0xFFD8 (ГїГ�) not 0x" + Sharpen.Extensions.ToHexString(magicNumber));
			}
			ICollection<sbyte> segmentTypeBytes = null;
			if (segmentTypes != null)
			{
				segmentTypeBytes = new HashSet<sbyte>();
				foreach (JpegSegmentType segmentType in segmentTypes)
				{
					segmentTypeBytes.Add(segmentType.byteValue);
				}
			}
			JpegSegmentData segmentData = new JpegSegmentData();
			do
			{
				// next byte is the segment identifier: 0xFF
				short segmentIdentifier = reader.GetUInt8();
				if (segmentIdentifier != unchecked((int)(0xFF)))
				{
					throw new JpegProcessingException("Expected JPEG segment start identifier 0xFF, not 0x" + Sharpen.Extensions.ToHexString(segmentIdentifier));
				}
				// next byte is the segment type
				sbyte segmentType = reader.GetInt8();
				if (segmentType == SegmentSos)
				{
					// The 'Start-Of-Scan' segment's length doesn't include the image data, instead would
					// have to search for the two bytes: 0xFF 0xD9 (EOI).
					// It comes last so simply return at this point
					return segmentData;
				}
				if (segmentType == MarkerEoi)
				{
					// the 'End-Of-Image' segment -- this should never be found in this fashion
					return segmentData;
				}
				// next 2-bytes are <segment-size>: [high-byte] [low-byte]
				int segmentLength = reader.GetUInt16();
				// segment length includes size bytes, so subtract two
				segmentLength -= 2;
				if (segmentLength < 0)
				{
					throw new JpegProcessingException("JPEG segment size would be less than zero");
				}
				// Check whether we are interested in this segment
				if (segmentTypeBytes == null || segmentTypeBytes.Contains(segmentType))
				{
					sbyte[] segmentBytes = reader.GetBytes(segmentLength);
					System.Diagnostics.Debug.Assert((segmentLength == segmentBytes.Length));
					segmentData.AddSegment(segmentType, segmentBytes);
				}
				else
				{
					// Some if the JPEG is truncated, just return what data we've already gathered
					if (!reader.TrySkip(segmentLength))
					{
						return segmentData;
					}
				}
			}
			while (true);
		}