public static void Encode(Image image, string filePath)
		{
			using (var fileStream = File.Open(filePath, FileMode.Create))
			{
				Encode(image, fileStream);
			}
		}
		public static void Encode(Image image, Stream stream)
		{
			stream.WriteString(image.Header);
			stream.WriteBytes(image.LogicalScreenDescriptor.ToBytes());

			if (image.LogicalScreenDescriptor.GlobalColorTableFlag)
			{
				stream.WriteBytes(image.GlobalColorTable);
			}

			foreach (var applicationExtension in image.ApplictionExtensions)
			{
				stream.WriteBytes(applicationExtension.ToBytes());
			}

			foreach (var commentExtension in image.CommentExtensions)
			{
				stream.WriteBytes(commentExtension.ToBytes());
			}

			WriteFrames(image.Frames, stream);
		}
		public static Image Decode(Stream stream)
		{
			var result = new Image
				{
					Header = stream.ReadString(6),
					LogicalScreenDescriptor = LogicalScreenDescriptor.Read(stream)
				};

			if (result.LogicalScreenDescriptor.GlobalColorTableFlag)
			{
				result.GlobalColorTable = stream.ReadBytes(result.LogicalScreenDescriptor.GlobalColorTableSize * 3);
			}

			GraphicControlExtension graphicControlExtension = null;

			var componentType = stream.ReadByte();
			while (componentType != 0)
			{
				if (componentType == ImageDescriptor.ImageSeparator)
				{
					var imageFrame = ReadImageFrame(stream, result.GlobalColorTable, graphicControlExtension);
					result.Frames.Add(imageFrame);
				}
				else if (componentType == Const.ExtensionIntroducer)
				{
					var extensionType = stream.ReadByte();
					switch (extensionType)
					{
						case GraphicControlExtension.GraphicControlLabel:
							{
								graphicControlExtension = GraphicControlExtension.Read(stream);
								break;
							}
						case CommentExtension.CommentLabel:
							{
								var commentExtension = CommentExtension.Read(stream);
								result.CommentExtensions.Add(commentExtension);
								break;
							}
						case ApplicationExtension.ExtensionLabel:
							{
								var applicationExtension = ApplicationExtension.Read(stream);
								result.ApplictionExtensions.Add(applicationExtension);
								break;
							}
						case PlainTextExtension.PlainTextLabel:
							{
								var plainTextExtension = PlainTextExtension.Read(stream);
								result.PlainTextEntensions.Add(plainTextExtension);
								break;
							}
					}
				}
				else if (componentType == Const.EndIntroducer)
				{
					break;
				}

				componentType = stream.ReadByte();
			}

			return result;
		}
		private static void ProcessDisposalMethod(Image image)
		{
			Bitmap lastBitmap = null;
			var lastDisposal = 0;
			var index = 0;

			foreach (var frame in image.Frames)
			{
				var offsetX = frame.ImageDescriptor.ImageLeftPosition;
				var offsetY = frame.ImageDescriptor.ImageTopPosition;
				var frameWidth = frame.ImageDescriptor.ImageWidth;
				var frameHeight = frame.ImageDescriptor.ImageHeight;

				if (frame.Bitmap.Width != image.Width || frame.Bitmap.Height != image.Height)
				{
					frame.ImageDescriptor.ImageLeftPosition = 0;
					frame.ImageDescriptor.ImageTopPosition = 0;
					frame.ImageDescriptor.ImageWidth = image.Width;
					frame.ImageDescriptor.ImageHeight = image.Height;
				}

				var transparentColorIndex = -1;
				if (frame.GraphicControlExtension != null && frame.GraphicControlExtension.TransparentColorFlag)
				{
					transparentColorIndex = frame.GraphicControlExtension.TransparentColorIndex;
				}

				if (frameWidth != image.Width || frameHeight != image.Height || index != 0)
				{
					var bgColor = Convert.ToInt32(image.GlobalColorIndexedTable[transparentColorIndex]);
					var color = Color.FromArgb(bgColor);

					var bitmap = new Bitmap(image.Width, image.Height);
					using (var graphics = Graphics.FromImage(bitmap))
					{
						if (lastBitmap != null)
						{
							graphics.DrawImageUnscaled(lastBitmap, new Point(0, 0));
						}

						if (frame.GraphicControlExtension != null && frame.GraphicControlExtension.DisposalMethod == 1)
						{
							graphics.DrawRectangle(new Pen(new SolidBrush(color)), new Rectangle(offsetX, offsetY, frameWidth, frameHeight));
						}

						if (frame.GraphicControlExtension != null && frame.GraphicControlExtension.DisposalMethod == 2 && lastDisposal != 1)
						{
							graphics.Clear(color);
						}

						graphics.DrawImageUnscaled(frame.Bitmap, new Point(offsetX, offsetY));
					}

					frame.Bitmap.Dispose();
					frame.Bitmap = bitmap;
				}

				lastBitmap = frame.Bitmap;
				DefaultQuantizer.Quantize(frame.Bitmap, frame.GetPalette());

				if (frame.GraphicControlExtension != null)
				{
					lastDisposal = frame.GraphicControlExtension.DisposalMethod;
				}

				index++;
			}
		}