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++; }
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); } }