示例#1
0
        // Draw the source parallelogram of an image into the parallelogram
        // defined by dest. Point[] has 3 Points, Top-Left, Top-Right and Bottom-Left.
        // The remaining point is inferred.
        public virtual void DrawImage(IToolkitImage image, Point[] src, Point[] dest)
        {
            int originX = dest[0].X;
            int originY = dest[0].Y;

            for (int i = 1; i < 3; i++)
            {
                if (originX > dest[i].X)
                {
                    originX = dest[i].X;
                }
                if (originY > dest[i].Y)
                {
                    originY = dest[i].Y;
                }
            }

            DotGNU.Images.Image gnuImage = (image as ToolkitImageBase).image;
            // Currently we only draw the first frame.
            Frame frame = gnuImage.GetFrame(0);

            frame = frame.AdjustImage(src[0].X, src[0].Y, src[1].X, src[1].Y,
                                      src[2].X, src[2].Y, dest[0].X - originX, dest[0].Y - originY,
                                      dest[1].X - originX, dest[1].Y - originY, dest[2].X - originX,
                                      dest[2].Y - originY);
            // Setup the new image and draw it.
            using (DotGNU.Images.Image newGnuImage = new DotGNU.Images.Image(gnuImage.Width,
                                                                             gnuImage.Height, gnuImage.PixelFormat))
            {
                newGnuImage.AddFrame(frame);
                IToolkitImage newImage = Toolkit.CreateImage(newGnuImage, 0);
                DrawImage(newImage, originX, originY);
            }
        }
示例#2
0
文件: Image.cs 项目: ForNeVeR/pnet
        // This is an internal member and should not be used.
        // Returns a bitmap which is the resized (to newWidth and newHeight) of the first frame.
        public Image Resize(int newWidth, int newHeight)
        {
            Frame frame    = dgImage.GetFrame(0);
            Frame newFrame = frame.AdjustImage(0, 0, width, 0, 0, height, 0, 0, newWidth, 0, 0, newHeight);

            DotGNU.Images.Image newImage = new DotGNU.Images.Image(newWidth, newHeight, newFrame.PixelFormat);
            newImage.AddFrame(newFrame);
            return(new Bitmap(newImage));
        }
示例#3
0
        public Image Reformat(PixelFormat newFormat)
        {
            Image newImage = new Image(this, newFormat);

            for (int i = 0; i < frames.Length; i++)
            {
                newImage.AddFrame(frames[i].Reformat(newFormat));
            }
            return(newImage);
        }
示例#4
0
	public Image Reformat(PixelFormat newFormat)
			{
				Image newImage = new Image(this, newFormat);
				for (int i = 0; i < frames.Length; i++)
					newImage.AddFrame(frames[i].Reformat(newFormat));
				return newImage;
			}
	// Create a device independant bitmap from a frame. Optionally set all bits that are masked to black.
	// This is required for icons.
	private IntPtr HandleFromBitmap(Frame frame, bool andMask)
	{
		// By default we use the data straight from the frame.
		byte[] data = frame.Data;
		if (andMask)
		{
			//TODO: this could be slow.
			// Create a new image that we will copy the pixels to, leaving the masked pixels black.
			DotGNU.Images.Image newImage  = new DotGNU.Images.Image(frame.Width, frame.Height, frame.PixelFormat);
			Frame newFrame = newImage.AddFrame();
			data = new byte[data.Length];
			for (int y = 0; y < frame.Height; y++)
			{
				for (int x = 0; x < frame.Width; x++)
				{
					if (frame.GetMask(x, y) != 0)
						newFrame.SetPixel(x, y, frame.GetPixel(x, y));
				}
			}
			data = newFrame.Data;
		}

		// Create BITMAPINFO structure.
		int bitmapInfoSize = 40;
		int bitCount = frame.BitsPerPixel;
		// Do we have a palette?
		if(bitCount <= 8)
			bitmapInfoSize += 1 << bitCount * 4;
		byte[] bitmapInfo = new byte[bitmapInfoSize];

		// Build and write the BITMAPINFOHEADER structure.
		WriteInt32(bitmapInfo, 0, 40);// biSize
		WriteInt32(bitmapInfo, 4, frame.Width);
		WriteInt32(bitmapInfo, 8, -frame.Height);// upside down so make the height negative.
		WriteUInt16(bitmapInfo, 12, 1);// biPlanes
		WriteUInt16(bitmapInfo, 14, bitCount);
		WriteInt32(bitmapInfo, 16, 0);// biCompression
		WriteInt32(bitmapInfo, 20, 0);// size of image
		WriteInt32(bitmapInfo, 24, 3780);// biXPelsPerMeter
		WriteInt32(bitmapInfo, 28, 3780);// biYPelsPerMeter
		WriteInt32(bitmapInfo, 32, 0);	// biClrUsed
		WriteInt32(bitmapInfo, 36, 0);	// biClrImportant

		// Write the palette.
		if(bitCount <= 8)
		{
			int count = (1 << bitCount);
			for(int index = 0; index < count; ++index)
			{
				if(frame.Palette != null && index < frame.Palette.Length)
					WriteBGR(bitmapInfo, index * 4 + 40, frame.Palette[index]);
				else
				{
					// Short palette: pad with black pixels.
					WriteBGR(bitmapInfo, index * 4 + 40, 0);
				}
			}
		}

		return Win32.Api.CreateDIBitmap( Win32.Api.GetDC(hwnd), bitmapInfo, 4 /*CBM_INIT*/, data, bitmapInfo, 0 /*DIB_RGB_COLORS*/);
	}
示例#6
0
        // Load a BMP image from the specified stream.  The first 4 bytes
        // have already been read and discarded.
        public static void Load(Stream stream, Image image)
        {
            byte[] buffer = new byte [1024];
            int    width, height, planes, bitCount;
            int    compression;
            bool   quads;

            // Read the rest of the BITMAPFILEHEADER.
            if (stream.Read(buffer, 0, 10) != 10)
            {
                throw new FormatException();
            }
            int bfOffBits = Utils.ReadInt32(buffer, 6);

            // The current file offset at the end of the BITMAPFILEHEADER.
            int offset = 14;

            // Get the size of the BITMAPINFOHEADER structure that follows,
            // and then read it into the buffer.
            if (stream.Read(buffer, 0, 4) != 4)
            {
                throw new FormatException();
            }
            int size = Utils.ReadInt32(buffer, 0);

            if (size <= 4 || size > 1024)
            {
                throw new FormatException();
            }
            if (stream.Read(buffer, 4, size - 4) != (size - 4))
            {
                throw new FormatException();
            }
            offset += size;
            if (size >= 40)
            {
                // This is a BITMAPINFOHEADER structure (Windows bitmaps).
                width       = Utils.ReadInt32(buffer, 4);
                height      = Utils.ReadInt32(buffer, 8);
                planes      = Utils.ReadUInt16(buffer, 12);
                bitCount    = Utils.ReadUInt16(buffer, 14);
                compression = Utils.ReadInt32(buffer, 16);
                quads       = true;
            }
            else if (size == 12)
            {
                // This is a BITMAPCOREHEADER structure (OS/2 bitmaps).
                width       = Utils.ReadUInt16(buffer, 4);
                height      = Utils.ReadUInt16(buffer, 6);
                planes      = Utils.ReadUInt16(buffer, 8);
                bitCount    = Utils.ReadUInt16(buffer, 10);
                compression = 0;                                // BI_RGB
                quads       = false;
            }
            else
            {
                throw new FormatException();
            }

            // Perform a sanity check on the header values.
            if (width <= 0 || planes != 1)
            {
                throw new FormatException();
            }
            if (bitCount != 1 && bitCount != 4 && bitCount != 16 &&
                bitCount != 8 && bitCount != 24)
            {
                // TODO: non-traditional BMP formats.
                throw new FormatException();
            }
            if (compression != 0 && compression != 3 /*BI_BITFIELDS*/)
            {
                // TODO: RLE bitmaps
                throw new FormatException();
            }

            // Set the basic image properties.
            image.Width       = width;
            image.Height      = height < 0 ? -height : height;
            image.PixelFormat = Utils.BitCountToFormat(bitCount);
            image.LoadFormat  = Image.Bmp;

            // Do the unusual 16 bit formats.
            if (compression == 3)
            {
                if (stream.Read(buffer, 0, 3 * 4) != (3 * 4))
                {
                    throw new FormatException();
                }
                int redMask   = Utils.ReadInt32(buffer, 0);
                int greenMask = Utils.ReadInt32(buffer, 4);
                int blueMask  = Utils.ReadInt32(buffer, 8);

                if (blueMask == 0x001F && redMask == 0x7C00 && greenMask == 0x03E0)
                {
                    image.PixelFormat = PixelFormat.Format16bppRgb555;
                }
                else if (blueMask == 0x001F && redMask == 0xF800 && greenMask == 0x07E0)
                {
                    image.PixelFormat = PixelFormat.Format16bppRgb565;
                }
                else
                {
                    throw new FormatException();
                }
            }

            // Read the palette into memory and set it.
            if (bitCount <= 8)
            {
                int   colors = (1 << bitCount);
                int   index;
                int[] palette = new int [colors];
                if (quads)
                {
                    // The RGB values are specified as RGBQUAD's.
                    if (stream.Read(buffer, 0, colors * 4) != (colors * 4))
                    {
                        throw new FormatException();
                    }
                    offset += colors * 4;
                    for (index = 0; index < colors; ++index)
                    {
                        palette[index] = Utils.ReadBGR(buffer, index * 4);
                    }
                }
                else
                {
                    // The RGB values are specified as RGBTRIPLE's.
                    if (stream.Read(buffer, 0, colors * 3) != (colors * 3))
                    {
                        throw new FormatException();
                    }
                    offset += colors * 3;
                    for (index = 0; index < colors; ++index)
                    {
                        palette[index] = Utils.ReadBGR(buffer, index * 3);
                    }
                }
                image.Palette = palette;
            }

            // Seek to the start of the bitmap data.
            Utils.Seek(stream, offset, bfOffBits);

            // Add a frame to the image object.
            Frame frame = image.AddFrame();

            // Load the bitmap data from the stream into the frame.
            LoadBitmapData(stream, frame, false, height > 0);
        }
示例#7
0
        // Load a GIF image from the specified stream.  The first 4 bytes
        // have already been read and discarded.  We always load GIF's
        // as 8bpp because that makes it easier to handle decompression.
        // GIF's with lower bit depths will be expanded appropriately.
        public static void Load(Stream stream, Image image)
        {
            byte[] buffer = new byte [1024];
            int    logicalWidth, logicalHeight;
            int    flags, bitCount, numColors, tag;

            int[] palette;
            int   transparentPixel;
            int   imageWidth, imageHeight;
            Frame frame;

            // Read the rest of the GIF header and validate it.
            if (stream.Read(buffer, 0, 9) != 9)
            {
                throw new FormatException();
            }
            if ((buffer[0] != (byte)'7' && buffer[0] != (byte)'9') ||
                buffer[1] != (byte)'a')
            {
                throw new FormatException();
            }
            logicalWidth  = Utils.ReadUInt16(buffer, 2);
            logicalHeight = Utils.ReadUInt16(buffer, 4);
            flags         = buffer[6];
            // buffer[7] is the background index, which we ignore.
            // buffer[8] is the aspect ratio, which we ignore.
            if (logicalWidth == 0 || logicalHeight == 0)
            {
                throw new FormatException();
            }

            // Set the global image information.
            bitCount          = (flags & 0x07) + 1;
            numColors         = (1 << bitCount);
            image.Width       = logicalWidth;
            image.Height      = logicalHeight;
            image.PixelFormat = PixelFormat.Format8bppIndexed;
            image.LoadFormat  = Image.Gif;

            // Read the global color table, if present.
            if ((flags & 0x80) != 0)
            {
                image.Palette = ReadGifPalette(stream, buffer, numColors);
            }

            // Process the image and extension blocks in the image.
            transparentPixel = -1;
            while (stream.Read(buffer, 0, 1) == 1)
            {
                tag = buffer[0];
                if (tag == 0x2C)
                {
                    // Read the image descriptor.
                    if (stream.Read(buffer, 0, 9) != 9)
                    {
                        throw new FormatException();
                    }
                    imageWidth  = Utils.ReadUInt16(buffer, 4);
                    imageHeight = Utils.ReadUInt16(buffer, 6);
                    flags       = buffer[8];
                    if (imageWidth == 0 || imageHeight == 0)
                    {
                        throw new FormatException();
                    }
                    frame = image.AddFrame(imageWidth, imageHeight,
                                           image.PixelFormat);
                    frame.TransparentPixel = transparentPixel;
                    frame.OffsetX          = Utils.ReadUInt16(buffer, 0);
                    frame.OffsetY          = Utils.ReadUInt16(buffer, 2);
                    transparentPixel       = -1;

                    // Read the local color table, if any.
                    if ((flags & 0x80) != 0)
                    {
                        tag           = (1 << ((flags & 0x07) + 1));
                        frame.Palette = ReadGifPalette
                                            (stream, buffer, tag);
                    }

                    // Decompress the image into the frame.
                    Decompress(stream, buffer, frame, (flags & 0x40) != 0);
                }
                else if (tag == 0x21)
                {
                    // Process an extension.
                    if (stream.Read(buffer, 0, 1) != 1)
                    {
                        throw new FormatException();
                    }
                    if (buffer[0] == (byte)0xF9)
                    {
                        // Graphic control extension sub-block.
                        if (stream.Read(buffer, 0, 1) != 1)
                        {
                            throw new FormatException();
                        }
                        tag = buffer[0];
                        if (stream.Read(buffer, 0, tag) != tag)
                        {
                            throw new FormatException();
                        }
                        if (tag >= 4)
                        {
                            if ((buffer[0] & 0x01) != 0)
                            {
                                transparentPixel = buffer[3];
                            }
                            else
                            {
                                transparentPixel = -1;
                            }
                        }
                    }

                    // Skip the remaining extension sub-blocks.
                    SkipSubBlocks(stream, buffer);
                }
                else if (tag == 0x3B)
                {
                    // End of the GIF file.
                    break;
                }
                else
                {
                    // Invalid GIF file.
                    throw new FormatException();
                }
            }
        }
示例#8
0
	// This is an internal member and should not be used.
	// Returns a bitmap which is the resized (to newWidth and newHeight) of the first frame.
	public Image Resize(int newWidth, int newHeight)
			{
				Frame frame = dgImage.GetFrame(0);
				Frame newFrame = frame.AdjustImage(0, 0, width, 0, 0, height, 0, 0, newWidth, 0, 0, newHeight);
				DotGNU.Images.Image newImage = new DotGNU.Images.Image(newWidth, newHeight, newFrame.PixelFormat);
				newImage.AddFrame(newFrame);
				return new Bitmap(newImage);
			}
	// Create a gradient for the background of a title bar.
	private DotGNU.Images.Image CreateGradient
				(int width, int height, Color startColor, Color endColor)
			{
				if(startColor.Index != StandardColor.RGB)
				{
					startColor = screen.ToColor(startColor.Index);
				}
				if(endColor.Index != StandardColor.RGB)
				{
					endColor = screen.ToColor(endColor.Index);
				}
				int startR = startColor.Red;
				int startG = startColor.Green;
				int startB = startColor.Blue;
				int lenR = endColor.Red - startR;
				int lenG = endColor.Green - startG;
				int lenB = endColor.Blue - startB;
				DotGNU.Images.Image image = new DotGNU.Images.Image
					(width, height, PixelFormat.Format24bppRgb);
				Frame frame = image.AddFrame();
				int x, y, red, green, blue;
				for(y = 0; y < height; ++y)
				{
					for(x = 0; x < width; ++x)
					{
						red = startR + lenR * x / width;
						green = startG + lenG * x / width;
						blue = startB + lenB * x / width;
						frame.SetPixel(x, y, (red << 16) + (green << 8) + blue);
					}
				}
				return image;
			}
	// Draw the source parallelogram of an image into the parallelogram
	// defined by dest. Point[] has 3 Points, Top-Left, Top-Right and Bottom-Left.
	// The remaining point is inferred.
	public virtual void DrawImage(IToolkitImage image, Point[] src, Point[] dest)
			{
				int originX = dest[0].X;
				int originY = dest[0].Y;
				for (int i = 1; i < 3; i++)
				{
					if (originX > dest[i].X)
						originX = dest[i].X;
					if (originY > dest[i].Y)
						originY = dest[i].Y;
				}

				DotGNU.Images.Image gnuImage = (image as ToolkitImageBase).image;
				// Currently we only draw the first frame.
				Frame frame = gnuImage.GetFrame(0);
				frame = frame.AdjustImage(src[0].X, src[0].Y, src[1].X, src[1].Y,
					src[2].X, src[2].Y, dest[0].X - originX, dest[0].Y - originY,
					dest[1].X - originX, dest[1].Y - originY, dest[2].X - originX,
					dest[2].Y - originY);
				// Setup the new image and draw it.
				using (DotGNU.Images.Image newGnuImage = new DotGNU.Images.Image(gnuImage.Width,
					gnuImage.Height, gnuImage.PixelFormat))
				{
					newGnuImage.AddFrame(frame);
					IToolkitImage newImage = Toolkit.CreateImage(newGnuImage, 0);
					DrawImage( newImage, originX, originY);
				}
			}
示例#11
0
	// Load a PNG image from the specified stream.  The first 4 bytes
	// have already been read and discarded.
	public static void Load(Stream stream, Image image)
			{
				byte[] buffer = new byte [1024];
				int width = 0;
				int height = 0;
				int bitDepth = 0;
				int colorType = 0;
				int compressionMethod = 0;
				int filterMethod = 0;
				int interlaceMethod = 0;
				Frame frame = null;
				PixelFormat format = 0;
				int index;
				int significant = 0;
				ZlibDecompressor decompress = null;
				ScanlineReader scanlineReader;
				int pass, passWidth, passHeight;
				PassFunc passFunc;

				// Read the rest of the magic number and check it.
				if(stream.Read(buffer, 0, 4) != 4)
				{
					throw new FormatException("could not read magic number");
				}
				if(buffer[0] != (byte)13 ||
				   buffer[1] != (byte)10 ||
				   buffer[2] != (byte)26 ||
				   buffer[3] != (byte)10)
				{
					throw new FormatException("invalid magic number");
				}

				// Create a chunk reader for the stream.
				ChunkReader reader = new ChunkReader(stream, buffer);

				// Read all of the chunks from the stream.
				while(reader.Type != IEND)
				{
					// Process the critical chunk types.
					if(reader.Type == IHDR)
					{
						// We can only have one header per PNG image.
						if(image.NumFrames > 0)
						{
							throw new FormatException("multiple headers");
						}

						// Read the contents of the image header.
						if(reader.Read(buffer, 0, 13) != 13)
						{
							throw new FormatException("truncated header");
						}
						width = Utils.ReadInt32B(buffer, 0);
						height = Utils.ReadInt32B(buffer, 4);
						bitDepth = buffer[8];
						colorType = buffer[9];
						compressionMethod = buffer[10];
						filterMethod = buffer[11];
						interlaceMethod = buffer[12];

						// Sanity-check the values.
						if(width < 1 || height < 1)
						{
							throw new FormatException("invalid size");
						}
						if(colorType == 0)
						{
							if(bitDepth != 1 && bitDepth != 2 &&
							   bitDepth != 4 && bitDepth != 8 &&
							   bitDepth != 16)
							{
								throw new FormatException
									("invalid depth for color type 0");
							}
						}
						else if(colorType == 2 || colorType == 4 ||
								colorType == 6)
						{
							if(bitDepth != 8 && bitDepth != 16)
							{
								throw new FormatException
									("invalid depth for color type " +
									 colorType.ToString());
							}
						}
						else if(colorType == 3)
						{
							if(bitDepth != 1 && bitDepth != 2 &&
							   bitDepth != 4 && bitDepth != 8)
							{
								throw new FormatException
									("invalid depth for color type 3");
							}
						}
						else
						{
							throw new FormatException("invalid color type");
						}
						if(compressionMethod != 0)
						{
							throw new FormatException
								("invalid compression method");
						}
						if(filterMethod != 0)
						{
							throw new FormatException
								("invalid filter method");
						}
						if(interlaceMethod != 0 && interlaceMethod != 1)
						{
							throw new FormatException
								("invalid interlace method");
						}

						// Create the image frame with the requested values.
						if(colorType == 3)
						{
							format = PixelFormat.Format8bppIndexed;
						}
						else if((colorType & 4) != 0)
						{
							if(significant == 0x01050505 && bitDepth == 8)
							{
								format = PixelFormat.Format16bppArgb1555;
							}
							else if(bitDepth == 8)
							{
								format = PixelFormat.Format32bppArgb;
							}
							else
							{
								format = PixelFormat.Format64bppArgb;
							}
						}
						else if(colorType == 0 && bitDepth == 16)
						{
							format = PixelFormat.Format16bppGrayScale;
						}
						else
						{
							if(significant == 0x00050505 && bitDepth == 8)
							{
								format = PixelFormat.Format16bppRgb555;
							}
							else if(significant == 0x00050605 && bitDepth == 8)
							{
								format = PixelFormat.Format16bppRgb565;
							}
							else if(bitDepth == 8)
							{
								format = PixelFormat.Format24bppRgb;
							}
							else
							{
								format = PixelFormat.Format48bppRgb;
							}
						}
						image.Width = width;
						image.Height = height;
						image.PixelFormat = format;
						image.LoadFormat = Image.Png;
						frame = image.AddFrame(width, height, format);
					}
					else if(reader.Type == PLTE)
					{
						// We must have a frame at this point.
						if(frame == null)
						{
							throw new FormatException
								("palette specified before image header");
						}

						// The palette is only required for color type 3.
						// Other color types use it as a hint only.
						if(colorType == 3)
						{
							int[] palette = new int [256];
							frame.Palette = palette;
							Array.Clear(buffer, 0, buffer.Length);
							if(reader.Length > 768)
							{
								reader.Read(buffer, 0, 768);
							}
							else
							{
								reader.Read(buffer, 0, buffer.Length);
							}
							for(index = 0; index < 256; ++index)
							{
								palette[index] =
									Utils.ReadRGB(buffer, index * 3);
							}
						}
					}
					else if(reader.Type == tRNS)
					{
						// We must have a frame at this point.
						if(frame == null)
						{
							throw new FormatException
								("transparency specified before image header");
						}

						// We only support simple transparencies for
						// color type 3 at present.  The transparency
						// information is ignored for other color types.
						if(colorType == 3)
						{
							index = 0;
							while(index < 256 && reader.Length > 0)
							{
								if(reader.Read(buffer, 0, 1) != 1)
								{
									break;
								}
								if(buffer[0] < 0x80)
								{
									frame.TransparentPixel = index;
									break;
								}
								++index;
							}
						}
					}
					else if(reader.Type == sBIT)
					{
						// Read the number of significant bits so that
						// we can detect images that started off life
						// as 15-bit or 16-bit RGB.
						if(reader.Length == 3)
						{
							reader.Read(buffer, 0, 3);
							significant = Utils.ReadRGB(buffer, 0);
						}
						else if(reader.Length == 4)
						{
							reader.Read(buffer, 0, 4);
							significant = Utils.ReadRGB(buffer, 0) |
										  (buffer[3] << 24);
						}
					}
					else if(reader.Type == IDAT)
					{
						// We must have a frame at this point.
						if(frame == null)
						{
							throw new FormatException
								("image data specified before image header");
						}

						// There can be only one set of data chunks.
						if(decompress != null)
						{
							throw new FormatException
								("multiple image data blocks encountered");
						}

						// Create a zlib decompressor.
						decompress = new ZlibDecompressor(reader);

						// Get the pass processing function.
						passFunc = GetPassFunc(colorType, bitDepth, format);

						// Process the data in the image.
						if(interlaceMethod == 0)
						{
							// No interlacing.
							scanlineReader = new ScanlineReader
								(decompress, width, height,
								colorType, bitDepth);
							passFunc(frame, scanlineReader, width, height,
								     0, 0, 1, 1);
						}
						else
						{
							// Use Adam7 interlacing.
							for(pass = 0; pass < 7; ++pass)
							{
								// Calculate the width and height of the pass.
								// Please refer "PNG - The Definitive Guide"
								// for a totally misleading and incompatible
								// description of the following code - Gopal

								passWidth = width + 
											adam7Rules[(pass+1) * 4 + 2] - 1;
								passWidth /= adam7Rules[pass * 4 + 2];
								if(passWidth <= 0)
								{
									continue;
								}
								
								passHeight = height + 
											adam7Rules[(pass+1) * 4 + 3 ] - 1;
								passHeight /= adam7Rules[pass * 4 + 3];
								if(passHeight <= 0)
								{
									continue;
								}

								// Create a scanline reader for the pass.
								scanlineReader = new ScanlineReader
									(decompress, passWidth, passHeight,
									 colorType, bitDepth);

								// Process the Adam7 pass.
								passFunc(frame, scanlineReader,
										 passWidth, passHeight,
										 adam7Rules[pass * 4],
										 adam7Rules[pass * 4 + 1],
										 adam7Rules[pass * 4 + 2],
										 adam7Rules[pass * 4 + 3]);
							}
						}

						// Eat any remaining IDAT data blocks.
						decompress.EatRemaining();

						// Skip the "Reset", because we've already done it.
						continue;
					}

					// Reset the chunk reader and move on to the next chunk.
					reader.Reset(buffer);
				}

				// Skip the contents of the IEND chunk and check its CRC.
				reader.Skip(buffer);

				// If we don't have a frame or decompressor,
				// then the PNG stream was empty.
				if(frame == null || decompress == null)
				{
					throw new FormatException("PNG did not contain an image");
				}
			}
示例#12
0
	// Load a JPEG image from the specified stream.  The first 4 bytes
	// have already been read and discarded.
	public static void Load(Stream stream, Image image,
							byte[] prime, int primeLen)
			{
				// Determine if we actually have the JPEG library.
				if(!JpegLib.JpegLibraryPresent())
				{
					throw new FormatException("libjpeg is not available");
				}

				// Create the decompression object.
				JpegLib.jpeg_decompress_struct cinfo;
				cinfo = new JpegLib.jpeg_decompress_struct();
				cinfo.err = JpegLib.CreateErrorHandler();
				JpegLib.jpeg_create_decompress(ref cinfo);

				// Initialize the source manager.
				JpegLib.StreamToSourceManager
					(ref cinfo, stream, prime, primeLen);

				// Read the JPEG header.
				JpegLib.jpeg_read_header(ref cinfo, (Int)1);

				// Set the decompression parameters the way we want them.
				cinfo.out_color_space = JpegLib.J_COLOR_SPACE.JCS_RGB;

				// Start the decompression process.
				JpegLib.jpeg_start_decompress(ref cinfo);

				// Initialize the image to 24-bit RGB, to match the JPEG file.
				image.Width = (int)(cinfo.output_width);
				image.Height = (int)(cinfo.output_height);
				image.PixelFormat = PixelFormat.Format24bppRgb;
				if(prime[3] == 0xE1)
				{
					image.LoadFormat = Image.Exif;
				}
				else
				{
					image.LoadFormat = Image.Jpeg;
				}
				Frame frame = image.AddFrame();

				// Read the scanlines from the image.
				int posn, width, offset, stride, y, twidth;
				width = frame.Width;
				twidth = width * 3;
				stride = frame.Stride;
				byte[] data = frame.Data;
				IntPtr buf = Marshal.AllocHGlobal(width * 3);
				byte *pbuf = (byte *)buf;
				y = 0;
				while(((int)(cinfo.output_scanline)) <
							((int)(cinfo.output_height)))
				{
					JpegLib.jpeg_read_scanlines
						(ref cinfo, ref buf, (UInt)1);
					offset = (y++) * stride;
					for(posn = 0; posn < twidth; posn += 3)
					{
						// Convert the JPEG RGB data into BGR for the frame.
						data[offset]     = pbuf[posn + 2];
						data[offset + 1] = pbuf[posn + 1];
						data[offset + 2] = pbuf[posn];
						offset += 3;
					}
				}
				Marshal.FreeHGlobal(buf);

				// Finish the decompression process.
				JpegLib.jpeg_finish_decompress(ref cinfo);

				// Clean everything up.
				JpegLib.FreeSourceManager(ref cinfo);
				JpegLib.jpeg_destroy_decompress(ref cinfo);
				JpegLib.FreeErrorHandler(cinfo.err);
			}
示例#13
0
	// Load a BMP image from the specified stream.  The first 4 bytes
	// have already been read and discarded.
	public static void Load(Stream stream, Image image)
			{
				byte[] buffer = new byte [1024];
				int width, height, planes, bitCount;
				int compression;
				bool quads;

				// Read the rest of the BITMAPFILEHEADER.
				if(stream.Read(buffer, 0, 10) != 10)
				{
					throw new FormatException();
				}
				int bfOffBits = Utils.ReadInt32(buffer, 6);

				// The current file offset at the end of the BITMAPFILEHEADER.
				int offset = 14;

				// Get the size of the BITMAPINFOHEADER structure that follows,
				// and then read it into the buffer.
				if(stream.Read(buffer, 0, 4) != 4)
				{
					throw new FormatException();
				}
				int size = Utils.ReadInt32(buffer, 0);
				if(size <= 4 || size > 1024)
				{
					throw new FormatException();
				}
				if(stream.Read(buffer, 4, size - 4) != (size - 4))
				{
					throw new FormatException();
				}
				offset += size;
				if(size >= 40)
				{
					// This is a BITMAPINFOHEADER structure (Windows bitmaps).
					width = Utils.ReadInt32(buffer, 4);
					height = Utils.ReadInt32(buffer, 8);
					planes = Utils.ReadUInt16(buffer, 12);
					bitCount = Utils.ReadUInt16(buffer, 14);
					compression = Utils.ReadInt32(buffer, 16);
					quads = true;
				}
				else if(size == 12)
				{
					// This is a BITMAPCOREHEADER structure (OS/2 bitmaps).
					width = Utils.ReadUInt16(buffer, 4);
					height = Utils.ReadUInt16(buffer, 6);
					planes = Utils.ReadUInt16(buffer, 8);
					bitCount = Utils.ReadUInt16(buffer, 10);
					compression = 0;	// BI_RGB
					quads = false;
				}
				else
				{
					throw new FormatException();
				}

				// Perform a sanity check on the header values.
				if(width <= 0 || planes != 1)
				{
					throw new FormatException();
				}
				if(bitCount != 1 && bitCount != 4 &&  bitCount != 16 &&
				   bitCount != 8 && bitCount != 24)
				{
					// TODO: non-traditional BMP formats.
					throw new FormatException();
				}
				if(compression != 0 && compression != 3/*BI_BITFIELDS*/)
				{
					// TODO: RLE bitmaps
					throw new FormatException();
				}

				// Set the basic image properties.
				image.Width = width;
				image.Height = height < 0 ? -height : height;
				image.PixelFormat = Utils.BitCountToFormat(bitCount);
				image.LoadFormat = Image.Bmp;

				// Do the unusual 16 bit formats.
				if (compression == 3)
				{
					if(stream.Read(buffer, 0, 3 * 4) != (3 * 4))
					{
						throw new FormatException();
					}
					int redMask = Utils.ReadInt32(buffer, 0);
					int greenMask = Utils.ReadInt32(buffer, 4);
					int blueMask = Utils.ReadInt32(buffer, 8);

					if (blueMask == 0x001F && redMask == 0x7C00 && greenMask == 0x03E0)
						image.PixelFormat = PixelFormat.Format16bppRgb555;
					else if (blueMask == 0x001F && redMask == 0xF800 && greenMask == 0x07E0)
						image.PixelFormat = PixelFormat.Format16bppRgb565;
					else
						throw new FormatException();
				}

				// Read the palette into memory and set it.
				if(bitCount <= 8)
				{
					int colors = (1 << bitCount);
					int index;
					int[] palette = new int [colors];
					if(quads)
					{
						// The RGB values are specified as RGBQUAD's.
						if(stream.Read(buffer, 0, colors * 4) != (colors * 4))
						{
							throw new FormatException();
						}
						offset += colors * 4;
						for(index = 0; index < colors; ++index)
						{
							palette[index] = Utils.ReadBGR(buffer, index * 4);
						}
					}
					else
					{
						// The RGB values are specified as RGBTRIPLE's.
						if(stream.Read(buffer, 0, colors * 3) != (colors * 3))
						{
							throw new FormatException();
						}
						offset += colors * 3;
						for(index = 0; index < colors; ++index)
						{
							palette[index] = Utils.ReadBGR(buffer, index * 3);
						}
					}
					image.Palette = palette;
				}

				// Seek to the start of the bitmap data.
				Utils.Seek(stream, offset, bfOffBits);

				// Add a frame to the image object.
				Frame frame = image.AddFrame();

				// Load the bitmap data from the stream into the frame.
				LoadBitmapData(stream, frame, false, height > 0);

			}
示例#14
0
	// Load a GIF image from the specified stream.  The first 4 bytes
	// have already been read and discarded.  We always load GIF's
	// as 8bpp because that makes it easier to handle decompression.
	// GIF's with lower bit depths will be expanded appropriately.
	public static void Load(Stream stream, Image image)
			{
				byte[] buffer = new byte [1024];
				int logicalWidth, logicalHeight;
				int flags, bitCount, numColors, tag;
				int[] palette;
				int transparentPixel;
				int imageWidth, imageHeight;
				Frame frame;

				// Read the rest of the GIF header and validate it.
				if(stream.Read(buffer, 0, 9) != 9)
				{
					throw new FormatException();
				}
				if((buffer[0] != (byte)'7' && buffer[0] != (byte)'9') ||
				   buffer[1] != (byte)'a')
				{
					throw new FormatException();
				}
				logicalWidth = Utils.ReadUInt16(buffer, 2);
				logicalHeight = Utils.ReadUInt16(buffer, 4);
				flags = buffer[6];
				// buffer[7] is the background index, which we ignore.
				// buffer[8] is the aspect ratio, which we ignore.
				if(logicalWidth == 0 || logicalHeight == 0)
				{
					throw new FormatException();
				}

				// Set the global image information.
				bitCount = (flags & 0x07) + 1;
				numColors = (1 << bitCount);
				image.Width = logicalWidth;
				image.Height = logicalHeight;
				image.PixelFormat = PixelFormat.Format8bppIndexed;
				image.LoadFormat = Image.Gif;

				// Read the global color table, if present.
				if((flags & 0x80) != 0)
				{
					image.Palette = ReadGifPalette(stream, buffer, numColors);
				}

				// Process the image and extension blocks in the image.
				transparentPixel = -1;
				while(stream.Read(buffer, 0, 1) == 1)
				{
					tag = buffer[0];
					if(tag == 0x2C)
					{
						// Read the image descriptor.
						if(stream.Read(buffer, 0, 9) != 9)
						{
							throw new FormatException();
						}
						imageWidth = Utils.ReadUInt16(buffer, 4);
						imageHeight = Utils.ReadUInt16(buffer, 6);
						flags = buffer[8];
						if(imageWidth == 0 || imageHeight == 0)
						{
							throw new FormatException();
						}
						frame = image.AddFrame(imageWidth, imageHeight,
											   image.PixelFormat);
						frame.TransparentPixel = transparentPixel;
						frame.OffsetX = Utils.ReadUInt16(buffer, 0);
						frame.OffsetY = Utils.ReadUInt16(buffer, 2);
						transparentPixel = -1;

						// Read the local color table, if any.
						if((flags & 0x80) != 0)
						{
							tag = (1 << ((flags & 0x07) + 1));
							frame.Palette = ReadGifPalette
								(stream, buffer, tag);
						}

						// Decompress the image into the frame.
						Decompress(stream, buffer, frame, (flags & 0x40) != 0);
					}
					else if(tag == 0x21)
					{
						// Process an extension.
						if(stream.Read(buffer, 0, 1) != 1)
						{
							throw new FormatException();
						}
						if(buffer[0] == (byte)0xF9)
						{
							// Graphic control extension sub-block.
							if(stream.Read(buffer, 0, 1) != 1)
							{
								throw new FormatException();
							}
							tag = buffer[0];
							if(stream.Read(buffer, 0, tag) != tag)
							{
								throw new FormatException();
							}
							if(tag >= 4)
							{
								if((buffer[0] & 0x01) != 0)
								{
									transparentPixel = buffer[3];
								}
								else
								{
									transparentPixel = -1;
								}
							}
						}

						// Skip the remaining extension sub-blocks.
						SkipSubBlocks(stream, buffer);
					}
					else if(tag == 0x3B)
					{
						// End of the GIF file.
						break;
					}
					else
					{
						// Invalid GIF file.
						throw new FormatException();
					}
				}
			}
示例#15
0
	// Load a Windows icon image from the specified stream.  The first
	// 4 bytes have already been read and discarded.  If "hotspots" is
	// "true", then the image is actually a Windows cursor with hotspots.
	public static void Load(Stream stream, Image image, bool hotspots)
			{
				byte[] buffer = new byte [1024];
				int offset = 4;
				int numImages, index;
				int width, height, bpp;
				PixelFormat format;
				Frame frame;
				int[] palette;
				int paletteCount;
				int paletteIndex;

				// Read the number of images in the file.
				if(stream.Read(buffer, 0, 2) != 2)
				{
					throw new FormatException();
				}
				numImages = Utils.ReadUInt16(buffer, 0);
				offset += 2;

				// Read the resource directory.
				int[] offsetList = new int [numImages];
				int[] hotspotX = null;
				int[] hotspotY = null;
				if(hotspots)
				{
					hotspotX = new int[numImages];
					hotspotY = new int[numImages];
				}
				for(index = 0; index < numImages; ++index)
				{
					if(stream.Read(buffer, 0, 16) != 16)
					{
						throw new FormatException();
					}
					offset += 16;
					if(hotspots)
					{
						hotspotX[index] = Utils.ReadUInt16(buffer, 4);
						hotspotY[index] = Utils.ReadUInt16(buffer, 6);
					}
					offsetList[index] = Utils.ReadInt32(buffer, 12);
				}

				// Read the contents of the images in the stream.
				for(index = 0; index < numImages; ++index)
				{
					
					// Seek to the start of the image.
					Utils.Seek(stream, offset, offsetList[index]);
					offset = offsetList[index];

					// Read the DIB header.
					if(stream.Read(buffer, 0, 40) != 40)
					{
						throw new FormatException();
					}
					offset += 40;
					width = Utils.ReadUInt16(buffer, 4);
					// The DIB height is the mask and the bitmap.
					height = Utils.ReadUInt16(buffer, 8) / 2;
					bpp = Utils.ReadUInt16(buffer, 14);
					if (bpp == 1)
						format = PixelFormat.Format1bppIndexed;
					else if (bpp == 4)
						format = PixelFormat.Format4bppIndexed;
					else if (bpp == 8)
						format = PixelFormat.Format8bppIndexed;
					else if (bpp == 24)
						format = PixelFormat.Format24bppRgb;
					else if (bpp == 32)
						format = PixelFormat.Format32bppArgb;
					else
						throw new FormatException();

					// Create a new frame for this icon.
					frame = new Frame(image, width, height, format);
					image.AddFrame(frame);
					if(hotspots)
					{
						frame.HotspotX = hotspotX[index];
						frame.HotspotY = hotspotY[index];
					}

					// Copy some of the format information up to the image.
					if(frame.Width > image.Width)
					{
						image.Width = frame.Width;
					}
					if(frame.Height > image.Height)
					{
						image.Height = frame.Height;
					}
					if(image.NumFrames == 1)
					{
						image.PixelFormat = format;
					}

					// If indexed, get the palette.
					if((frame.pixelFormat & PixelFormat.Indexed) != 0)
					{
						paletteCount =
							(1 << Utils.FormatToBitCount(frame.pixelFormat));
						if(stream.Read(buffer, 0, paletteCount * 4)
								!= paletteCount * 4)
						{
							throw new FormatException();
						}
						offset += paletteCount * 4;
						palette = new int [paletteCount];
						for(paletteIndex = 0; paletteIndex < paletteCount;
							++paletteIndex)
						{
							palette[paletteIndex] = Utils.ReadBGR
								(buffer, paletteIndex * 4);
						}
						frame.Palette = palette;
					}

					// Read the main part of the icon or cursor.
					BmpReader.LoadBitmapData(stream, frame, false, true);
					offset += frame.Height * frame.Stride;

					// Read the mask.
					BmpReader.LoadBitmapData(stream, frame, true, true);
					offset += frame.Height * frame.MaskStride;

					// Invert the mask, because we want 1 to mean "active".
					InvertMask(frame);
				}

				// Set the appropriate load format.
				if(hotspots)
				{
					image.LoadFormat = Image.Cursor;
				}
				else
				{
					image.LoadFormat = Image.Icon;
				}
			}