private byte[] ReadFrameLocalColorTable(GifImageDescriptor imageDescriptor)
 {
     byte[] localColorTable = null;
     if (imageDescriptor.LocalColorTableFlag)
     {
         localColorTable = new byte[imageDescriptor.LocalColorTableSize * 3];
         currentStream.Read(localColorTable, 0, localColorTable.Length);
     }
     return(localColorTable);
 }
 public void TestPackedValue()
 {
     Assert.Equal(128, GifImageDescriptor.GetPackedValue(true, false, false, 1));  // localColorTable
     Assert.Equal(64, GifImageDescriptor.GetPackedValue(false, true, false, 1));   // interfaceFlag
     Assert.Equal(32, GifImageDescriptor.GetPackedValue(false, false, true, 1));   // sortFlag
     Assert.Equal(224, GifImageDescriptor.GetPackedValue(true, true, true, 1));    // all
     Assert.Equal(7, GifImageDescriptor.GetPackedValue(false, false, false, 8));
     Assert.Equal(227, GifImageDescriptor.GetPackedValue(true, true, true, 4));
     Assert.Equal(231, GifImageDescriptor.GetPackedValue(true, true, true, 8));
 }
Exemple #3
0
    private void Read(Stream stream, IEnumerable <GifExtension> controlExtensions, bool metadataOnly)
    {
        //Note: at this point, the Image Separator (0x2C) has already been read
        Descriptor = GifImageDescriptor.ReadImageDescriptor(stream);

        if (Descriptor.HasLocalColorTable)
        {
            LocalColorTable = GifHelpers.ReadColorTable(stream, Descriptor.LocalColorTableSize);
        }

        ImageData  = GifImageData.ReadImageData(stream, metadataOnly);
        Extensions = controlExtensions.ToList().AsReadOnly();
    }
Exemple #4
0
        private async Task RenderFrameAsync(int frameIndex, CancellationToken cancellationToken)
        {
            if (frameIndex < 0)
            {
                return;
            }
            GifFrame           frame = this._metadata.Frames[frameIndex];
            GifImageDescriptor desc  = frame.Descriptor;

            using (Stream indexStreamAsync = await this.GetIndexStreamAsync(frame, cancellationToken))
            {
                if (frameIndex < this._previousFrameIndex)
                {
                    this.ClearArea((IGifRect)this._metadata.Header.LogicalScreenDescriptor);
                }
                else
                {
                    this.DisposePreviousFrame(frame);
                }
                int    length               = 4 * desc.Width;
                byte[] buffer               = new byte[desc.Width];
                byte[] numArray             = new byte[length];
                Animator.GifPalette palette = this._palettes[frameIndex];
                int num1 = palette.TransparencyIndex ?? -1;
                foreach (int num2 in frame.Descriptor.Interlace ? Animator.InterlacedRows(frame.Descriptor.Height) : Animator.NormalRows(frame.Descriptor.Height))
                {
                    if (indexStreamAsync.Read(buffer, 0, desc.Width) != desc.Width)
                    {
                        throw new EndOfStreamException();
                    }
                    int offset = (desc.Top + num2) * this._stride + desc.Left * 4;
                    if (num1 >= 0)
                    {
                        Animator.CopyFromBitmap(numArray, this._bitmap, offset, length);
                    }
                    for (int index = 0; index < desc.Width; ++index)
                    {
                        byte num3       = buffer[index];
                        int  startIndex = 4 * index;
                        if ((int)num3 != num1)
                        {
                            Animator.WriteColor(numArray, palette[(int)num3], startIndex);
                        }
                    }
                    Animator.CopyToBitmap(numArray, this._bitmap, offset, length);
                }
                this._bitmap.Invalidate();
                this._previousFrame      = frame;
                this._previousFrameIndex = frameIndex;
            }
        }
Exemple #5
0
    static void CalculColors(GifData gifData)
    {
        Color[] previousFrame    = new Color[gifData.canvasWidth * gifData.canvasHeight];
        Color[] currentFrame     = new Color[gifData.canvasWidth * gifData.canvasHeight];
        Color[] transparentFrame = new Color[gifData.canvasWidth * gifData.canvasHeight];

        // Create sprites
        for (int i = 0; i < gifData.graphicsControlExtensions.Count; i++)
        {
            GifGraphicsControlExtension graphicsControlExt = gifData.graphicsControlExtensions[i];
            GifImageDescriptor          imageDescriptor    = graphicsControlExt.imageDescriptor;
            GifImageData imageData      = imageDescriptor.imageData;
            int          top            = imageDescriptor.imageTop;
            int          left           = imageDescriptor.imageLeft;
            int          disposalMethod = graphicsControlExt.disposalMethod;

            int     transparencyIndex = graphicsControlExt.transparentColorFlag ? graphicsControlExt.transparentColorIndex : -1;
            Color[] colorTabel        = imageData.imageDescriptor.localColorTableFlag ? imageData.imageDescriptor.localColorTable : gifData.globalColorTable;

            for (int j = 0; j < imageDescriptor.imageWidth; j++)
            {
                for (int k = 0; k < imageDescriptor.imageHeight; k++)
                {
                    int x           = left + j;
                    int y           = (gifData.canvasHeight - 1) - (top + k);
                    int colorIndex  = imageData.colorIndices[j + k * imageDescriptor.imageWidth];
                    int pixelOffset = x + y * gifData.canvasWidth;

                    if (colorIndex != transparencyIndex)
                    {
                        currentFrame[pixelOffset] = colorTabel[colorIndex];//imageData.getColor(colorIndex);
                    }
                }
            }
            // Set texture pixels and create sprite
            // Store current frame as previous before continuing, and reset current frame
            currentFrame.CopyTo(previousFrame, 0);
            if (disposalMethod == 0 || disposalMethod == 2)
            {
                currentFrame     = new Color[currentFrame.Length];
                imageData.colors = currentFrame;
            }
            else
            {
                imageData.colors = new Color[currentFrame.Length];
                currentFrame.CopyTo(imageData.colors, 0);
            }
        }
    }
        private void ReadFrame()
        {
            GifImageDescriptor imageDescriptor = ReadImageDescriptor();

            byte[] localColorTable = ReadFrameLocalColorTable(imageDescriptor);
            byte[] indices         = ReadFrameIndices(imageDescriptor);

            // Determine the color table for this frame. If there is a local one, use it
            // otherwise use the global color table.
            byte[] colorTable = localColorTable ?? globalColorTable;
            ReadFrameColors(indices, colorTable, imageDescriptor);

            // Skip any remaining blocks
            Skip(0);
        }
        private GifImageDescriptor ReadImageDescriptor()
        {
            byte[] buffer = new byte[9];
            currentStream.Read(buffer, 0, buffer.Length);
            byte packed = buffer[8];
            GifImageDescriptor imageDescriptor = new GifImageDescriptor {
                Left   = BitConverter.ToInt16(buffer, 0),
                Top    = BitConverter.ToInt16(buffer, 2),
                Width  = BitConverter.ToInt16(buffer, 4),
                Height = BitConverter.ToInt16(buffer, 6),
                LocalColorTableFlag = ((packed & 0x80) >> 7) == 1,
                LocalColorTableSize = 2 << (packed & 0x07),
                    InterlaceFlag   = ((packed & 0x40) >> 6) == 1
            };

            return(imageDescriptor);
        }
Exemple #8
0
        /// <summary>
        /// <p>Sets new stream to read gif data from</p>
        /// <br/>
        /// <p>GifStream is reusable, you can change stream and read new gif from it.
        /// That way you reuse allocations that you've made, and keep your memory usage to minimum</p>
        /// <br/>
        /// <p>Stream will be reset to its initial state</p>
        /// </summary>
        /// <param name="stream">new stream with gif data</param>
        /// <param name="disposePrevious">Dispose previous stream</param>
        public void SetStream(Stream stream, bool disposePrevious = false)
        {
            if (disposePrevious)
            {
                if (currentStream != null)
                {
                    currentStream.Dispose();
                }
            }

            header          = new GifHeader();
            imageDescriptor = new GifImageDescriptor();
            graphicControl  = new GifGraphicControl();

            currentStream = stream;
            CurrentToken  = Token.Header;
            blockReader.SetStream(stream);
        }
Exemple #9
0
            private GifImageDescriptor ReadImageDescriptor()
            {
                byte[] buffer = new byte[9];

                _stream.Read(buffer, 0, buffer.Length);

                byte packed = buffer[8];

                GifImageDescriptor imageDescriptor = new GifImageDescriptor();

                imageDescriptor.Left   = BitConverter.ToInt16(buffer, 0);
                imageDescriptor.Top    = BitConverter.ToInt16(buffer, 2);
                imageDescriptor.Width  = BitConverter.ToInt16(buffer, 4);
                imageDescriptor.Height = BitConverter.ToInt16(buffer, 6);
                imageDescriptor.LocalColorTableFlag = ((packed & 0x80) >> 7) == 1;
                imageDescriptor.LocalColorTableSize = 2 << (packed & 0x07);
                imageDescriptor.InterlaceFlag       = ((packed & 0x40) >> 6) == 1;

                return(imageDescriptor);
            }
Exemple #10
0
            private void ReadFrame()
            {
                GifImageDescriptor imageDescriptor = ReadImageDescriptor();

                byte[] localColorTable = ReadFrameLocalColorTable(imageDescriptor);

                byte[] indices = ReadFrameIndices(imageDescriptor);

                // Determine the color table for this frame. If there is a local one, use it
                // otherwise use the global color table.
                byte[] colorTable = localColorTable != null ? localColorTable : _globalColorTable;

                ReadFrameColors(indices, colorTable, imageDescriptor);

                int blockSize = _stream.ReadByte();

                if (blockSize > 0)
                {
                    _stream.Seek(blockSize, SeekOrigin.Current);
                }
            }
    private GifImageDescriptor readImageDescriptor(GifData gifData, byte[] bytes, int offset)
    {
        GifImageDescriptor id = new GifImageDescriptor(gifData);

        id.imageLeft           = BitHelper.getInt16FromBytes(bytes, offset + 1);
        id.imageTop            = BitHelper.getInt16FromBytes(bytes, offset + 3);
        id.imageWidth          = BitHelper.getInt16FromBytes(bytes, offset + 5);
        id.imageHeight         = BitHelper.getInt16FromBytes(bytes, offset + 7);
        id.localColorTableFlag = BitHelper.getIntFromPackedByte(bytes[offset + 9], 0, 1) == 1;
        id.interlaceFlag       = BitHelper.getIntFromPackedByte(bytes[offset + 9], 1, 2) == 1;
        id.sortFlag            = BitHelper.getIntFromPackedByte(bytes[offset + 9], 2, 3) == 1;
        id.localColorTableSize = BitHelper.getIntFromPackedByte(bytes[offset + 9], 5, 8);

        // Interlace flag
        if (id.interlaceFlag)
        {
            throw new NotImplementedException("Use of interlace flag not implemented.");
        }

        return(id);
    }
Exemple #12
0
    static List <Texture2D> CreateAnimator(GifData gifData)
    {
        List <Texture2D> sprites = new List <Texture2D>();

        // Create sprites
        for (int i = 0; i < gifData.graphicsControlExtensions.Count; i++)
        {
            GifGraphicsControlExtension graphicsControlExt = gifData.graphicsControlExtensions[i];
            GifImageDescriptor          imageDescriptor    = graphicsControlExt.imageDescriptor;
            GifImageData imageData = imageDescriptor.imageData;

            Texture2D texture = new Texture2D(gifData.canvasWidth, gifData.canvasHeight);

            // Set texture pixels and create sprite
            texture.SetPixels(imageData.colors);
            texture.Apply();
            texture.filterMode = FilterMode.Point;
            sprites.Add(texture);
        }
        return(sprites);
    }
    public void CreateNextTexture()
    {
        if (textures == null)
        {
            textures = new List <Texture2D>();
        }
        int c = decodeCount;

        for (int i = createCount; i < c; i++)
        {
            GifGraphicsControlExtension graphicsControlExt = graphicsControlExtensions[i];
            GifImageDescriptor          imageDescriptor    = graphicsControlExt.imageDescriptor;
            GifImageData imageData = imageDescriptor.imageData;

            Texture2D texture = new Texture2D(canvasWidth, canvasHeight);
            texture.SetPixels(imageData.colors);
            texture.Apply();
            texture.filterMode = FilterMode.Point;
            textures.Add(texture);
        }
        createCount = c;
    }
Exemple #14
0
        private static FrameMetadata GetFrameMetadata(GifFrame gifMetadata)
        {
            GifImageDescriptor descriptor = gifMetadata.Descriptor;
            FrameMetadata      metadata   = new FrameMetadata {
                Left           = descriptor.Left,
                Top            = descriptor.Top,
                Width          = descriptor.Width,
                Height         = descriptor.Height,
                Delay          = TimeSpan.FromMilliseconds(100.0),
                DisposalMethod = FrameDisposalMethod.None
            };
            GifGraphicControlExtension extension = gifMetadata.Extensions.OfType <GifGraphicControlExtension>().FirstOrDefault <GifGraphicControlExtension>();

            if (extension != null)
            {
                if (extension.Delay != 0)
                {
                    metadata.Delay = TimeSpan.FromMilliseconds((double)extension.Delay);
                }
                metadata.DisposalMethod = (FrameDisposalMethod)extension.DisposalMethod;
            }
            return(metadata);
        }
Exemple #15
0
            private byte[] ReadFrameLocalColorTable(GifImageDescriptor imageDescriptor)
            {
                byte[] localColorTable = null;

                if (imageDescriptor.LocalColorTableFlag == true)
                {
                    localColorTable = new byte[imageDescriptor.LocalColorTableSize * 3];

                    _stream.Read(localColorTable, 0, localColorTable.Length);
                }

                return localColorTable;
            }
Exemple #16
0
    private void createAnimator(GifData gifData)
    {
        List <Sprite>     sprites        = new List <Sprite>();
        GifAnimatorScript animatorScript = gameObject.AddComponent <GifAnimatorScript>();

        Color[] previousFrame    = new Color[gifData.canvasWidth * gifData.canvasHeight];
        Color[] currentFrame     = new Color[gifData.canvasWidth * gifData.canvasHeight];
        Color[] transparentFrame = new Color[gifData.canvasWidth * gifData.canvasHeight];

        // Create sprites
        for (int i = 0; i < gifData.graphicsControlExtensions.Count; i++)
        {
            GifGraphicsControlExtension graphicsControlExt = gifData.graphicsControlExtensions[i];
            GifImageDescriptor          imageDescriptor    = graphicsControlExt.imageDescriptor;
            GifImageData imageData         = imageDescriptor.imageData;
            int          top               = imageDescriptor.imageTop;
            int          left              = imageDescriptor.imageLeft;
            int          disposalMethod    = graphicsControlExt.disposalMethod;
            Texture2D    texture           = new Texture2D(gifData.canvasWidth, gifData.canvasHeight);
            int          transparencyIndex = graphicsControlExt.transparentColorFlag ? graphicsControlExt.transparentColorIndex : -1;

            // Determine base pixels
            if (i == 0)
            {
                texture.SetPixels(transparentFrame);
            }
            else
            {
                if (disposalMethod == 1)
                {
                    texture.SetPixels(previousFrame);
                }
                else if (disposalMethod == 2)
                {
                    texture.SetPixels(transparentFrame);
                }
                else if (disposalMethod == 3)
                {
                    throw new NotImplementedException("Disposal method 3 is not implemented.");
                }
            }

            // Set pixels from image data
            for (int j = 0; j < imageDescriptor.imageWidth; j++)
            {
                for (int k = 0; k < imageDescriptor.imageHeight; k++)
                {
                    int x           = left + j;
                    int y           = (gifData.canvasHeight - 1) - (top + k);
                    int colorIndex  = imageData.colorIndices[j + k * imageDescriptor.imageWidth];
                    int pixelOffset = x + y * gifData.canvasWidth;

                    if (colorIndex != transparencyIndex)
                    {
                        GifColor gifColor = imageData.getColor(colorIndex);

                        currentFrame[pixelOffset] = new Color(gifColor.r / 255f, gifColor.g / 255f, gifColor.b / 255f);
                    }
                }
            }

            //float bgMax = 50f / 255;
            //var transparent = currentFrame.Where(p => p.a == 0);
            //var bgMeanSum = currentFrame.Aggregate(new float[8], (curSum, color) =>
            //{
            //    curSum[4] += color.a;
            //    ++curSum[5];

            //    if (color.a > 0)
            //    {
            //        curSum[6] += color.a;
            //        ++curSum[7];
            //    }

            //    if (color.r >= bgMax || color.g >= bgMax || color.b >= bgMax)
            //        return curSum; // We are interested on dark colors

            //    curSum[0] += color.r;
            //    curSum[1] += color.g;
            //    curSum[2] += color.b;
            //    ++curSum[3];

            //    return curSum;
            //});

            //var bgMean = new Color32(
            //    (byte)(bgMeanSum[0] * 255 / bgMeanSum[3]),
            //    (byte)(bgMeanSum[1] * 255 / bgMeanSum[3]),
            //    (byte)(bgMeanSum[2] * 255 / bgMeanSum[3]),
            //    (byte)(bgMeanSum[4] * 255 / bgMeanSum[5]));

            //Debug.Log(
            //    $"Frame {i} has transparent colors?: {transparent.Any()} || Count: {transparent.Count()} || Background: {bgMean}" +
            //    Environment.NewLine +
            //    $"Solid transparency mean (must be 255): {(byte)(bgMeanSum[6] * 255 / bgMeanSum[7])}");

            // Set texture pixels and create sprite
            texture.SetPixels(currentFrame);
            texture.Apply();
            texture.filterMode = FilterMode.Point;
            sprites.Add(Sprite.Create(texture, new Rect(0f, 0f, gifData.canvasWidth, gifData.canvasHeight), new Vector2(1f, 1f)));

            // Store current frame as previous before continuing, and reset current frame
            currentFrame.CopyTo(previousFrame, 0);
            if (disposalMethod == 0 || disposalMethod == 2)
            {
                currentFrame = new Color[currentFrame.Length];
            }
        }

        // Setup animator script
        animatorScript.sprites = sprites;
    }
Exemple #17
0
            private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
            {
                int imageWidth  = _logicalScreenDescriptor.Width;
                int imageHeight = _logicalScreenDescriptor.Height;

                if (_currentFrame == null)
                {
                    _currentFrame = new byte[imageWidth * imageHeight * 4];
                }

                byte[] lastFrame = null;

                if (_graphicsControl != null &&
                    _graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    lastFrame = new byte[imageWidth * imageHeight * 4];

                    Array.Copy(_currentFrame, lastFrame, lastFrame.Length);
                }

                int offset = 0, i = 0, index = -1;

                int iPass  = 0; // the interlace pass
                int iInc   = 8; // the interlacing line increment
                int iY     = 0; // the current interlaced line
                int writeY = 0; // the target y offset to write to

                for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                {
                    // Check if this image is interlaced.
                    if (descriptor.InterlaceFlag)
                    {
                        // If so then we read lines at predetermined offsets.
                        // When an entire image height worth of offset lines has been read we consider this a pass.
                        // With each pass the number of offset lines changes and the starting line changes.
                        if (iY >= descriptor.Height)
                        {
                            iPass++;
                            switch (iPass)
                            {
                            case 1:
                                iY = 4;
                                break;

                            case 2:
                                iY   = 2;
                                iInc = 4;
                                break;

                            case 3:
                                iY   = 1;
                                iInc = 2;
                                break;
                            }
                        }

                        writeY = iY + descriptor.Top;

                        iY += iInc;
                    }
                    else
                    {
                        writeY = y;
                    }

                    for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                    {
                        offset = writeY * imageWidth + x;

                        index = indices[i];

                        if (_graphicsControl == null ||
                            _graphicsControl.TransparencyFlag == false ||
                            _graphicsControl.TransparencyIndex != index)
                        {
                            _currentFrame[offset * 4 + 0] = colorTable[index * 3 + 0];
                            _currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
                            _currentFrame[offset * 4 + 2] = colorTable[index * 3 + 2];
                            _currentFrame[offset * 4 + 3] = (byte)255;
                        }

                        i++;
                    }
                }

                byte[] pixels = new byte[imageWidth * imageHeight * 4];

                Array.Copy(_currentFrame, pixels, pixels.Length);
                _currentFrame = new byte[imageWidth * imageHeight * 4];
                Image frame = new Image(imageWidth, imageHeight);

                int  indx = 0;
                byte r, g, b, a;

                for (uint y = 0; y < frame.Height; y++)
                {
                    for (uint x = 0; x < frame.Width; x++)
                    {
                        r = pixels[indx];
                        indx++;
                        g = pixels[indx];
                        indx++;
                        b = pixels[indx];
                        indx++;
                        a = pixels[indx];
                        indx++;
                        frame.SetPixel(x, y, new Pixel(r, g, b, a));
                    }
                }
                pixels = null;
                System.GC.Collect();
                _image.AddFrame(frame);


                if (_graphicsControl != null)
                {
                    if (_graphicsControl.DelayTime > 0)
                    {
                        _image.TimePerFrame = _graphicsControl.DelayTime;
                    }

                    if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToBackground)
                    {
                        Image im = new Image(imageWidth, imageHeight);
                        im.Clear(new Pixel(true));
                        _image.AddFrame(im);
                        _image.Loop = false;
                    }
                    else if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                    {
                        _image.Loop = true;
                    }
                }
            }
 private void AddFramDimensions(GifImageDescriptor.ImageDescriptor id)
 {
     FrameDimensions frame = new FrameDimensions();
     frame.Set( id.Left, id.Top,id.Width, id.Height);
     DimensionList.Add(frame);
 }
 public void Set(GifGraphicsControlExtension.GraphicsControlExtension g, GifImageDescriptor.ImageDescriptor id, GifImageData.ImageData d)
 {
     GCE = g;
     desciptor = id;
     data = d;
 }
Exemple #20
0
            private byte[] ReadFrameIndices(GifImageDescriptor imageDescriptor)
            {
                int dataSize = _stream.ReadByte();

                LZWDecoder lzwDecoder = new LZWDecoder(_stream);

                byte[] indices = lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize);
                return indices;
            }
Exemple #21
0
            private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
            {
                int imageWidth = _logicalScreenDescriptor.Width;
                int imageHeight = _logicalScreenDescriptor.Height;

                if (_currentFrame == null)
                {
                    _currentFrame = new byte[imageWidth * imageHeight * 4];
                }

                byte[] lastFrame = null;

                if (_graphicsControl != null &&
                    _graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    lastFrame = new byte[imageWidth * imageHeight * 4];

                    Array.Copy(_currentFrame, lastFrame, lastFrame.Length);
                }

                int offset = 0, i = 0, index = -1;

                int iPass = 0; // the interlace pass
                int iInc = 8; // the interlacing line increment
                int iY = 0; // the current interlaced line
                int writeY = 0; // the target y offset to write to

                for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                {
                    // Check if this image is interlaced.
                    if (descriptor.InterlaceFlag)
                    {
                        // If so then we read lines at predetermined offsets.
                        // When an entire image height worth of offset lines has been read we consider this a pass.
                        // With each pass the number of offset lines changes and the starting line changes.
                        if (iY >= descriptor.Height)
                        {
                            iPass++;
                            switch (iPass)
                            {
                                case 1:
                                    iY = 4;
                                    break;
                                case 2:
                                    iY = 2;
                                    iInc = 4;
                                    break;
                                case 3:
                                    iY = 1;
                                    iInc = 2;
                                    break;
                            }
                        }

                        writeY = iY + descriptor.Top;

                        iY += iInc;
                    }
                    else
                    {
                        writeY = y;
                    }

                    for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                    {
                        offset = writeY * imageWidth + x;

                        index = indices[i];

                        if (_graphicsControl == null ||
                            _graphicsControl.TransparencyFlag == false ||
                            _graphicsControl.TransparencyIndex != index)
                        {
                            _currentFrame[offset * 4 + 0] = colorTable[index * 3 + 0];
                            _currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
                            _currentFrame[offset * 4 + 2] = colorTable[index * 3 + 2];
                            _currentFrame[offset * 4 + 3] = (byte)255;
                        }

                        i++;
                    }
                }

                byte[] pixels = new byte[imageWidth * imageHeight * 4];

                Array.Copy(_currentFrame, pixels, pixels.Length);
                _currentFrame = new byte[imageWidth * imageHeight * 4];
                Image frame = new Image(imageWidth, imageHeight);
                
                int indx = 0;
                byte r, g, b, a;
                for (uint y = 0; y < frame.Height; y++)
                {
                    for (uint x = 0; x < frame.Width; x++)
                    {
                        r = pixels[indx];
                        indx++;
                        g = pixels[indx];
                        indx++;
                        b = pixels[indx];
                        indx++;
                        a = pixels[indx];
                        indx++;
                        frame.SetPixel(x, y, new Pixel(r, g, b, a));
                    }
                }
                pixels = null;
                System.GC.Collect();
                _image.AddFrame(frame);


                if (_graphicsControl != null)
                {
                    if (_graphicsControl.DelayTime > 0)
                    {
                        _image.TimePerFrame = _graphicsControl.DelayTime;
                    }

                    if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToBackground)
                    {
                        Image im = new Image(imageWidth, imageHeight);
                        im.Clear(new Pixel(true));
                        _image.AddFrame(im);
                        _image.Loop = false;
                        
                    }
                    else if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                    {
                        _image.Loop = true;
                    }
                }
            }
Exemple #22
0
            private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
            {
                int imageWidth  = _descriptor.Width;
                int imageHeight = _descriptor.Height;

                if (_currentFrame == null)
                {
                    _currentFrame = new byte[imageWidth * imageHeight * 4];
                }

                byte[] lastFrame = null;

                if (_graphicsControl != null &&
                    _graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    lastFrame = new byte[imageWidth * imageHeight * 4];

                    Array.Copy(_currentFrame, lastFrame, lastFrame.Length);
                }

                int offset = 0, i = 0, index = -1;

                int iPass  = 0; // the interlace pass
                int iInc   = 8; // the interlacing line increment
                int iY     = 0; // the current interlaced line
                int writeY = 0; // the target y offset to write to

                for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                {
                    // Check if this image is interlaced.
                    if (descriptor.InterlaceFlag)
                    {
                        // If so then we read lines at predetermined offsets.
                        // When an entire image height worth of offset lines has been read we consider this a pass.
                        // With each pass the number of offset lines changes and the starting line changes.
                        if (iY >= descriptor.Height)
                        {
                            iPass++;
                            switch (iPass)
                            {
                            case 1:
                                iY = 4;
                                break;

                            case 2:
                                iY   = 2;
                                iInc = 4;
                                break;

                            case 3:
                                iY   = 1;
                                iInc = 2;
                                break;
                            }
                        }

                        writeY = iY + descriptor.Top;

                        iY += iInc;
                    }
                    else
                    {
                        writeY = y;
                    }

                    for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                    {
                        offset = writeY * imageWidth + x;

                        index = indices[i];

                        if (_graphicsControl == null ||
                            _graphicsControl.TransparencyFlag == false ||
                            _graphicsControl.TransparencyIndex != index)
                        {
                            _currentFrame[offset * 4 + 0] = colorTable[index * 3 + 2];
                            _currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
                            _currentFrame[offset * 4 + 2] = colorTable[index * 3 + 0];
                            _currentFrame[offset * 4 + 3] = (byte)255;
                        }

                        i++;
                    }
                }

                var pixels = new byte[imageWidth * imageHeight * 4];

                Array.Copy(_currentFrame, pixels, pixels.Length);

                _frames.Add(new Image(imageWidth, imageHeight, pixels));

                if (_graphicsControl != null)
                {
                    if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToBackground)
                    {
                        for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                        {
                            for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                            {
                                offset = y * imageWidth + x;

                                _currentFrame[offset * 4 + 0] = 0;
                                _currentFrame[offset * 4 + 1] = 0;
                                _currentFrame[offset * 4 + 2] = 0;
                                _currentFrame[offset * 4 + 3] = 0;
                            }
                        }
                    }
                    else if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                    {
                        _currentFrame = lastFrame;
                    }
                }
            }
        private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
        {
            int imageWidth  = logicalScreenDescriptor.Width;
            int imageHeight = logicalScreenDescriptor.Height;

            if (currentFrame == null)
            {
                currentFrame = new Color2[imageWidth * imageHeight];
            }
            Color2[] lastFrame = null;
            if (graphicsControlExtension != null && graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
            {
                lastFrame = new Color2[imageWidth * imageHeight];
                Array.Copy(currentFrame, lastFrame, lastFrame.Length);
            }
            int offset, i = 0;
            int interlacePass      = 0;     // The interlace pass
            int interlaceIncrement = 8;     // The interlacing line increment
            int interlaceY         = 0;     // The current interlaced line

            for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
            {
                // Check if this image is interlaced.
                int writeY;                 // the target y offset to write to
                if (descriptor.InterlaceFlag)
                {
                    // If so then we read lines at predetermined offsets.
                    // When an entire image height worth of offset lines has been read we consider this a pass.
                    // With each pass the number of offset lines changes and the starting line changes.
                    if (interlaceY >= descriptor.Height)
                    {
                        interlacePass++;
                        switch (interlacePass)
                        {
                        case 1:
                            interlaceY = 4;
                            break;

                        case 2:
                            interlaceY         = 2;
                            interlaceIncrement = 4;
                            break;

                        case 3:
                            interlaceY         = 1;
                            interlaceIncrement = 2;
                            break;
                        }
                    }
                    writeY      = interlaceY + descriptor.Top;
                    interlaceY += interlaceIncrement;
                }
                else
                {
                    writeY = y;
                }
                for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                {
                    offset = (writeY * imageWidth) + x;
                    int index = indices[i];
                    if (graphicsControlExtension == null || graphicsControlExtension.TransparencyFlag == false ||
                        graphicsControlExtension.TransparencyIndex != index)
                    {
                        // Stored in r-> g-> b-> a order.
                        int    indexOffset = index * 3;
                        Color2 pixel       = Color2.FromArgb(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2]);
                        currentFrame[offset] = pixel;
                    }
                    i++;
                }
            }
            Color2[] pixels = new Color2[imageWidth * imageHeight];
            Array.Copy(currentFrame, pixels, pixels.Length);
            ImageBase currentImage;

            if (decodedImage.Pixels == null)
            {
                currentImage = decodedImage;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);
                currentImage.Quality = colorTable.Length / 3;
                if (graphicsControlExtension != null && graphicsControlExtension.DelayTime > 0)
                {
                    decodedImage.FrameDelay = graphicsControlExtension.DelayTime;
                }
            }
            else
            {
                ImageFrame frame = new ImageFrame();
                currentImage = frame;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);
                currentImage.Quality = colorTable.Length / 3;
                if (graphicsControlExtension != null && graphicsControlExtension.DelayTime > 0)
                {
                    currentImage.FrameDelay = graphicsControlExtension.DelayTime;
                }
                decodedImage.Frames.Add(frame);
            }
            if (graphicsControlExtension != null)
            {
                if (graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
                {
                    for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                    {
                        for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                        {
                            offset = (y * imageWidth) + x;

                            // Stored in r-> g-> b-> a order.
                            currentFrame[offset] = default(Color2);
                        }
                    }
                }
                else if (graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    currentFrame = lastFrame;
                }
            }
        }
    private void createAnimator(GifData gifData)
    {
        List <Sprite>     sprites        = new List <Sprite>();
        GifAnimatorScript animatorScript = gameObject.AddComponent <GifAnimatorScript>();

        Color[] previousFrame    = new Color[gifData.canvasWidth * gifData.canvasHeight];
        Color[] currentFrame     = new Color[gifData.canvasWidth * gifData.canvasHeight];
        Color[] transparentFrame = new Color[gifData.canvasWidth * gifData.canvasHeight];

        // Create sprites
        for (int i = 0; i < gifData.graphicsControlExtensions.Count; i++)
        {
            GifGraphicsControlExtension graphicsControlExt = gifData.graphicsControlExtensions[i];
            GifImageDescriptor          imageDescriptor    = graphicsControlExt.imageDescriptor;
            GifImageData imageData         = imageDescriptor.imageData;
            int          top               = imageDescriptor.imageTop;
            int          left              = imageDescriptor.imageLeft;
            int          disposalMethod    = graphicsControlExt.disposalMethod;
            Texture2D    texture           = new Texture2D(gifData.canvasWidth, gifData.canvasHeight);
            int          transparencyIndex = graphicsControlExt.transparentColorFlag ? graphicsControlExt.transparentColorIndex : -1;

            // Determine base pixels
            if (i == 0)
            {
                texture.SetPixels(transparentFrame);
            }
            else
            {
                if (disposalMethod == 1)
                {
                    texture.SetPixels(previousFrame);
                }
                else if (disposalMethod == 2)
                {
                    texture.SetPixels(transparentFrame);
                }
                else if (disposalMethod == 3)
                {
                    throw new NotImplementedException("Disposal method 3 is not implemented.");
                }
            }

            // Set pixels from image data
            for (int j = 0; j < imageDescriptor.imageWidth; j++)
            {
                for (int k = 0; k < imageDescriptor.imageHeight; k++)
                {
                    int x           = left + j;
                    int y           = (gifData.canvasHeight - 1) - (top + k);
                    int colorIndex  = imageData.colorIndices[j + k * imageDescriptor.imageWidth];
                    int pixelOffset = x + y * gifData.canvasWidth;

                    if (colorIndex != transparencyIndex)
                    {
                        GifColor gifColor = imageData.getColor(colorIndex);

                        currentFrame[pixelOffset] = new Color(gifColor.r / 255f, gifColor.g / 255f, gifColor.b / 255f);
                    }
                }
            }

            // Set texture pixels and create sprite
            texture.SetPixels(currentFrame);
            texture.Apply();
            texture.filterMode = FilterMode.Point;
            sprites.Add(Sprite.Create(texture, new Rect(0f, 0f, gifData.canvasWidth, gifData.canvasHeight), new Vector2(1f, 1f)));

            // Store current frame as previous before continuing, and reset current frame
            currentFrame.CopyTo(previousFrame, 0);
            if (disposalMethod == 0 || disposalMethod == 2)
            {
                currentFrame = new Color[currentFrame.Length];
            }
        }

        // Setup animator script
        animatorScript.sprites = sprites;
    }
Exemple #25
0
            private GifImageDescriptor ReadImageDescriptor()
            {
                byte[] buffer = new byte[9];

                _stream.Read(buffer, 0, buffer.Length);

                byte packed = buffer[8];

                GifImageDescriptor imageDescriptor = new GifImageDescriptor();
                imageDescriptor.Left = BitConverter.ToInt16(buffer, 0);
                imageDescriptor.Top = BitConverter.ToInt16(buffer, 2);
                imageDescriptor.Width = BitConverter.ToInt16(buffer, 4);
                imageDescriptor.Height = BitConverter.ToInt16(buffer, 6);
                imageDescriptor.LocalColorTableFlag = ((packed & 0x80) >> 7) == 1;
                imageDescriptor.LocalColorTableSize = 2 << (packed & 0x07);
                imageDescriptor.InterlaceFlag = ((packed & 0x40) >> 6) == 1;

                return imageDescriptor;
            }