private GifImageData readImageData(GifData gifData, byte[] bytes, int offset) { GifImageData imgData = new GifImageData(gifData); int subblockOffset = offset + 1; int subblockCount = 0; imgData.lzwMinimumCodeSize = bytes[offset]; // Read subblock data while (true) { int subblockSize = bytes[subblockOffset]; if (subblockSize == 0) { break; } else { for (int i = 0; i < subblockSize; i++) { imgData.blockBytes.Add(bytes[subblockOffset + 1 + i]); } subblockOffset += subblockSize + 1; subblockCount++; } } imgData.endingOffset = subblockOffset; //Debug.Log("Number of subblocks read: " + subblockCount); return(imgData); }
static void CalculColors(GifData gifData, int index) { Color[] previousFrame = gifData.previousFrame; if (previousFrame == null) { previousFrame = new Color[gifData.canvasWidth * gifData.canvasHeight]; } Color[] currentFrame = gifData.currentFrame; if (currentFrame == null) { currentFrame = new Color[gifData.canvasWidth * gifData.canvasHeight]; } Color[] transparentFrame = gifData.transparentFrame; if (transparentFrame == null) { transparentFrame = new Color[gifData.canvasWidth * gifData.canvasHeight]; } GifGraphicsControlExtension graphicsControlExt = gifData.graphicsControlExtensions[index]; 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]; } } } 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); } gifData.previousFrame = previousFrame; gifData.currentFrame = currentFrame; gifData.transparentFrame = transparentFrame; }
internal static GifImageData ReadImageData(Stream stream, bool metadataOnly) { var imgData = new GifImageData(); imgData.Read(stream, metadataOnly); return(imgData); }
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(); }
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); } } }
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; }
private async Task <Stream> GetIndexStreamAsync(GifFrame frame, CancellationToken cancellationToken) { GifImageData data = frame.ImageData; cancellationToken.ThrowIfCancellationRequested(); this._sourceStream.Seek(data.CompressedDataStartOffset, SeekOrigin.Begin); MemoryStream ms = new MemoryStream(this._indexStreamBuffer); try { await GifHelpers.CopyDataBlocksToStreamAsync(this._sourceStream, (Stream)ms, cancellationToken).ConfigureAwait(false); } finally { if (ms != null) { ((IDisposable)ms).Dispose(); } } ms = null; return((Stream) new LzwDecompressStream(this._indexStreamBuffer, (int)data.LzwMinimumCodeSize)); }
/// <summary> /// Animates the given image. /// </summary> /// <param name="image"></param> /// <param name="onFrameChangedHandler"></param> public void Animate(Image image, EventHandler onFrameChangedHandler) { if (!CanAnimate(image)) { return; } if (ourImageState.ContainsKey(image)) { return; } // AddOrUpdate has a race condition that could allow us to erroneously // create multiple animation threads per image. To combat that // we manually try to add entries ourself, and if it fails we // kill the thread. // GifImageData toAdd = AddFactory(image, onFrameChangedHandler); if (!ourImageState.TryAdd(image, toAdd)) { Interlocked.Exchange(ref toAdd.myIsThreadDead, 1); } }
private GifImageData AddFactory(Image image, EventHandler eventHandler) { GifImageData data; lock (image) { data = new GifImageData(image, eventHandler); } Thread heartbeat = new Thread(() => { int sleepTime = getSleepAmountInMilliseconds(data.GetCurrentDelayInMilliseconds()); Thread.Sleep(sleepTime); while (data.ThreadIsNotDead()) { data.HandleUpdateTick(); sleepTime = getSleepAmountInMilliseconds(data.GetCurrentDelayInMilliseconds()); Thread.Sleep(sleepTime); } }); heartbeat.IsBackground = true; heartbeat.Name = "heartbeat - HighResolutionAnimator"; heartbeat.Start(); return(data); }
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; }
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; }
public void Set(GifGraphicsControlExtension.GraphicsControlExtension g, GifImageDescriptor.ImageDescriptor id, GifImageData.ImageData d) { GCE = g; desciptor = id; data = d; }