The GIF file format is the most wide-spread graphic format that supports animation. Animated images saved in this format can be rendered by almost any modern image viewer. Graphics Mill for .NET provides some means to work with animated GIFs.
Two most typical tasks for which Graphics Mill for .NET may be helpful are:
In order to work with GIF files using Graphics Mill for .NET, you need to know how to deal with its readers and writers. The readers and writers are objects that actually perform reading and writing (respectively) of some media files. There are special readers and writers for each format, for example, for the GIF format they are Aurigma.GraphicsMill.Codecs.GifReader and Aurigma.GraphicsMill.Codecs.GifWriter.
Usage of the reader can be descibed by the following sequence of steps:
And usage of the writer can be descibed by the following sequence of steps:
Below is a short example of using a GIF reader and a GIF writer.
'Create and open a reader and a writer Dim reader As New Aurigma.GraphicsMill.Codecs.GifReader("D:\wolf.gif") Dim writer As New Aurigma.GraphicsMill.Codecs.GifWriter("D:\Copy of wolf.gif") 'Set writer properties writer.BackgroundEntryIndex = reader.BackgroundEntryIndex writer.GlobalPalette = reader.GlobalPalette writer.PlaybackCount = reader.PlaybackCount writer.Optimized = True For i As Integer = 0 To reader.FrameCount - 1 'Load a successive frame Dim frame As Aurigma.GraphicsMill.Codecs.GifFrame = _ CType(reader.LoadFrame(i), Aurigma.GraphicsMill.Codecs.GifFrame) '...Proccess the frame, if required... 'Save the frame writer.AddFrame(frame) frame.Dispose() Next i 'Close the reader and the writer writer.Close() reader.Close()
//Create and open a reader and a writer Aurigma.GraphicsMill.Codecs.GifReader reader = new Aurigma.GraphicsMill.Codecs.GifReader(@"D:\wolf.gif"); Aurigma.GraphicsMill.Codecs.GifWriter writer = new Aurigma.GraphicsMill.Codecs.GifWriter(@"D:\Copy of wolf.gif"); //Set writer properties writer.BackgroundEntryIndex = reader.BackgroundEntryIndex; writer.GlobalPalette = reader.GlobalPalette; writer.PlaybackCount = reader.PlaybackCount; writer.Optimized = true; for (int i = 0; i <= reader.FrameCount - 1; i++) { //Load a successive frame Aurigma.GraphicsMill.Codecs.GifFrame frame = (Aurigma.GraphicsMill.Codecs.GifFrame)reader.LoadFrame(i); //...Proccess the frame, if required... //Save the frame writer.AddFrame(frame); frame.Dispose(); } //Close the reader and the writer writer.Close(); reader.Close();
When you create an animated GIF file, most likely, you will want to make it as small by file size as possible while having a sufficient quality. That is when the optimization means of Graphics Mill for .NET come in handy.
Graphics Mill for .NET uses three ways to optimize an animated GIF file:
To enable these optimization methods you only need to set the GifWriter.Optimized property to true
.
However, there is a catch. To build a global palette, Graphics Mill for .NET
should load all frames, for which the palette is built, into memory. According to the GIF format
specification, no frames will actually be written into a file, until the global palette is created,
therefore, the frames will be saved into memory. Naturally, if there are too many frames, the writer
will consume too much memory. To avoid this, specify a threshold for the number of frames to build a
global palette for. So, if you know that the final image will contain a lot of frames, and they will
not introduce new colors, you may also wish to set the GifWriter.BasisOptimizationFrameCount property.
Another way to stop gathering statistics for the global palette is to set the GifFrame.LastFrame to true
when
you reach the frame where you would like to stop. This may be useful if know that after some frame
no more colors will be added. If you set this property, the value of the GifWriter.BasisOptimizationFrameCount property will be ignored.
If frames are added after the global palette is generated, and colors used in those frames are the same as in the global palette, Graphics Mill for .NET will automatically use the global palette. However, if at least one color will not be in the global palette, the frame will be saved with a local palette.
Here is an example of creating an optimized sequence of frames.
Dim folder As String = "C:\Documents and Settings\All Users\Documents\My " & _ "Pictures\Sample Pictures\" Dim images() As String = New String() {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg"} Dim bitmap As New Aurigma.GraphicsMill.Bitmap() Dim writer As New Aurigma.GraphicsMill.Codecs.GifWriter("D:\slideshow.gif") 'Use optimization writer.Optimized = True For Each image As String In images bitmap.Load(folder & image) 'Convert the bitmap to an indexed format bitmap.ColorManagement.ConvertToIndexed(8, _ Aurigma.GraphicsMill.ColorPaletteType.Adaptive, Nothing) 'Save the frame Dim frame As New Aurigma.GraphicsMill.Codecs.GifFrame frame.Delay = 100 frame.SetBitmap(bitmap) writer.AddFrame(frame) frame.Dispose() Next image writer.Dispose() bitmap.Dispose()
string folder = @"C:\Documents and Settings\All Users\Documents\My " + @"Pictures\Sample Pictures"; string[] images = {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg"}; Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); Aurigma.GraphicsMill.Codecs.GifWriter writer = new Aurigma.GraphicsMill.Codecs.GifWriter(@"D:\slideshow.gif"); //Use optimization writer.Optimized = true; foreach (string image in images) { bitmap.Load(folder + image); //Convert the bitmap to an indexed format bitmap.ColorManagement.ConvertToIndexed(8, Aurigma.GraphicsMill.ColorPaletteType.Adaptive, null); //Save the frame Aurigma.GraphicsMill.Codecs.GifFrame frame = new Aurigma.GraphicsMill.Codecs.GifFrame(); frame.Delay = 100; frame.SetBitmap(bitmap); writer.AddFrame(frame); frame.Dispose(); } writer.Dispose(); bitmap.Dispose();
Suppose, you need to resize an existing animated GIF file. To do that you will need to read the image frame by frame, and while for each frame perform the following:
Here is an example implementation of the above algorithm that scales down an animated GIF.
Dim reader As New Aurigma.GraphicsMill.Codecs.GifReader("D:\wolf.gif") Dim writer As New Aurigma.GraphicsMill.Codecs.GifWriter("D:\big_wolf.gif") writer.Optimized = True 'Copy general properties of the source file writer.BackgroundEntryIndex = reader.BackgroundEntryIndex writer.GlobalPalette = reader.GlobalPalette writer.PlaybackCount = reader.PlaybackCount Dim bitmap As New Aurigma.GraphicsMill.Bitmap() For i As Integer = 0 To reader.FrameCount - 1 'Read a successive frame Dim frame As Aurigma.GraphicsMill.Codecs.GifFrame = _ CType(reader.LoadFrame(i), Aurigma.GraphicsMill.Codecs.GifFrame) frame.GetBitmap(bitmap) 'Preserve the original palette Dim palette As Aurigma.GraphicsMill.ColorPalette = bitmap.Palette 'Resize the bitmap in a high quality mode bitmap.Transforms.Resize(frame.Width \ 2, frame.Height \ 2, _ Aurigma.GraphicsMill.Transforms.ResizeMode.Resize, _ Aurigma.GraphicsMill.Transforms.InterpolationMode.HighQuality) 'Return to the indexed format bitmap.ColorManagement.PaletteAlphaThreshold = 127 bitmap.ColorManagement.ConvertToIndexed(frame.BitsPerPixel, _ Aurigma.GraphicsMill.ColorPaletteType.Custom, palette) 'Save the frame frame.SetBitmap(bitmap) frame.Top = frame.Top \ 2 frame.Left = frame.Left \ 2 writer.AddFrame(frame) frame.Dispose() Next i writer.Dispose() reader.Dispose() bitmap.Dispose()
Aurigma.GraphicsMill.Codecs.GifReader reader = new Aurigma.GraphicsMill.Codecs.GifReader(@"D:\wolf.gif"); Aurigma.GraphicsMill.Codecs.GifWriter writer = new Aurigma.GraphicsMill.Codecs.GifWriter(@"D:\big_wolf.gif"); writer.Optimized = true; //Copy general properties of the source file writer.BackgroundEntryIndex = reader.BackgroundEntryIndex; writer.GlobalPalette = reader.GlobalPalette; writer.PlaybackCount = reader.PlaybackCount; Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); for (int i = 0; i <= reader.FrameCount - 1; i++) { //Read a successive frame Aurigma.GraphicsMill.Codecs.GifFrame frame = (Aurigma.GraphicsMill.Codecs.GifFrame)reader.LoadFrame(i); frame.GetBitmap(bitmap); //Preserve the original palette Aurigma.GraphicsMill.ColorPalette palette = bitmap.Palette; //Resize the bitmap in a high quality mode bitmap.Transforms.Resize(frame.Width / 2, frame.Height / 2, Aurigma.GraphicsMill.Transforms.ResizeMode.Resize, Aurigma.GraphicsMill.Transforms.InterpolationMode.HighQuality); //Return to the indexed format bitmap.ColorManagement.PaletteAlphaThreshold = 127; bitmap.ColorManagement.ConvertToIndexed(frame.BitsPerPixel, Aurigma.GraphicsMill.ColorPaletteType.Custom, palette); //Save the frame frame.SetBitmap(bitmap); frame.Top = frame.Top / 2; frame.Left = frame.Left / 2; writer.AddFrame(frame); frame.Dispose(); } writer.Dispose(); reader.Dispose(); bitmap.Dispose();