Making gif with transparent backgrounds has ghosting/flickering
Posted: 2017-01-21T19:41:03-07:00
I'm drawing some bitmaps from a tileset in a game and trying to make some animated GIFs so we don't have to hand-stitch some gifs. I am having an issue where I am getting either some flickering (when optimizing) or some ghosting where previous frames are still shown in further frames. Here are some examples of what I've seen as I try to fool around with it.
Flickering
Ghosting
No Flicker or Ghost but some strange black background on 1 frame, and also not transparent.
I am drawing the images on screen so I am sure the output of my drawing sprite method is OK. Here is my export code - The sprites are drawn on a 256x256 canvas (until the whole sprite is assembled though we wouldn't know the size), and each tile is drawn at a different position in the animation so I can only crop it after I generate all the sprite bitmaps.
I appreciate your help. I'm not a graphics person really so I don't know if I am missing something crucial.
Flickering
Ghosting
No Flicker or Ghost but some strange black background on 1 frame, and also not transparent.
I am drawing the images on screen so I am sure the output of my drawing sprite method is OK. Here is my export code - The sprites are drawn on a 256x256 canvas (until the whole sprite is assembled though we wouldn't know the size), and each tile is drawn at a different position in the animation so I can only crop it after I generate all the sprite bitmaps.
Code: Select all
private void exportedAnimatedGIFOfAnimationToolStripMenuItem_Click(object sender, EventArgs e)
{
int padding = 2;
int animationToExport = Convert.ToInt32(animationIndexUpDown.Value);
Animation anim = ActiveBNSA.Animations[animationToExport];
using (MagickImageCollection collection = new MagickImageCollection())
{
List<GifBitmapDelayPair> sprites = new List<GifBitmapDelayPair>();
//draw all sprites
foreach (Frame f in anim.Frames)
{
int animationDelay = Convert.ToInt32(f.FrameDelay * 1.66); //1/60 in ms;
sprites.Add(new GifBitmapDelayPair(DrawSprite(f), animationDelay));
}
//calculate corners
int top = 256, left = 256, bottom = 0, right = 0; //inverted maximum values.
foreach (GifBitmapDelayPair gbdp in sprites)
{
Bitmap b = gbdp.bitmap;
var pixelsX = Enumerable.Range(0, b.Width);
var pixelsY = Enumerable.Range(0, b.Height);
int localleft = pixelsX.FirstOrDefault(
x => pixelsY.Any(y => b.GetPixel(x, y).A != 0));
int localright = pixelsX.Reverse().FirstOrDefault(
x => pixelsY.Any(y => b.GetPixel(x, y).A != 0));
int localtop = pixelsY.FirstOrDefault(
y => pixelsX.Any(x => b.GetPixel(x, y).A != 0));
int localbottom = pixelsY.Reverse().FirstOrDefault(
y => pixelsX.Any(x => b.GetPixel(x, y).A != 0));
top = Math.Min(top, localtop);
left = Math.Min(left, localleft);
right = Math.Max(right, localright);
bottom = Math.Max(bottom, localbottom);
}
//crop bitmaps
int gifWidth = right - left + padding * 2;
int gifHeight = bottom - top + padding * 2;
foreach (GifBitmapDelayPair gbdp in sprites)
{
gbdp.bitmap = CropBitmap(gbdp.bitmap, left - padding, top - padding, gifWidth, gifHeight);
}
//add bitmaps to animation
foreach (GifBitmapDelayPair gbdp in sprites)
{
MagickImage img = new MagickImage(gbdp.bitmap);
collection.Last().AnimationDelay = gbdp.delay;
}
// Reduce colors (causes flicker)
//QuantizeSettings settings = new QuantizeSettings();
//settings.Colors = 256;
//collection.Quantize(settings);
// Optionally optimize the images (images should have the same size).
//collection.Optimize(); //causes ghosting
//doing neither seems to cause both
// Save gif
collection.Write(@"C:\Users\Michael\BNSA\output.gif");
}
}