예제 #1
0
        public static Type Extract(BinaryReader Reader, out Extension Extension)
        {
            Type type = (Type)Reader.ReadByte();

            switch (type)
            {
            case Type.PlainText:        Extension = new ExtensionGeneric(Reader);         break;     //todo

            case Type.GraphicsControl:  Extension = new ExtensionGraphicsControl(Reader); break;

            case Type.Comment:          Extension = new ExtensionGeneric(Reader);         break;     //todo

            case Type.Application:      Extension = ExtensionApplication.Extract(Reader); break;

            default:                    Extension = new ExtensionGeneric(Reader);         break;
            }
            return(type);
        }
예제 #2
0
    /// <summary>
    /// Reads this Gif from a Stream
    /// </summary>
    /// <param name="Stream"></param>
    public void Read(Stream Stream)
    {
        BinaryReader reader = new BinaryReader(
            Stream, Encoding.ASCII, true);

        //////////////////////////////////////////////
        // HEADER
        //////////////////////////////////////////////
        byte[] buffer = new byte[3];

        // signature
        reader.Read(buffer, 0, 3);

        if (!buffer.SequenceEqual(Constants.SIGNATURE))
        {
            throw new Exception("Not a GIF file");
        }

        // version
        reader.Read(buffer, 0, 3);

        // check version
        if (!buffer.SequenceEqual(Constants.VERSION_89A) &&
            !buffer.SequenceEqual(Constants.VERSION_87A))
        {
            throw new Exception("Unsupported Version");
        }

        //////////////////////////////////////////////
        // LOGICAL SCREEN DESCRIPTOR DATA
        //////////////////////////////////////////////

        // width & height
        CanvasWidth  = reader.ReadUInt16();
        CanvasHeight = reader.ReadUInt16();

        // other data
        Packed.Value         = reader.ReadByte();
        BackgroundColorIndex = reader.ReadByte();
        PixelAspectRatio     = reader.ReadByte();

        //////////////////////////////////////////////
        // GLOBAL COLOR TABLE (OPTIONAL)
        //////////////////////////////////////////////
        GlobalColorTable = (Packed.IsGlobalColorTable) ?
                           reader.ReadBytes((int)Packed.ByteSizeOfColorTable) :
                           new byte[0];

        //////////////////////////////////////////////
        // DYNAMIC CHUNKS (OPTIONAL, EXCEPT ONE FRAME)
        //////////////////////////////////////////////
        ExtensionGraphicsControl lastGraphicsControl = null;

        while (true)
        {
            byte introducer = reader.ReadByte();

            // EXTENSION
            if (introducer == (byte)Introducer.Extension)
            {
                // try parse it
                Extension      extension;
                Extension.Type type = Extension.Extract(reader, out extension);

                // GraphicsControl
                if (type == Extension.Type.GraphicsControl)
                {
                    // save it for next frame
                    if (lastGraphicsControl == null)
                    {
                        lastGraphicsControl = (ExtensionGraphicsControl)extension;
                    }

                    // not good, we got another graphicscontrol extension
                    // without having read a frame since then...
                    else
                    {
                        // discard previous one, save this one
                        lastGraphicsControl = (ExtensionGraphicsControl)extension;
                    }
                }

                // Application
                else if (type == Extension.Type.Application)
                {
                    ApplicationExtension = (ExtensionApplication)extension;
                }

                // Generic
                else
                {
                    Extensions.Add(extension);
                }
            }

            // IMAGEDESCRIPTOR
            else if (introducer == (byte)Introducer.ImageDescriptor)
            {
                // parse frame data
                Frame frame = new Frame(reader);

                // attach the last GraphicsControl extension that was
                // not used yet and last read before this frame
                if (lastGraphicsControl != null)
                {
                    frame.GraphicsControl = lastGraphicsControl;
                    lastGraphicsControl   = null;
                }

                // store frame
                Frames.Add(frame);
            }

            // TRAILER (PARSING SUCCESSFUL)
            else if (introducer == (byte)Introducer.Trailer)
            {
                break;
            }

            // UNKNOWN
            else
            {
                throw new Exception("Unknown Dynamic Chunk Introducer");
            }
        }

        reader.Dispose();
    }
예제 #3
0
        public Frame(byte[] Pixels, int Width, int Height, uint[] Palette, uint ColorCount, LZWEncoder Encoder, ushort Delay, int TransparentColorIndex = -1)
        {
            if (Pixels == null)
            {
                throw new ArgumentException("Pixels can't be null.");
            }

            if (Width <= 0 || Height <= 0)
            {
                throw new ArgumentException("Width and Height must be greater 0.");
            }

            if (Palette == null || Palette.Length > 256)
            {
                throw new ArgumentException("Palette null or more than 256 entries.");
            }

            if (ColorCount > Palette.Length)
            {
                throw new ArgumentException("ColorCount bigger than Palette size.");
            }

            if (Encoder == null)
            {
                throw new ArgumentException("Encoder can't be null.");
            }

            // save provided dimension
            this.Width  = (ushort)Width;
            this.Height = (ushort)Height;

            // encode pixels using argument encoder instance
            Encoder.Encode(Pixels, Chunks, Width, Height);
            MinLZWCodeSize = 8;

            // determine size of colortable to use
            // get next bigger power of 2 value of used colorcount
            uint palSize2 = NextPowerOf2(ColorCount);

            // use and create local color table with determined size
            Packed.IsLocalColorTable     = true;
            Packed.SizeOfLocalColorTable = (uint)Math.Max((int)Math.Log(palSize2, 2.0) - 1, 0);
            ColorTable = new byte[palSize2 * 3];

            // fill color table
            int i = 0;

            for (uint j = 0; j < ColorCount; j++)
            {
                uint c = Palette[j];
                ColorTable[i] = (byte)((c & 0x00FF0000) >> 16); i++;
                ColorTable[i] = (byte)((c & 0x0000FF00) >> 8); i++;
                ColorTable[i] = (byte)(c & 0x000000FF); i++;
            }

            // set graphics control extension
            GraphicsControl                       = new ExtensionGraphicsControl();
            GraphicsControl.DelayTime             = Delay;
            GraphicsControl.Packed.IsUserInput    = false;
            GraphicsControl.Packed.DisposalMethod =
                ExtensionGraphicsControl.Flags.DisposalMethods.RestoreToBackground;

            // possibly set transparent color index and enable transparency
            if (TransparentColorIndex > -1 && TransparentColorIndex < 256)
            {
                GraphicsControl.Packed.IsTransparentColor = true;
                GraphicsControl.TransparentColorIndex     = (byte)TransparentColorIndex;
            }
        }