public void BadEncodingUsingGameboyPaletteLocal() { ReportStart(); _e = new AnimatedGifEncoder(); _e.ColourTableStrategy = ColourTableStrategy.UseLocal; _e.QuantizerType = QuantizerType.UseSuppliedPalette; GifFrame frame = new GifFrame(Image.FromFile(@"images\smiley.bmp")); _e.AddFrame(frame); Assert.AreEqual(ColourTableStrategy.UseLocal, _e.ColourTableStrategy); Assert.AreEqual(QuantizerType.UseSuppliedPalette, _e.QuantizerType); frame.Palette = Palette.FromFile(@"ColourTables\gameboy.act"); Assert.AreEqual(ColourTableStrategy.UseLocal, _e.ColourTableStrategy); Assert.AreEqual(QuantizerType.UseSuppliedPalette, _e.QuantizerType); _e.WriteToFile(GifFileName); _d = new GifDecoder(GifFileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState); ReportEnd(); }
private void Encode() { // Note the encoder was instantiated in this form's constructor // and the user has set its properties in the UI, including adding // all the frames. try { _encoder.WriteToFile(_saveFileName); Invoke(new MethodInvoker(StopTheClock)); } catch (Exception ex) { HandleException(ex); } }
public void TransparencyTest() { ReportStart(); Color noColour = Color.FromArgb(0, 0, 0, 0); // note alpha of 0 Color blue = Color.FromArgb(0, 0, 255); Color transparent = Color.FromArgb(100, 100, 100); _encoder = new AnimatedGifEncoder(); _encoder.Transparent = transparent; // transparent | transparent // ------------------------- // blue | blue Bitmap bitmap = new Bitmap(2, 2); bitmap.SetPixel(0, 0, transparent); bitmap.SetPixel(1, 0, transparent); bitmap.SetPixel(0, 1, blue); bitmap.SetPixel(1, 1, blue); _frame = new GifFrame(bitmap); _encoder.AddFrame(_frame); // encode and decode string filename = "GifFrameTest.TransparencyTest.gif"; _encoder.WriteToFile(filename); _decoder = new GifDecoder(filename); _decoder.Decode(); Assert.AreEqual(ErrorState.Ok, _decoder.ConsolidatedState); // Result should be: // black | black // ------------- // blue | blue Bitmap actual = (Bitmap)_decoder.Frames[0].TheImage; Assert.AreEqual(noColour, actual.GetPixel(0, 0)); Assert.AreEqual(noColour, actual.GetPixel(1, 0)); Assert.AreEqual(blue, actual.GetPixel(0, 1)); Assert.AreEqual(blue, actual.GetPixel(1, 1)); ReportEnd(); }
private void TryDifferentPixelFormats() { Size size = new Size(50, 50); int blockiness = 10; PixelFormat[] pixelFormats = new PixelFormat[] { PixelFormat.Format16bppArgb1555, PixelFormat.Format16bppRgb555, PixelFormat.Format16bppRgb565, PixelFormat.Format24bppRgb, PixelFormat.Format32bppArgb, PixelFormat.Format32bppPArgb, PixelFormat.Format32bppRgb, PixelFormat.Format48bppRgb, PixelFormat.Format64bppArgb, PixelFormat.Format64bppPArgb, }; foreach (PixelFormat pf in pixelFormats) { string formatName = pf.ToString(); _encoder = new AnimatedGifEncoder(); for (int i = 0; i < 10; i++) { Bitmap bitmap = RandomBitmap.Create(size, blockiness, pf); _encoder.AddFrame(new GifFrame(bitmap)); } DateTime startTime = DateTime.Now; _encoder.WriteToFile(formatName + ".gif"); DateTime endTime = DateTime.Now; TimeSpan timeToEncode8bit = endTime - startTime; WriteMessage("Encoding " + formatName + " took " + timeToEncode8bit); } }
/// <summary> /// Tests the AnimatedGifEncoder and the encoded GIF file it produces /// using the supplied parameters as property values. /// </summary> private void TestAnimatedGifEncoder(ColourTableStrategy strategy, int colourQuality, Size logicalScreenSize) { _e = new AnimatedGifEncoder(); // Check default properties set by constructor. Assert.AreEqual(ColourTableStrategy.UseGlobal, _e.ColourTableStrategy, "Colour table strategy set by constructor"); Assert.AreEqual(10, _e.SamplingFactor, "Colour quantization quality set by constructor"); Assert.AreEqual(Size.Empty, _e.LogicalScreenSize, "Logical screen size set by constructor"); _e.ColourTableStrategy = strategy; _e.SamplingFactor = colourQuality; _e.LogicalScreenSize = logicalScreenSize; // Check property set/gets Assert.AreEqual(strategy, _e.ColourTableStrategy, "Colour table strategy property set/get"); Assert.AreEqual(colourQuality, _e.SamplingFactor, "Colour quantization quality property set/get"); Assert.AreEqual(logicalScreenSize, _e.LogicalScreenSize, "Logical screen size property get/set"); foreach (GifFrame thisFrame in _frames) { _e.AddFrame(thisFrame); } StackTrace t = new StackTrace(); StackFrame f = t.GetFrame(1); string fileName = "Checks." + this.GetType().Name + "." + f.GetMethod().Name + ".gif"; _e.WriteToFile(fileName); Stream s = File.OpenRead(fileName); // global info CheckGifHeader(s); bool shouldHaveGlobalColourTable = (strategy == ColourTableStrategy.UseGlobal); LogicalScreenDescriptor lsd = CheckLogicalScreenDescriptor(s, shouldHaveGlobalColourTable); // Only check the global colour table if there should be one ColourTable gct = null; if (shouldHaveGlobalColourTable) { gct = CheckColourTable(s, lsd.GlobalColourTableSize); } CheckExtensionIntroducer(s); CheckAppExtensionLabel(s); CheckNetscapeExtension(s, 0); CheckFrame(s, gct, Bitmap1()); CheckFrame(s, gct, Bitmap2()); // end of image data CheckGifTrailer(s); CheckEndOfStream(s); s.Close(); // Check the file using the decoder _d = new GifDecoder(fileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState, "Decoder consolidated state"); Assert.AreEqual(2, _d.Frames.Count, "Decoder frame count"); Assert.AreEqual(shouldHaveGlobalColourTable, _d.LogicalScreenDescriptor.HasGlobalColourTable, "Should have global colour table"); Assert.AreEqual(logicalScreenSize, _d.LogicalScreenDescriptor.LogicalScreenSize, "Decoder logical screen size"); BitmapAssert.AreEqual(Bitmap1(), (Bitmap)_d.Frames[0].TheImage, "frame 0"); BitmapAssert.AreEqual(Bitmap2(), (Bitmap)_d.Frames[1].TheImage, "frame 1"); bool shouldHaveLocalColourTable = !shouldHaveGlobalColourTable; Assert.AreEqual(shouldHaveLocalColourTable, _d.Frames[0].ImageDescriptor.HasLocalColourTable, "Frame 0 has local colour table"); Assert.AreEqual(shouldHaveLocalColourTable, _d.Frames[1].ImageDescriptor.HasLocalColourTable, "Frame 0 has local colour table"); }
private void TestUseSuppliedPalette(ColourTableStrategy strategy) { string globalLocal = strategy == ColourTableStrategy.UseGlobal ? "Global" : "Local"; // First, create and check a series of single-frame GIFs, one for // each of the available colour tables. string[] files = Directory.GetFiles(@"ColourTables", "*.act"); foreach (string act in files) { string actFileWithoutExtension = Path.GetFileNameWithoutExtension(act); _e = new AnimatedGifEncoder(); if (strategy == ColourTableStrategy.UseGlobal) { _e.Palette = Palette.FromFile(act); Assert.AreEqual(ColourTableStrategy.UseGlobal, _e.ColourTableStrategy); // QuantizerType should default to UseSuppliedPalette when // the encoder's Palette property is set. Assert.AreEqual(QuantizerType.UseSuppliedPalette, _e.QuantizerType); } else { _e.ColourTableStrategy = ColourTableStrategy.UseLocal; Assert.AreEqual(ColourTableStrategy.UseLocal, _e.ColourTableStrategy); _e.QuantizerType = QuantizerType.UseSuppliedPalette; Assert.AreEqual(QuantizerType.UseSuppliedPalette, _e.QuantizerType); } GifFrame frame = new GifFrame(Image.FromFile(@"images\smiley.bmp")); if (strategy == ColourTableStrategy.UseLocal) { frame.Palette = Palette.FromFile(act); } _e.AddFrame(frame); string fileName = "AnimatedGifEncoderTest.UseSuppliedPalette" + globalLocal + "-" + actFileWithoutExtension + ".gif"; _e.WriteToFile(fileName); _d = new GifDecoder(fileName, true); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState, actFileWithoutExtension); Assert.AreEqual(1, _d.Frames.Count, actFileWithoutExtension); if (strategy == ColourTableStrategy.UseGlobal) { Assert.AreEqual(true, _d.LogicalScreenDescriptor.HasGlobalColourTable, actFileWithoutExtension); Assert.IsNotNull(_d.GlobalColourTable, actFileWithoutExtension); } else { Assert.AreEqual(false, _d.LogicalScreenDescriptor.HasGlobalColourTable, actFileWithoutExtension); Assert.IsNull(_d.GlobalColourTable, actFileWithoutExtension); } string expectedFileName = @"images\Smiley\Smiley" + "-" + actFileWithoutExtension + ".bmp"; Image expected = Image.FromFile(expectedFileName); ImageAssert.AreEqual(expected, _d.Frames[0].TheImage, expectedFileName); } // now encode a multi-frame animation with a user-supplied palette _d = new GifDecoder(@"images\globe\spinning globe better 200px transparent background.gif"); _d.Decode(); _e = new AnimatedGifEncoder(); _e.QuantizerType = QuantizerType.UseSuppliedPalette; _e.Palette = Palette.FromFile(@"ColourTables\C64.act"); foreach (GifFrame f in _d.Frames) { _e.AddFrame(f); } string globeFileName = "AnimatedGifEncoderTest.UseSuppliedPalette" + globalLocal + ".gif"; _e.WriteToFile(globeFileName); _d = new GifDecoder(globeFileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState); Assert.AreEqual(_e.Frames.Count, _d.Frames.Count); }
public void WikipediaExampleTest() { ReportStart(); _e = new AnimatedGifEncoder(); GifFrame frame = new GifFrame(WikipediaExample.ExpectedBitmap); frame.Delay = WikipediaExample.DelayTime; _e.AddFrame(frame); // TODO: some way of creating/testing a UseLocal version of WikipediaExample string fileName = "WikipediaExampleUseGlobal.gif"; _e.WriteToFile(fileName); Stream s = File.OpenRead(fileName); int code; // check GIF header GifHeader gh = new GifHeader(s); Assert.AreEqual(ErrorState.Ok, gh.ConsolidatedState); // check logical screen descriptor LogicalScreenDescriptor lsd = new LogicalScreenDescriptor(s); Assert.AreEqual(ErrorState.Ok, lsd.ConsolidatedState); WikipediaExample.CheckLogicalScreenDescriptor(lsd); // read global colour table ColourTable gct = new ColourTable(s, WikipediaExample.GlobalColourTableSize); Assert.AreEqual(ErrorState.Ok, gct.ConsolidatedState); // cannot compare global colour table as different encoders will // produce difference colour tables. // WikipediaExample.CheckGlobalColourTable( gct ); // check for extension introducer code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeExtensionIntroducer, code); // check for app extension label code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeApplicationExtensionLabel, code); // check netscape extension ApplicationExtension ae = new ApplicationExtension(s); Assert.AreEqual(ErrorState.Ok, ae.ConsolidatedState); NetscapeExtension ne = new NetscapeExtension(ae); Assert.AreEqual(ErrorState.Ok, ne.ConsolidatedState); Assert.AreEqual(0, ne.LoopCount); // check for extension introducer code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeExtensionIntroducer, code); // check for gce label code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeGraphicControlLabel, code); // check graphic control extension GraphicControlExtension gce = new GraphicControlExtension(s); Assert.AreEqual(ErrorState.Ok, gce.ConsolidatedState); WikipediaExample.CheckGraphicControlExtension(gce); // check for image separator code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeImageSeparator, code); // check for image descriptor ImageDescriptor id = new ImageDescriptor(s); Assert.AreEqual(ErrorState.Ok, id.ConsolidatedState); WikipediaExample.CheckImageDescriptor(id); // read, decode and check image data // Cannot compare encoded LZW data directly as different encoders // will create different colour tables, so even if the bitmaps are // identical, the colour indices will be different int pixelCount = WikipediaExample.FrameSize.Width * WikipediaExample.FrameSize.Height; TableBasedImageData tbid = new TableBasedImageData(s, pixelCount); for (int y = 0; y < WikipediaExample.LogicalScreenSize.Height; y++) { for (int x = 0; x < WikipediaExample.LogicalScreenSize.Width; x++) { int i = (y * WikipediaExample.LogicalScreenSize.Width) + x; Assert.AreEqual(WikipediaExample.ExpectedBitmap.GetPixel(x, y), gct[tbid.Pixels[i]], "X: " + x + ", Y: " + y); } } // Check for block terminator after image data code = ExampleComponent.CallRead(s); Assert.AreEqual(0x00, code); // check for GIF trailer code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeTrailer, code); // check we're at the end of the stream code = ExampleComponent.CallRead(s); Assert.AreEqual(-1, code); s.Close(); _d = new GifDecoder(fileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState); BitmapAssert.AreEqual(WikipediaExample.ExpectedBitmap, (Bitmap)_d.Frames[0].TheImage, ""); ReportEnd(); }
private void DoEncode() { _e.WriteToFile("MockOrange.test.gif"); }
public void CompareQuantizers() { ReportStart(); string fileName; DateTime startTime; DateTime endTime; TimeSpan encodingTime; // Test actual quantization using image with 256+ colours. string bitmapFileName = "images/" + TestFixtureName + "." + TestCaseName + ".bmp"; Bitmap b = new Bitmap(bitmapFileName); for (int q = 1; q <= 20; q++) { _e = new AnimatedGifEncoder(); _e.QuantizerType = QuantizerType.NeuQuant; _e.SamplingFactor = q; _e.AddFrame(new GifFrame(b)); fileName = TestFixtureName + "." + TestCaseName + ".NeuQuant." + q + ".gif"; startTime = DateTime.Now; _e.WriteToFile(fileName); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage("Encoding with quantization using NeuQuant, quality=" + q + " took " + encodingTime); _d = new GifDecoder(fileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState, "Quality " + q); Assert.AreEqual(1, _d.Frames.Count, "Quality " + q); // FIXME: NeuQuant quantizer reducing to 180 colours instead of 256 colours // TODO: Check for exactly 256 colours once Octree quantizer returns 256-colour images // Assert.AreEqual( 256, ImageTools.GetDistinctColours( colours ).Count ); Assert.LessOrEqual(ImageTools.GetDistinctColours(_d.Frames[0].TheImage).Count, 256); for (int tolerance = 0; tolerance < 256; tolerance++) { try { ImageAssert.AreEqual(b, _d.Frames[0].TheImage, tolerance, "Quality " + q); WriteMessage("Quality " + q + " required tolerance " + tolerance); break; } catch (AssertionExtensionException) { if (tolerance == 255) { throw; } } } } _e = new AnimatedGifEncoder(); _e.QuantizerType = QuantizerType.Octree; _e.AddFrame(new GifFrame(b)); fileName = TestFixtureName + "." + TestCaseName + ".Octree.gif"; startTime = DateTime.Now; _e.WriteToFile(fileName); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage("Encoding with quantization using Octree took " + encodingTime); _d = new GifDecoder(fileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState); Assert.AreEqual(1, _d.Frames.Count); // FIXME: Octree quantizer should return a 256-colour image here // Assert.AreEqual( 256, ImageTools.GetDistinctColours( colours2 ).Count ); Assert.LessOrEqual(ImageTools.GetDistinctColours(_d.Frames[0].TheImage).Count, 256); for (int tolerance = 0; tolerance < 256; tolerance++) { try { ImageAssert.AreEqual(b, _d.Frames[0].TheImage, tolerance, "Octree"); WriteMessage("Octree quantization required tolerance " + tolerance); break; } catch (AssertionExtensionException) { if (tolerance == 255) { throw; } } } // re-encoding an existing GIF should not cause quantization _d = new GifDecoder(@"images\globe\spinning globe better 200px transparent background.gif"); _d.Decode(); _e = new AnimatedGifEncoder(); // NB OctreeQuantizer does not support global colour tables (yet!) _e.ColourTableStrategy = ColourTableStrategy.UseLocal; foreach (GifFrame f in _d.Frames) { _e.AddFrame(new GifFrame(f.TheImage)); } fileName = "NeuQuant.gif"; _e.QuantizerType = QuantizerType.NeuQuant; startTime = DateTime.Now; _e.WriteToFile(fileName); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage("Encoding without quantization using NeuQuant took " + encodingTime); fileName = "Octree.gif"; _e.QuantizerType = QuantizerType.Octree; startTime = DateTime.Now; _e.WriteToFile(fileName); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage("Encoding without quantization using Octree took " + encodingTime); GifDecoder nqDecoder = new GifDecoder("NeuQuant.gif"); nqDecoder.Decode(); GifDecoder otDecoder = new GifDecoder("Octree.gif"); otDecoder.Decode(); Assert.AreEqual(nqDecoder.Frames.Count, otDecoder.Frames.Count); for (int i = 0; i < nqDecoder.Frames.Count; i++) { ImageAssert.AreEqual(nqDecoder.Frames[i].TheImage, otDecoder.Frames[i].TheImage, "frame " + i); } ReportEnd(); }
public void Bug2892015() { ReportStart(); _e = new AnimatedGifEncoder(); #region create 10 random bitmaps Collection<Bitmap> bitmaps = new Collection<Bitmap>(); for( int i = 0; i < 10; i++ ) { Bitmap bitmap = RandomBitmap.Create( new Size( 50, 50 ), 10, PixelFormat.Format32bppRgb ); bitmaps.Add( bitmap ); } #endregion DateTime startTime; DateTime endTime; #region create animation using just the first 3 (this should be quick) for( int i = 0; i < 3; i++ ) { _e.AddFrame( new GifFrame( bitmaps[i] ) ); } startTime = DateTime.Now; _e.WriteToFile( "2892015-1.gif" ); endTime = DateTime.Now; TimeSpan runTime1 = endTime - startTime; WriteMessage( "Encoding 3 frames took " + runTime1 ); #endregion _e.Frames.Clear(); #region create animation using all the bitmaps (this will take longer) foreach( Bitmap bitmap in bitmaps ) { _e.AddFrame( new GifFrame( bitmap ) ); } startTime = DateTime.Now; _e.WriteToFile( "2892015-2.gif" ); endTime = DateTime.Now; TimeSpan runTime2 = endTime - startTime; WriteMessage( "Encoding all " + bitmaps.Count + " frames took " + runTime2 ); #endregion _e.Frames.Clear(); #region create animation using just the first 3 (this should be quick) for( int i = 0; i < 3; i++ ) { _e.AddFrame( new GifFrame( bitmaps[i] ) ); } startTime = DateTime.Now; _e.WriteToFile( "2892015-3.gif" ); endTime = DateTime.Now; TimeSpan runTime3 = endTime - startTime; WriteMessage( "Encoding 3 frames took " + runTime3 ); #endregion Assert.IsTrue( runTime3 < runTime2 ); _d = new GifDecoder( "2892015-3.gif" ); _d.Decode(); Assert.AreEqual( 3, _d.Frames.Count ); ReportEnd(); }
private void TestUseSuppliedPalette( ColourTableStrategy strategy ) { string globalLocal = strategy == ColourTableStrategy.UseGlobal ? "Global" : "Local"; // First, create and check a series of single-frame GIFs, one for // each of the available colour tables. string[] files = Directory.GetFiles( @"ColourTables", "*.act" ); foreach( string act in files ) { string actFileWithoutExtension = Path.GetFileNameWithoutExtension( act ); _e = new AnimatedGifEncoder(); if( strategy == ColourTableStrategy.UseGlobal ) { _e.Palette = Palette.FromFile( act ); Assert.AreEqual( ColourTableStrategy.UseGlobal, _e.ColourTableStrategy ); // QuantizerType should default to UseSuppliedPalette when // the encoder's Palette property is set. Assert.AreEqual( QuantizerType.UseSuppliedPalette, _e.QuantizerType ); } else { _e.ColourTableStrategy = ColourTableStrategy.UseLocal; Assert.AreEqual( ColourTableStrategy.UseLocal, _e.ColourTableStrategy ); _e.QuantizerType = QuantizerType.UseSuppliedPalette; Assert.AreEqual( QuantizerType.UseSuppliedPalette, _e.QuantizerType ); } GifFrame frame = new GifFrame( Image.FromFile( @"images\smiley.bmp" ) ); if( strategy == ColourTableStrategy.UseLocal ) { frame.Palette = Palette.FromFile( act ); } _e.AddFrame( frame ); string fileName = "AnimatedGifEncoderTest.UseSuppliedPalette" + globalLocal + "-" + actFileWithoutExtension + ".gif"; _e.WriteToFile( fileName ); _d = new GifDecoder( fileName, true ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState, actFileWithoutExtension ); Assert.AreEqual( 1, _d.Frames.Count, actFileWithoutExtension ); if( strategy == ColourTableStrategy.UseGlobal ) { Assert.AreEqual( true, _d.LogicalScreenDescriptor.HasGlobalColourTable, actFileWithoutExtension ); Assert.IsNotNull( _d.GlobalColourTable, actFileWithoutExtension ); } else { Assert.AreEqual( false, _d.LogicalScreenDescriptor.HasGlobalColourTable, actFileWithoutExtension ); Assert.IsNull( _d.GlobalColourTable, actFileWithoutExtension ); } string expectedFileName = @"images\Smiley\Smiley" + "-" + actFileWithoutExtension + ".bmp"; Image expected = Image.FromFile( expectedFileName ); ImageAssert.AreEqual( expected, _d.Frames[0].TheImage, expectedFileName ); } // now encode a multi-frame animation with a user-supplied palette _d = new GifDecoder( @"images\globe\spinning globe better 200px transparent background.gif" ); _d.Decode(); _e = new AnimatedGifEncoder(); _e.QuantizerType = QuantizerType.UseSuppliedPalette; _e.Palette = Palette.FromFile( @"ColourTables\C64.act" ); foreach( GifFrame f in _d.Frames ) { _e.AddFrame( f ); } string globeFileName = "AnimatedGifEncoderTest.UseSuppliedPalette" + globalLocal + ".gif"; _e.WriteToFile( globeFileName ); _d = new GifDecoder( globeFileName ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState ); Assert.AreEqual( _e.Frames.Count, _d.Frames.Count ); }
public static void ExtractAnimation(WzSubProperty parent, string savePath, bool apng, bool apngFirstFrame) { List <Bitmap> bmpList = new List <Bitmap>(parent.WzProperties.Count); List <int> delayList = new List <int>(parent.WzProperties.Count); Point biggestPng = new Point(0, 0); Point SmallestEmptySpace = new Point(65535, 65535); Point MaximumPngMappingEndingPts = new Point(0, 0); foreach (IWzImageProperty subprop in parent.WzProperties) { if (subprop is WzCanvasProperty) { //WzVectorProperty origin = (WzVectorProperty)subprop["origin"]; WzPngProperty png = ((WzCanvasProperty)subprop).PngProperty; if (png.Height > biggestPng.Y) { biggestPng.Y = png.Height; } if (png.Width > biggestPng.X) { biggestPng.X = png.Width; } } } List <WzCanvasProperty> sortedProps = new List <WzCanvasProperty>(); foreach (IWzImageProperty subprop in parent.WzProperties) { if (subprop is WzCanvasProperty) { sortedProps.Add((WzCanvasProperty)subprop); WzPngProperty png = ((WzCanvasProperty)subprop).PngProperty; WzVectorProperty origin = (WzVectorProperty)subprop["origin"]; Point StartPoints = new Point(biggestPng.X - origin.X.Value, biggestPng.Y - origin.Y.Value); Point PngMapppingEndingPts = new Point(StartPoints.X + png.Width, StartPoints.Y + png.Height); if (StartPoints.X < SmallestEmptySpace.X) { SmallestEmptySpace.X = StartPoints.X; } if (StartPoints.Y < SmallestEmptySpace.Y) { SmallestEmptySpace.Y = StartPoints.Y; } if (PngMapppingEndingPts.X > MaximumPngMappingEndingPts.X) { MaximumPngMappingEndingPts.X = PngMapppingEndingPts.X; } if (PngMapppingEndingPts.Y > MaximumPngMappingEndingPts.Y) { MaximumPngMappingEndingPts.Y = PngMapppingEndingPts.Y; } } } sortedProps.Sort(new Comparison <WzCanvasProperty>(PropertySorter)); /* foreach (IWzImageProperty subprop in parent.WzProperties) * { * if (subprop is WzCanvasProperty) * { * WzCompressedIntProperty delayProp = (WzCompressedIntProperty)subprop["delay"]; * if (delayProp != null) delay = delayProp.Value; * } * }*/ /* Brush bgcolor = null; * switch (toolStripComboBox2.SelectedIndex) * { * case 0: * bgcolor = Brushes.Widthhite; * break; * case 1: * bgcolor = Brushes.Black; * break; * default: * bgcolor = Brushes.Black; * break; * }*/ for (int i = 0; i < sortedProps.Count; i++) { WzCanvasProperty subprop = sortedProps[i]; if (i.ToString() != subprop.Name) { Warning.Error("Something f****d up at animation builder, frame " + i.ToString()); return; } Bitmap bmp = subprop.PngProperty.GetPNG(false); WzVectorProperty origin = (WzVectorProperty)subprop["origin"]; // if (apng) bmpList.Add(OptimizeBitmapTransparent(bmp, origin, biggestPng, SmallestEmptySpace, MaximumPngMappingEndingPts)); /* else * bmpList.Add(OptimizeBitmap(bmp, origin, biggestPng, SmallestEmptySpace, MaximumPngMappingEndingPts, bgcolor));*/ WzCompressedIntProperty delayProp = (WzCompressedIntProperty)subprop["delay"]; int delay = 100; if (delayProp != null) { delay = delayProp.Value; } delayList.Add(delay); //} } if (apng) { //List<Frame> frameList = new List<Frame>(); /* List<int> delayList = new List<int>(); * foreach (TreeNode subnode in parent.Nodes) * { * if (subnode.Tag2 is PNG) * { * TreeNode delayNode = FindNodeInSubnodes(subnode, "delay"); * if (delayNode == null) delayList.Add(0); * else delayList.Add((int)delayNode.Tag2); * } * } * if (delayList.Count != bmp.Count) * { * MessageBox.Show("Weird error, seems like there are more PNGs than delay values"); * return; * }*/ Apng apngBuilder = new Apng(); if (apngFirstFrame) { apngBuilder.AddFrame(new Frame(CreateIncompatibilityFrame(new Size(bmpList[0].Width, bmpList[0].Height)), 1, 1)); } for (int i = 0; i < bmpList.Count; i++) { apngBuilder.AddFrame(new Frame(bmpList[i], getNumByDelay(delayList[i]), getDenByDelay(delayList[i]))); } apngBuilder.WriteApng(savePath, apngFirstFrame, true); //createapng(frameList, savePath); } else { AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder(); for (int i = 0; i < bmpList.Count; i++) { gifEncoder.AddFrame(new GifFrame(bmpList[i]) { Delay = delayList[i] / 10 }); } gifEncoder.WriteToFile(savePath); } }
public void ExportAnimationAsGif() { var error = false; if (CurrentShownSpriteSheet == null) { Messager.ShowMessage(Messager.Mode.Exception, "No spritesheet loaded! Please load a sprite sheet first by clicking the button Import Spritesheet on topbar"); return; } if (CurrentShownAnimation != null) { if (CurrentShownAnimation.Frames.Count == 0) { Messager.ShowMessage(Messager.Mode.Exception, "No frames to export. The animation is empty!"); return; } var path = ShowCompleteSaveToDialog("Choose location to save GIF", @"Animated GIF(.gif)|*.gif"); if (path == null) { return; } if (path.Length == 0) { Messager.ShowMessage(Messager.Mode.Exception, string.Format("Nothing exported. The path is invalid or empty!")); return; } try { Size frameSize = Size.Empty; Point offSetMin = Point.Empty; Point offSetMax = Point.Empty; foreach (var frame in CurrentShownAnimation.Frames) { if (frame.SpriteFrame.Width > frameSize.Width) { frameSize.Width = frame.SpriteFrame.Width; } if (frame.SpriteFrame.Height > frameSize.Height) { frameSize.Height = frame.SpriteFrame.Height; } } foreach (var frame in CurrentShownAnimation.Frames) { if (frame.OffSetX < offSetMin.X) { offSetMin.X = frame.OffSetX; } if (frame.OffSetY < offSetMin.Y) { offSetMin.Y = frame.OffSetY; } if (frame.OffSetX > offSetMax.X) { offSetMax.X = frame.OffSetX; } if (frame.OffSetY > offSetMax.Y) { offSetMax.Y = frame.OffSetY; } } frameSize.Width += Math.Abs(offSetMin.X) + offSetMax.X; frameSize.Height += Math.Abs(offSetMin.Y) + offSetMax.Y; frameSize.Width = frameSize.Width > frameSize.Height ? frameSize.Width : frameSize.Height; frameSize.Height = frameSize.Width; int repeatCount = CurrentShownAnimation.Loop ? 0 : 1; ColourTableStrategy strategy = ColourTableStrategy.UseGlobal; int quality = 10; AnimatedGifEncoder animatedGifEncoder = new AnimatedGifEncoder { LogicalScreenSize = frameSize, RepeatCount = repeatCount, ColourTableStrategy = strategy, SamplingFactor = quality, }; var texture = CurrentShownSpriteSheet.Texture; animatedGifEncoder.Transparent = Color.Black; foreach (var frame in CurrentShownAnimation.Frames) { Bitmap frameBitMap = texture.Surface.ToBitmap(frame.SpriteFrame.Region); GifFrame gifFrame = new GifFrame(frameBitMap); gifFrame.Delay = 100 * ((int)(frame.FrameDuration)); if (gifFrame.Delay < 1) { gifFrame.Delay = 1; } gifFrame.Position = new Point((int)((frameSize.Width / 2f - frame.SpriteFrame.Width / 2f) + frame.OffSetX), (int)((frameSize.Height / 2f - frame.SpriteFrame.Height / 2f) + frame.OffSetY)); animatedGifEncoder.AddFrame(gifFrame); } animatedGifEncoder.WriteToFile(path); animatedGifEncoder.Dispose(); } catch (Exception ex) { error = true; Messager.ShowMessage(Messager.Mode.Exception, string.Format("Error on exporting GIF: {0}", ex.Message)); Vortex.Debugging.Log.Error(ex, "Error on exporting GIF"); } finally { if (!error) { Messager.ShowMessage(Messager.Mode.Message, "GIF created successfully!"); } } } else { Messager.ShowMessage(Messager.Mode.Exception, "No animations to export!"); } }
/// <summary> /// Tests the AnimatedGifEncoder and the encoded GIF file it produces /// using the supplied parameters as property values. /// </summary> private void TestAnimatedGifEncoder( ColourTableStrategy strategy, int colourQuality, Size logicalScreenSize) { _e = new AnimatedGifEncoder(); // Check default properties set by constructor. Assert.AreEqual( ColourTableStrategy.UseGlobal, _e.ColourTableStrategy, "Colour table strategy set by constructor" ); Assert.AreEqual( 10, _e.SamplingFactor, "Colour quantization quality set by constructor" ); Assert.AreEqual( Size.Empty, _e.LogicalScreenSize, "Logical screen size set by constructor" ); _e.ColourTableStrategy = strategy; _e.SamplingFactor = colourQuality; _e.LogicalScreenSize = logicalScreenSize; // Check property set/gets Assert.AreEqual( strategy, _e.ColourTableStrategy, "Colour table strategy property set/get" ); Assert.AreEqual( colourQuality, _e.SamplingFactor, "Colour quantization quality property set/get" ); Assert.AreEqual( logicalScreenSize, _e.LogicalScreenSize, "Logical screen size property get/set" ); foreach( GifFrame thisFrame in _frames ) { _e.AddFrame( thisFrame ); } StackTrace t = new StackTrace(); StackFrame f = t.GetFrame( 1 ); string fileName = "Checks." + this.GetType().Name + "." + f.GetMethod().Name + ".gif"; _e.WriteToFile( fileName ); Stream s = File.OpenRead( fileName ); // global info CheckGifHeader( s ); bool shouldHaveGlobalColourTable = (strategy == ColourTableStrategy.UseGlobal); LogicalScreenDescriptor lsd = CheckLogicalScreenDescriptor( s, shouldHaveGlobalColourTable ); // Only check the global colour table if there should be one ColourTable gct = null; if( shouldHaveGlobalColourTable ) { gct = CheckColourTable( s, lsd.GlobalColourTableSize ); } CheckExtensionIntroducer( s ); CheckAppExtensionLabel( s ); CheckNetscapeExtension( s, 0 ); CheckFrame( s, gct, Bitmap1() ); CheckFrame( s, gct, Bitmap2() ); // end of image data CheckGifTrailer( s ); CheckEndOfStream( s ); s.Close(); // Check the file using the decoder _d = new GifDecoder( fileName ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState, "Decoder consolidated state" ); Assert.AreEqual( 2, _d.Frames.Count, "Decoder frame count" ); Assert.AreEqual( shouldHaveGlobalColourTable, _d.LogicalScreenDescriptor.HasGlobalColourTable, "Should have global colour table" ); Assert.AreEqual( logicalScreenSize, _d.LogicalScreenDescriptor.LogicalScreenSize, "Decoder logical screen size" ); BitmapAssert.AreEqual( Bitmap1(), (Bitmap) _d.Frames[0].TheImage, "frame 0" ); BitmapAssert.AreEqual( Bitmap2(), (Bitmap) _d.Frames[1].TheImage, "frame 1" ); bool shouldHaveLocalColourTable = !shouldHaveGlobalColourTable; Assert.AreEqual( shouldHaveLocalColourTable, _d.Frames[0].ImageDescriptor.HasLocalColourTable, "Frame 0 has local colour table" ); Assert.AreEqual( shouldHaveLocalColourTable, _d.Frames[1].ImageDescriptor.HasLocalColourTable, "Frame 0 has local colour table" ); }
public void BadEncodingUsingGameboyPaletteLocal() { ReportStart(); _e = new AnimatedGifEncoder(); _e.ColourTableStrategy = ColourTableStrategy.UseLocal; _e.QuantizerType = QuantizerType.UseSuppliedPalette; GifFrame frame = new GifFrame( Image.FromFile( @"images\smiley.bmp" ) ); _e.AddFrame( frame ); Assert.AreEqual( ColourTableStrategy.UseLocal, _e.ColourTableStrategy ); Assert.AreEqual( QuantizerType.UseSuppliedPalette, _e.QuantizerType ); frame.Palette = Palette.FromFile( @"ColourTables\gameboy.act" ); Assert.AreEqual( ColourTableStrategy.UseLocal, _e.ColourTableStrategy ); Assert.AreEqual( QuantizerType.UseSuppliedPalette, _e.QuantizerType ); _e.WriteToFile( GifFileName ); _d = new GifDecoder( GifFileName ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState ); ReportEnd(); }
public void WikipediaExampleTest() { ReportStart(); _e = new AnimatedGifEncoder(); GifFrame frame = new GifFrame( WikipediaExample.ExpectedBitmap ); frame.Delay = WikipediaExample.DelayTime; _e.AddFrame( frame ); // TODO: some way of creating/testing a UseLocal version of WikipediaExample string fileName = "WikipediaExampleUseGlobal.gif"; _e.WriteToFile( fileName ); Stream s = File.OpenRead( fileName ); int code; // check GIF header GifHeader gh = new GifHeader( s ); Assert.AreEqual( ErrorState.Ok, gh.ConsolidatedState ); // check logical screen descriptor LogicalScreenDescriptor lsd = new LogicalScreenDescriptor( s ); Assert.AreEqual( ErrorState.Ok, lsd.ConsolidatedState ); WikipediaExample.CheckLogicalScreenDescriptor( lsd ); // read global colour table ColourTable gct = new ColourTable( s, WikipediaExample.GlobalColourTableSize ); Assert.AreEqual( ErrorState.Ok, gct.ConsolidatedState ); // cannot compare global colour table as different encoders will // produce difference colour tables. // WikipediaExample.CheckGlobalColourTable( gct ); // check for extension introducer code = ExampleComponent.CallRead( s ); Assert.AreEqual( GifComponent.CodeExtensionIntroducer, code ); // check for app extension label code = ExampleComponent.CallRead( s ); Assert.AreEqual( GifComponent.CodeApplicationExtensionLabel, code ); // check netscape extension ApplicationExtension ae = new ApplicationExtension( s ); Assert.AreEqual( ErrorState.Ok, ae.ConsolidatedState ); NetscapeExtension ne = new NetscapeExtension( ae ); Assert.AreEqual( ErrorState.Ok, ne.ConsolidatedState ); Assert.AreEqual( 0, ne.LoopCount ); // check for extension introducer code = ExampleComponent.CallRead( s ); Assert.AreEqual( GifComponent.CodeExtensionIntroducer, code ); // check for gce label code = ExampleComponent.CallRead( s ); Assert.AreEqual( GifComponent.CodeGraphicControlLabel, code ); // check graphic control extension GraphicControlExtension gce = new GraphicControlExtension( s ); Assert.AreEqual( ErrorState.Ok, gce.ConsolidatedState ); WikipediaExample.CheckGraphicControlExtension( gce ); // check for image separator code = ExampleComponent.CallRead( s ); Assert.AreEqual( GifComponent.CodeImageSeparator, code ); // check for image descriptor ImageDescriptor id = new ImageDescriptor( s ); Assert.AreEqual( ErrorState.Ok, id.ConsolidatedState ); WikipediaExample.CheckImageDescriptor( id ); // read, decode and check image data // Cannot compare encoded LZW data directly as different encoders // will create different colour tables, so even if the bitmaps are // identical, the colour indices will be different int pixelCount = WikipediaExample.FrameSize.Width * WikipediaExample.FrameSize.Height; TableBasedImageData tbid = new TableBasedImageData( s, pixelCount ); for( int y = 0; y < WikipediaExample.LogicalScreenSize.Height; y++ ) { for( int x = 0; x < WikipediaExample.LogicalScreenSize.Width; x++ ) { int i = (y * WikipediaExample.LogicalScreenSize.Width) + x; Assert.AreEqual( WikipediaExample.ExpectedBitmap.GetPixel( x, y ), gct[tbid.Pixels[i]], "X: " + x + ", Y: " + y ); } } // Check for block terminator after image data code = ExampleComponent.CallRead( s ); Assert.AreEqual( 0x00, code ); // check for GIF trailer code = ExampleComponent.CallRead( s ); Assert.AreEqual( GifComponent.CodeTrailer, code ); // check we're at the end of the stream code = ExampleComponent.CallRead( s ); Assert.AreEqual( -1, code ); s.Close(); _d = new GifDecoder( fileName ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState ); BitmapAssert.AreEqual( WikipediaExample.ExpectedBitmap, (Bitmap) _d.Frames[0].TheImage, "" ); ReportEnd(); }
public void CompareQuantizers() { ReportStart(); string fileName; DateTime startTime; DateTime endTime; TimeSpan encodingTime; // Test actual quantization using image with 256+ colours. string bitmapFileName = "images/" + TestFixtureName + "." + TestCaseName + ".bmp"; Bitmap b = new Bitmap( bitmapFileName ); for( int q = 1; q <= 20; q++ ) { _e = new AnimatedGifEncoder(); _e.QuantizerType = QuantizerType.NeuQuant; _e.SamplingFactor = q; _e.AddFrame( new GifFrame( b ) ); fileName = TestFixtureName + "." + TestCaseName + ".NeuQuant." + q + ".gif"; startTime = DateTime.Now; _e.WriteToFile( fileName ); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage( "Encoding with quantization using NeuQuant, quality=" + q + " took " + encodingTime ); _d = new GifDecoder( fileName ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState, "Quality " + q ); Assert.AreEqual( 1, _d.Frames.Count, "Quality " + q ); // FIXME: NeuQuant quantizer reducing to 180 colours instead of 256 colours // TODO: Check for exactly 256 colours once Octree quantizer returns 256-colour images // Assert.AreEqual( 256, ImageTools.GetDistinctColours( colours ).Count ); Assert.LessOrEqual( ImageTools.GetDistinctColours( _d.Frames[0].TheImage ).Count, 256 ); for( int tolerance = 0; tolerance < 256; tolerance++ ) { try { ImageAssert.AreEqual( b, _d.Frames[0].TheImage, tolerance, "Quality " + q ); WriteMessage( "Quality " + q + " required tolerance " + tolerance ); break; } catch( AssertionExtensionException ) { if( tolerance == 255 ) { throw; } } } } _e = new AnimatedGifEncoder(); _e.QuantizerType = QuantizerType.Octree; _e.AddFrame( new GifFrame( b ) ); fileName = TestFixtureName + "." + TestCaseName + ".Octree.gif"; startTime = DateTime.Now; _e.WriteToFile( fileName ); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage( "Encoding with quantization using Octree took " + encodingTime ); _d = new GifDecoder( fileName ); _d.Decode(); Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState ); Assert.AreEqual( 1, _d.Frames.Count ); // FIXME: Octree quantizer should return a 256-colour image here // Assert.AreEqual( 256, ImageTools.GetDistinctColours( colours2 ).Count ); Assert.LessOrEqual( ImageTools.GetDistinctColours( _d.Frames[0].TheImage ).Count, 256 ); for( int tolerance = 0; tolerance < 256; tolerance++ ) { try { ImageAssert.AreEqual( b, _d.Frames[0].TheImage, tolerance, "Octree" ); WriteMessage( "Octree quantization required tolerance " + tolerance ); break; } catch( AssertionExtensionException ) { if( tolerance == 255 ) { throw; } } } // re-encoding an existing GIF should not cause quantization _d = new GifDecoder( @"images\globe\spinning globe better 200px transparent background.gif" ); _d.Decode(); _e = new AnimatedGifEncoder(); // NB OctreeQuantizer does not support global colour tables (yet!) _e.ColourTableStrategy = ColourTableStrategy.UseLocal; foreach( GifFrame f in _d.Frames ) { _e.AddFrame( new GifFrame( f.TheImage ) ); } fileName = "NeuQuant.gif"; _e.QuantizerType = QuantizerType.NeuQuant; startTime = DateTime.Now; _e.WriteToFile( fileName ); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage( "Encoding without quantization using NeuQuant took " + encodingTime ); fileName = "Octree.gif"; _e.QuantizerType = QuantizerType.Octree; startTime = DateTime.Now; _e.WriteToFile( fileName ); endTime = DateTime.Now; encodingTime = endTime - startTime; WriteMessage( "Encoding without quantization using Octree took " + encodingTime ); GifDecoder nqDecoder = new GifDecoder( "NeuQuant.gif" ); nqDecoder.Decode(); GifDecoder otDecoder = new GifDecoder( "Octree.gif" ); otDecoder.Decode(); Assert.AreEqual( nqDecoder.Frames.Count, otDecoder.Frames.Count ); for( int i = 0; i < nqDecoder.Frames.Count; i++ ) { ImageAssert.AreEqual( nqDecoder.Frames[i].TheImage, otDecoder.Frames[i].TheImage, "frame " + i ); } ReportEnd(); }
private void EncodeBigFile() { _encoder.WriteToFile("Profile.gif"); }
public void TransparencyTest() { ReportStart(); Color noColour = Color.FromArgb( 0, 0, 0, 0 ); // note alpha of 0 Color blue = Color.FromArgb( 0, 0, 255 ); Color transparent = Color.FromArgb( 100, 100, 100 ); _encoder = new AnimatedGifEncoder(); _encoder.Transparent = transparent; // transparent | transparent // ------------------------- // blue | blue Bitmap bitmap = new Bitmap( 2, 2 ); bitmap.SetPixel( 0, 0, transparent ); bitmap.SetPixel( 1, 0, transparent ); bitmap.SetPixel( 0, 1, blue ); bitmap.SetPixel( 1, 1, blue ); _frame = new GifFrame( bitmap ); _encoder.AddFrame( _frame ); // encode and decode string filename = "GifFrameTest.TransparencyTest.gif"; _encoder.WriteToFile( filename ); _decoder = new GifDecoder( filename ); _decoder.Decode(); Assert.AreEqual( ErrorState.Ok, _decoder.ConsolidatedState ); // Result should be: // black | black // ------------- // blue | blue Bitmap actual = (Bitmap) _decoder.Frames[0].TheImage; Assert.AreEqual( noColour, actual.GetPixel( 0, 0 ) ); Assert.AreEqual( noColour, actual.GetPixel( 1, 0 ) ); Assert.AreEqual( blue, actual.GetPixel( 0, 1 ) ); Assert.AreEqual( blue, actual.GetPixel( 1, 1 ) ); ReportEnd(); }
public void Bug2892015() { ReportStart(); _e = new AnimatedGifEncoder(); #region create 10 random bitmaps Collection <Bitmap> bitmaps = new Collection <Bitmap>(); for (int i = 0; i < 10; i++) { Bitmap bitmap = RandomBitmap.Create(new Size(50, 50), 10, PixelFormat.Format32bppRgb); bitmaps.Add(bitmap); } #endregion DateTime startTime; DateTime endTime; #region create animation using just the first 3 (this should be quick) for (int i = 0; i < 3; i++) { _e.AddFrame(new GifFrame(bitmaps[i])); } startTime = DateTime.Now; _e.WriteToFile("2892015-1.gif"); endTime = DateTime.Now; TimeSpan runTime1 = endTime - startTime; WriteMessage("Encoding 3 frames took " + runTime1); #endregion _e.Frames.Clear(); #region create animation using all the bitmaps (this will take longer) foreach (Bitmap bitmap in bitmaps) { _e.AddFrame(new GifFrame(bitmap)); } startTime = DateTime.Now; _e.WriteToFile("2892015-2.gif"); endTime = DateTime.Now; TimeSpan runTime2 = endTime - startTime; WriteMessage("Encoding all " + bitmaps.Count + " frames took " + runTime2); #endregion _e.Frames.Clear(); #region create animation using just the first 3 (this should be quick) for (int i = 0; i < 3; i++) { _e.AddFrame(new GifFrame(bitmaps[i])); } startTime = DateTime.Now; _e.WriteToFile("2892015-3.gif"); endTime = DateTime.Now; TimeSpan runTime3 = endTime - startTime; WriteMessage("Encoding 3 frames took " + runTime3); #endregion Assert.IsTrue(runTime3 < runTime2); _d = new GifDecoder("2892015-3.gif"); _d.Decode(); Assert.AreEqual(3, _d.Frames.Count); ReportEnd(); }
private void TryDifferentPixelFormats() { Size size = new Size( 50, 50 ); int blockiness = 10; PixelFormat[] pixelFormats = new PixelFormat[] { PixelFormat.Format16bppArgb1555, PixelFormat.Format16bppRgb555, PixelFormat.Format16bppRgb565, PixelFormat.Format24bppRgb, PixelFormat.Format32bppArgb, PixelFormat.Format32bppPArgb, PixelFormat.Format32bppRgb, PixelFormat.Format48bppRgb, PixelFormat.Format64bppArgb, PixelFormat.Format64bppPArgb, }; foreach( PixelFormat pf in pixelFormats ) { string formatName = pf.ToString(); _encoder = new AnimatedGifEncoder(); for( int i = 0; i < 10; i++ ) { Bitmap bitmap = RandomBitmap.Create( size, blockiness, pf ); _encoder.AddFrame( new GifFrame( bitmap ) ); } DateTime startTime = DateTime.Now; _encoder.WriteToFile( formatName + ".gif" ); DateTime endTime = DateTime.Now; TimeSpan timeToEncode8bit = endTime - startTime; WriteMessage( "Encoding " + formatName + " took " + timeToEncode8bit ); } }