Пример #1
0
 public PortableImage Reformat(PixelFormat newFormat)
 {
     PortableImage newImage = new PortableImage(this, newFormat);
     for (int i = 0; i < frames.Length; i++)
         newImage.AddFrame(frames[i].Reformat(newFormat));
     return newImage;
 }
Пример #2
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, PortableImage 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 = PortableImage.Cursor;
            }
            else
            {
                image.LoadFormat = PortableImage.Icon;
            }
        }
Пример #3
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, PortableImage 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  = PortableImage.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();
                }
            }
        }
Пример #4
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, PortableImage 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  = PortableImage.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);
        }