public FrameGraphicController(byte[] bytes, ref int byteIndex)
        {
            //扩展标引导记 0x21 (1 byte)
            Introducer = bytes[byteIndex];
            byteIndex++;

            //绘图控制扩展标记 0xF9 (1 byte)
            Label = bytes[byteIndex];
            byteIndex++;

            //扩展字节长度 0x04 (1 byte)
            Length = bytes[byteIndex];
            byteIndex++;

            #region Packet Fields (1byte)

            //保留字段(3bit)
            Reserved = bytes[byteIndex] >> 5;

            //图像显示方法 (3 bit)
            NextFrameDisposalMethod = (NextFrameDisposalMethod)((bytes[byteIndex] >> 2) % 8);

            //用户输入标志 (1 bit)
            FlagUserInput = (bytes[byteIndex] >> 1) % 2 == 1;

            //透明颜色索引有效标志 (1 bit)
            FlagTransparentColor = bytes[byteIndex] % 2 == 1;

            #endregion

            //指针下移
            byteIndex++;

            //帧延时 (2 byte)
            DelayTime  = BitConverter.ToUInt16(bytes, byteIndex);
            byteIndex += 2;

            //透明颜色索引 (1 byte)
            TransparentColorIndex = bytes[byteIndex];
            byteIndex++;

            //结尾标识 (1 byte)
            Terminator = bytes[byteIndex];
            byteIndex++;
        }
示例#2
0
        public static SequenceFrame[] GetFrames(TextAsset gifAsset)
        {
            try
            {
                if (_cache.ContainsKey(gifAsset.name))
                {
                    return(_cache[gifAsset.name]);
                }

                var startTime = DateTime.Now;

                //初始化GIF
                var gif = new GraphicsInterchangeFormat(gifAsset.bytes);

                //序列帧集初始化
                var frames = new SequenceFrame[gif.FrameImageDescriptors.Length];
                //初始化Texture
                var frameTexture = new Texture2D(gif.Width, gif.Height);

                //透明背景
                var transparentPixels = frameTexture.GetPixels32();
                for (var index = 0; index < transparentPixels.Length; index++)
                {
                    transparentPixels[index] = Color.clear;
                }

                //背景色
                var backgroundColor  = gif.GetColor32(gif.BgColorIndex);
                var backgroundPixels = frameTexture.GetPixels32();
                for (var index = 0; index < backgroundPixels.Length; index++)
                {
                    backgroundPixels[index] = backgroundColor;
                }

                //记录下一帧的处理方法
                NextFrameDisposalMethod frameDisposalMethod = NextFrameDisposalMethod.Normal;
                bool previousReserved = false;

                //处理每个图块
                for (var frameIndex = 0; frameIndex < frames.Length; frameIndex++)
                {
                    //命名
                    frameTexture.name = "FrameOfIndex" + frameIndex;
                    //图像描述器
                    var frameImageDescriptor = gif.FrameImageDescriptors[frameIndex];
                    //绘图控制扩展
                    var frameGraphicController = gif.FrameGraphicControllers[frameIndex];

                    //上一帧控制器如果记录本帧的处理方法为bg,并且本帧的透明标识为true,那么背景替换为透明
                    if (frameDisposalMethod == NextFrameDisposalMethod.Bg && frameGraphicController.FlagTransparentColor)
                    {
                        //hack SetPixels is slower than SetPixels32
                        frameTexture.SetPixels32(transparentPixels);
                    }

                    //着色范围
                    var blockWidth  = frameImageDescriptor.Width;
                    var blockHeight = frameImageDescriptor.Height;

                    var leftIndex   = frameImageDescriptor.MarginLeft;             //含
                    var rightBorder = leftIndex + blockWidth;                      //不含

                    var topBorder   = gif.Height - frameImageDescriptor.MarginTop; //不含
                    var bottomIndex = topBorder - blockHeight;                     //含

                    //色表
                    var descriptorColors = frameImageDescriptor.GetColors32(frameGraphicController, gif);
                    //色表指针
                    var colorIndex = -1;
                    //gif的y是从上往下,texture的y是从下往上
                    for (var y = topBorder - 1; y >= bottomIndex; y--)
                    {
                        for (var x = leftIndex; x < rightBorder; x++)
                        {
                            colorIndex++;
                            //判断是否保留像素
                            if (previousReserved && descriptorColors[colorIndex].a == 0)
                            {
                                continue;
                            }
                            frameTexture.SetPixel(x, y, descriptorColors[colorIndex]);
                        }
                    }

                    //保存
                    frameTexture.wrapMode = TextureWrapMode.Clamp;
                    frameTexture.Apply();

                    //添加序列帧,并兵初始化Texture
                    var spriteFrame = frameTexture.GetSprite();
                    frames[frameIndex] = new SequenceFrame(spriteFrame, frameGraphicController.DelaySecond);
                    frameTexture       = new Texture2D(gif.Width, gif.Height);

                    //预处理下一帧图像
                    previousReserved = false;
                    switch (frameGraphicController.NextFrameDisposalMethod)
                    {
                    //1 - Do not dispose. The graphic is to be left in place.
                    //保留此帧
                    case NextFrameDisposalMethod.Last:
                        frameTexture.SetPixels32(frames[frameIndex].Texture.GetPixels32());
                        previousReserved = true;
                        break;

                    //2 - Restore to background color. The area used by the graphic must be restored to the background color.
                    //还原成背景色
                    case NextFrameDisposalMethod.Bg:
                        frameTexture.SetPixels32(backgroundPixels);
                        break;

                    //3 - Restore to previous. The decoder is required to restore the area overwritten by the graphic with what was there prior to rendering the graphic.
                    //还原成上一帧
                    case NextFrameDisposalMethod.Previous:
                        frameTexture.SetPixels32(frames[frameIndex - 1].Texture.GetPixels32());
                        previousReserved = true;
                        break;
                    }
                    frameDisposalMethod = frameGraphicController.NextFrameDisposalMethod;
                }

                Debug.Log(string.Format("Analyzing gif {0} with {1} frames costs {2} seconds ", gifAsset.name, frames.Length,
                                        (DateTime.Now - startTime).TotalSeconds.ToString("0.000")));
                _cache.Add(gifAsset.name, frames);
                return(frames);
            }
            catch (Exception ex)
            {
                var logBuilder = new StringBuilder();
                logBuilder.AppendLine("GIF解析发生错误/Gif analysed error");
                logBuilder.AppendLine("可能是版本不兼容导致,请用PhotoShop 存储为web所用格式GIF 后重试/Mybe the version invalid , try to convert it by photoshop web format gif");
                logBuilder.Append(ex.Message);
                Debug.LogError(logBuilder.ToString());
                return(null);
            }
        }