|
|
 |
9.1 GIF Format Overview
9.2 AspJpeg.NET's GIF Output Support
9.3 GIF Image Resizing
9.4 Using External Images as Frames
9.5 Palette Management
9.6 Transparency
9.7 Miscellaneous Features
Introduced by CompuServe in 1987, Graphics Interchange Format (GIF, pronounced Jiff)
is widely used on the Web for sharp-edged images with a limited number of colors,
such as navigation buttons, logos, graphs, charts and icons.
GIF is based on LZW, a lossless compression algorithm ideally suited for simple graphics
(but not photographs.)
A GIF image can contain up to 256 distinct colors from the 24-bit color set.
Pixel colors in a GIF image are numbers between 0 and 255 which are indices to a color palette
included with the image.
Any pixel of a GIF image can be assigned a "transparent", or see-through, color.
This enables GIF images to take arbitrary shapes when appearing on a web page.
GIF is the only widely used graphics format that supports animation. A GIF image can contain
multiple frames that are displayed one after another as a movie.
To reduce overall image size, some frames are often made smaller than the image itself,
and are displayed at an offset to only affect those portions of the image that need redrawing.
AspJpeg.NET's GIF functionality is encapsulated in the JpegGif object
which provides a wide range of operations on GIF images. An instance of this object
is obtained via the JpegManager.Gif property. The JpegGif object is completely autonomous, i.e. it is not
affected by AspJpeg.NET's other properties and methods.
A simple GIF image is created by calling the JpegGif.AddFrame method followed by some drawing
routines, and saved via the Save method. Other saving routines available
in the JpegImage object (SaveUnique, SendBinary and Binary) are supported by the JpegGif object as well.
AddFrame requires 4 arguments: frame width and height,
and horizontal and vertical offsets. For a single-frame image, the offset arguments are usually 0.
Most properties and methods of the JpegGif object operate on the current frame.
Once a new frame is added, it becomes the current one.
Another frame can be set current by setting the JpegGif.CurrentFrame property to the 1-based index
of the desired frame. The total number of frames is returned via JpegGif.FrameCount. A frame can be removed
via JpegGif.RemoveFrame.
The JpegGif object supports most of the drawing routines the JpegCanvas object supports,
such as PrintText, DrawLine, etc. Setting various drawing properties
is somewhat streamlined compared to the Canvas object. For example, an equivalent of JpegImage.Canvas.Pen.Color is simply JpegGif.PenColor.
Colors in the JpegGif object are always numbers in the range 0 to 255
which are indices within the current palette. Palette management is described in Section 9.5 below.
The following code sample creates a simple animated 5-frame drawing with some text and a pie chart:
C# |
<%@ Page Language="C#" debug="true" %>
<%@ Import Namespace="Persits.Jpeg"%>
<html>
<head>
<title>AspJpeg.NET User Manual Chapter 9 - GIF Animation</title>
<script runat="server" languge="C#">
void Page_Load( Object Source, EventArgs E)
{
JpegManager objJpeg = new JpegManager();
// Obtain GIF management object
JpegGif objGif = objJpeg.Gif;
// Font path
string strFont = objJpeg.WindowsDirectory + @"\Fonts\Cour.ttf";
// initial market share of hypothetical XYZ company
int nMarketShare = 6;
// create a 5-frame animated gif
for (int i = 1; i <= 5; i++)
{
objGif.AddFrame(300, 200, 0, 0);
objGif.PenColor = 10;
objGif.BrushColor = 10;
objGif.FillRect(0, 0, 300, 200);
objGif.PenColor = 201;
objGif.FontSize = 20;
objGif.PrintText("XYZ, Inc. Market Share", 18, 20, strFont);
objGif.PrintText((2010 + i).ToString(), 120, 50, strFont);
// Draw pie chart
objGif.PenColor = 0;
objGif.BrushColor = 30;
objGif.FillSegment(150, 130, 50, 50, 0, nMarketShare*360/100, 0);
objGif.BrushColor = 20;
objGif.FillSegment(150, 130, 50, 50, nMarketShare*360/100, 360, 0);
objGif.PenColor = 210;
objGif.PrintText(nMarketShare.ToString() + "%", 200, 100, strFont);
// market share almost doubles every year!
nMarketShare = nMarketShare * 2 - 3;
// increase delay on the last frame
if (i == 5)
objGif.Delay = 300; // 3 sec
}
// Save
string strFilename = objGif.SaveUnique(Server.MapPath("chart.gif"));
OutputImage.ImageUrl = strFilename;
}
</script>
</head>
<form runat="server">
<asp:image runat="server" id="OutputImage"/>
</form>
</html>
|
VB.NET |
<%@ Page Language="vb" debug="true" %>
<%@ Import Namespace="Persits.Jpeg"%>
<html>
<head>
<title>AspJpeg.NET User Manual Chapter 9 - GIF Animation</title>
<script runat="server" languge="vb">
Sub Page_Load(Source As Object, E As EventArgs)
Dim objJpeg As JpegManager = New JpegManager()
' Obtain GIF management object
Dim objGif As JpegGif = objJpeg.Gif
' Font path
Dim strFont As String = objJpeg.WindowsDirectory + "\Fonts\Cour.ttf"
' initial market share of hypothetical XYZ company
Dim nMarketShare As Integer = 6
' create a 5-frame animated gif
For i As Integer = 1 To 5
objGif.AddFrame(300, 200, 0, 0)
objGif.PenColor = 10
objGif.BrushColor = 10
objGif.FillRect(0, 0, 300, 200)
objGif.PenColor = 201
objGif.FontSize = 20
objGif.PrintText("XYZ, Inc. Market Share", 18, 20, strFont)
objGif.PrintText((2010 + i).ToString(), 120, 50, strFont)
' Draw pie chart
objGif.PenColor = 0
objGif.BrushColor = 30
objGif.FillSegment(150, 130, 50, 50, 0, nMarketShare*360/100, 0)
objGif.BrushColor = 20
objGif.FillSegment(150, 130, 50, 50, nMarketShare*360/100, 360, 0)
objGif.PenColor = 210
objGif.PrintText(nMarketShare.ToString() + "%", 200, 100, strFont)
' market share almost doubles every year!
nMarketShare = nMarketShare * 2 - 3
' increase delay on the last frame
If i = 5 Then objGif.Delay = 300 ' 3 sec
Next
' Save
Dim strFilename As String =
objGif.SaveUnique(Server.MapPath("chart.gif"))
OutputImage.ImageUrl = strFilename
End Sub
</script>
</head>
<form runat="server">
<asp:image runat="server" id="OutputImage"/>
</form>
</html>
|
Click the links below to run this code sample:
http://localhost/aspjpeg.net/manual_09/09_animation.cs.aspx
http://localhost/aspjpeg.net/manual_09/09_animation.vb.aspx
The JpegGif object is capable of resizing animated GIF images while preserving their animation and transparency.
Resizing is performed via the JpegGif.Resize image which
accepts three arguments, 2 required and 1 optional: new width, new height and a resizing algorithm.
The resizing algorithm is 0 (nearest-neighbor) by default.
More information about the resizing algorithms supported by AspJpeg.NET
is available here.
Original Image | Resized Image |
 |  |
The resized image above on the right was generated using the following code:
C# |
...
// Image path
string strPath = Server.MapPath(@"..\images\WalkingCat.gif");
// Open and resize by 50%
objGif.Open(strPath);
objGif.Resize(objGif.Width / 2, objGif.Height / 2);
...
|
VB.NET |
...
' Open and resize by 50%
objGif.Open(strPath)
objGif.Resize(objGif.Width / 2, objGif.Height / 2)
' Save
Dim strFilename =
objGif.SaveUnique(Server.MapPath("WalkingCat_small.gif"))
...
|
Click the links below to run this code sample:
http://localhost/aspjpeg.net/manual_09/09_resize.cs.aspx
http://localhost/aspjpeg.net/manual_09/09_resize.vb.aspx
Note that the file size of a resized animated image may be larger that the original image even though the pixel
size is smaller (as in this example.) Also note that the 3rd argument to the Resize method (resizing algorithm)
can be set to 1 to create higher-quality thumbnails, but some animated images may produce
undesired "artifacts" in that case.
The Gif object is capable of converting RGB images such as JPEGs into 256-colors GIFs
with only a minor loss in image quality. An arbitrary existing image can be added to a GIF as a new frame via
the Gif.AddImage method. This method expects a populated instance of the JpegImage object as the first
argument, and (X, Y)-offsets of this new frame within the GIF image being created.
You must perform all desired operations over the JpegImage object (resizing, cropping, drawing, etc.)
before passing it to the AddImage method. The image being added must be in the RGB color space.
The following snippet resizes a JPEG image and converts it to a single-frame GIF:
VB Script:
JpegManager objJpeg = new JpegManager();
JpegGif objGif = objJpeg.Gif;
JpegImage objImage = objJpeg.OpenImage(@"c:\path\image.jpg");
objImage.PreserveAspectRatio = true;
objImage.Width = 200;
objGif.AddImage(objImage, 0, 0);
// Save
objGif.SaveUnique(@"c:\path\out.gif");
Because of the loss of quality and larger file size, converting a JPEG photograph to GIF
is not beneficial, unless other GIF features are used, such as animation.
The code sample of Section 6.1
generates an image containing the thumbnails of several photographs
shown side by side. Let's rewrite
this application to generate an animated GIF showing the thumbnails in rotation instead:
C# |
<%@ Page Language="C#" debug="true" %>
<%@ Import Namespace="Persits.Jpeg"%>
<html>
<head>
<title>AspJpeg.NET User Manual Chapter 9 - Images as Frames</title>
<script runat="server" languge="C#">
void Page_Load( Object Source, EventArgs E)
{
JpegManager objJpeg = new JpegManager();
// Obtain GIF management object
JpegGif objGif = objJpeg.Gif;
// Read images from Images directory of the installation
string [] arrFileNames = new string[3];
arrFileNames[0] = "apple.jpg";
arrFileNames[1] = "clock.jpg";
arrFileNames[2] = "photo.jpg";
string strPath = Server.MapPath("../images");
// Stipulate output image size
objGif.Width = 100;
objGif.Height = 100;
for( int i = 0; i < 3; i++ )
{
JpegImage objImage =
objJpeg.OpenImage( strPath + "\\" + arrFileNames[i] );
// Resize to inscribe in 100x100 square
objImage.PreserveAspectRatio = true;
if(objImage.OriginalWidth > 100 || objImage.OriginalHeight > 100)
{
if( objImage.OriginalWidth > objImage.OriginalHeight )
objImage.Width = 100;
else
objImage.Height = 100;
}
objGif.AddImage( objImage,
(100 - objImage.Width) / 2, (100 - objImage.Height) / 2 );
objGif.DisposalMethod = 2;
}
// Save
string strFilename = objGif.SaveUnique(Server.MapPath("picture.gif"));
OutputImage.ImageUrl = strFilename;
}
</script>
</head>
<form runat="server">
<asp:image runat="server" id="OutputImage"/>
</form>
</html>
|
VB.NET |
<%@ Page Language="vb" debug="true" %>
<%@ Import Namespace="Persits.Jpeg"%>
<html>
<head>
<title>AspJpeg.NET User Manual Chapter 9 - Images as Frames</title>
<script runat="server" languge="vb">
Sub Page_Load(Source As Object, E As EventArgs)
Dim objJpeg As JpegManager = New JpegManager()
' Obtain GIF management object
Dim objGif As JpegGif = objJpeg.Gif
' Read images from Images directory of the installation
Dim arrFileNames(3) As String
arrFileNames(0) = "apple.jpg"
arrFileNames(1) = "clock.jpg"
arrFileNames(2) = "photo.jpg"
Dim strPath As String = Server.MapPath("../images")
' Stipulate output image size
objGif.Width = 100
objGif.Height = 100
For i As Integer = 0 To 2
Dim objImage As JpegImage =
objJpeg.OpenImage( strPath + "\\" + arrFileNames(i) )
' Resize to inscribe in 100x100 square
objImage.PreserveAspectRatio = true
if objImage.OriginalWidth>100 Or objImage.OriginalHeight>100 Then
If objImage.OriginalWidth > objImage.OriginalHeight Then
objImage.Width = 100
Else
objImage.Height = 100
End If
End If
objGif.AddImage( objImage,
(100 - objImage.Width) / 2, (100 - objImage.Height) / 2 )
objGif.DisposalMethod = 2
Next
' Save
Dim strFilename =
objGif.SaveUnique(Server.MapPath("picture.gif"))
OutputImage.ImageUrl = strFilename
End Sub
</script>
</head>
<form runat="server">
<asp:image runat="server" id="OutputImage"/>
</form>
</html>
|
Click the links below to run this code sample:
http://localhost/aspjpeg.net/manual_09/09_rotation.cs.aspx
http://localhost/aspjpeg.net/manual_09/09_rotation.vb.aspx
Note that the overall GIF image size is dictated by the size of the first frame added,
unless we explicitly specify it via JpegGif.Width and JpegGif.Height properties.
In this application, we want the image to always be 100 x 100 regardless of the size
and orientation of the thumbnails being added. Therefore, we have to explicitly
specify the image size.
Note also that we set the DisposalMethod for each frame to 2, which means
the canvas should be restored to the background color before the next frame is drawn.
This property is 1 by default which means the previous frame needs to be left in place
and the next frame is to be drawn on top of it. In our application, the default behavior
is undesirable since all thumbnails are different sizes.
Converting true-color to 256-color images is a fairly complex process usually
referred to as quantization. The speed and quality of the conversion
is controlled by the property JpegGif.Quantization. Valid values for this property
are 1 to 30, 1 being highest quality and slowest speed. The default value of 20 provides
a reasonably good trade-off between quality and speed.
9.5.1 GIF Palette Overview
GIF is an indexed color format. Each pixel color is specified via an index
pointing to an RGB entry in a palette.
Each GIF image contains at least one palette. Usually, there is a single global palette
which applies to each frame of the image. In some cases, a frame has its own local palette
which takes precedence over the global palette within that frame but does not apply to any other frames.
If each frame has its own local palette, a global palette is usually not present at all.
GIF format requires that a palette contain 2, 4, 8, 16, 32, 64, 128, or 256 colors.
Each color entry in a palette contains exactly three bytes: the R, G, and B values.
9.5.2 Accessing and Modifying Palettes
The JpegGif object offers a number of properties and methods to access and modify
the global and local palettes of an image.
To specify an entire palette (global or local) in a single step, the SetPalette
method should be used. This method expects a Boolean flag indicating
whether the palette is global (true) or local (false), and a byte
array of numbers specifying the RGB values of the entire palette. The array must contain
a valid number of colors (2, 4, 8, etc.) multiplied by 3. If the first argument is false (indicating
a local palette) the image must already contain at least one frame, and
the palette pertaining to the current frame will be affected.
The following code snippet sets the global palette to contain 4 colors: black (0, 0, 0), white (255, 255, 255),
green (0, 255, 0) and yellow (255, 255, 0):
C# |
...
byte[] Colors = new byte[] { 0, 0, 0,
255, 255, 255,
0, 255, 0,
255, 255, 255 };
objGif.SetPalette(true, Colors);
...
|
VB.NET |
...
Dim Colors() as Byte = { 0, 0, 0,
255, 255, 255,
0, 255, 0,
255, 255, 0}
objGif.SetPalette(True, Colors)
...
|
To set or obtain the size of a palette, use the methods SetPaletteSize and GetPaletteSize, respectively.
These methods expect the same global/local
flag as the SetPalette method as the first argument. SetPaletteSize also expects the palette size as the 2nd argument.
GetPaletteSize returns the palette size.
The size of a palette is the number of colors, not the
total number of color components. Valid values are 2, 4, 8, ..., 256. Setting this property to 0 effectively
removes the palette entirely. For example:
C# |
...
objGif.SetPaletteSize(false, 256);
int N = objGif.GetPaletteSize( false );
...
|
VB.NET |
...
objGif.SetPaletteSize(False, 256)
Dim N As Integer = objGif.GetPaletteSize( False )
...
|
To set or get an individual color component of a palette, use the methods SetPaletteItem and GetPaletteItem.
Both expect the the global/local flag as the first argument. The 2nd argument is the address (0-based) of the desired color
component within the palette. The three RGB components of the 1st color have the addresses 0, 1 and 2, the 2nd color
-- 3, 4, and 5, etc. The address parameter must be in the range [0, GetPaletteSize() * 3 - 1].
The 3rd argument of SetPaletteItem is the value for the specified color component to be set to.
GetPaletteItem returns the value for the specified color component.
9.5.3 Stock Palettes
The JpegGif object enables you to specify one of several built-in palettes via the SetStockPalette
method. This method expects two arguments: the global/local flag, and the palette number.
Currently, 3 stock palettes are available:
Palette #1: Web-safe colors (default palette, 216 actual colors, 40 reserved slots);
Palette #2: Standard HTML colors (16 colors);
Palette #3: Grayscale colors (256 colors).
Palette #1 is the default global palette in all new images created with the JpegGif object.
This palette contains the standard Web-safe colors as described in the HTML specifications.
There are 216 standard Web-safe colors, and the indices 216 to 255 are not used and set to black.
These unused slots can be set to any arbitrary colors, if necessary.
The standard Web-safe color palette looks as follows:
| 0 | 1 | 2 | 3 | 4 | 5 |
0 |
000000 |
000033 |
000066 |
000099 |
0000CC |
0000FF |
6 |
003300 |
003333 |
003366 |
003399 |
0033CC |
0033FF |
12 |
006600 |
006633 |
006666 |
006699 |
0066CC |
0066FF |
18 |
009900 |
009933 |
009966 |
009999 |
0099CC |
0099FF |
24 |
00CC00 |
00CC33 |
00CC66 |
00CC99 |
00CCCC |
00CCFF |
30 |
00FF00 |
00FF33 |
00FF66 |
00FF99 |
00FFCC |
00FFFF |
36 |
330000 |
330033 |
330066 |
330099 |
3300CC |
3300FF |
42 |
333300 |
333333 |
333366 |
333399 |
3333CC |
3333FF |
48 |
336600 |
336633 |
336666 |
336699 |
3366CC |
3366FF |
54 |
339900 |
339933 |
339966 |
339999 |
3399CC |
3399FF |
60 |
33CC00 |
33CC33 |
33CC66 |
33CC99 |
33CCCC |
33CCFF |
66 |
33FF00 |
33FF33 |
33FF66 |
33FF99 |
33FFCC |
33FFFF |
72 |
660000 |
660033 |
660066 |
660099 |
6600CC |
6600FF |
78 |
663300 |
663333 |
663366 |
663399 |
6633CC |
6633FF |
84 |
666600 |
666633 |
666666 |
666699 |
6666CC |
6666FF |
90 |
669900 |
669933 |
669966 |
669999 |
6699CC |
6699FF |
96 |
66CC00 |
66CC33 |
66CC66 |
66CC99 |
66CCCC |
66CCFF |
102 |
66FF00 |
66FF33 |
66FF66 |
66FF99 |
66FFCC |
66FFFF |
108 |
990000 |
990033 |
990066 |
990099 |
9900CC |
9900FF |
114 |
993300 |
993333 |
993366 |
993399 |
9933CC |
9933FF |
120 |
996600 |
996633 |
996666 |
996699 |
9966CC |
9966FF |
126 |
999900 |
999933 |
999966 |
999999 |
9999CC |
9999FF |
132 |
99CC00 |
99CC33 |
99CC66 |
99CC99 |
99CCCC |
99CCFF |
138 |
99FF00 |
99FF33 |
99FF66 |
99FF99 |
99FFCC |
99FFFF |
144 |
CC0000 |
CC0033 |
CC0066 |
CC0099 |
CC00CC |
CC00FF |
150 |
CC3300 |
CC3333 |
CC3366 |
CC3399 |
CC33CC |
CC33FF |
156 |
CC6600 |
CC6633 |
CC6666 |
CC6699 |
CC66CC |
CC66FF |
162 |
CC9900 |
CC9933 |
CC9966 |
CC9999 |
CC99CC |
CC99FF |
168 |
CCCC00 |
CCCC33 |
CCCC66 |
CCCC99 |
CCCCCC |
CCCCFF |
174 |
CCFF00 |
CCFF33 |
CCFF66 |
CCFF99 |
CCFFCC |
CCFFFF |
180 |
FF0000 |
FF0033 |
FF0066 |
FF0099 |
FF00CC |
FF00FF |
186 |
FF3300 |
FF3333 |
FF3366 |
FF3399 |
FF33CC |
FF33FF |
192 |
FF6600 |
FF6633 |
FF6666 |
FF6699 |
FF66CC |
FF66FF |
198 |
FF9900 |
FF9933 |
FF9966 |
FF9999 |
FF99CC |
FF99FF |
204 |
FFCC00 |
FFCC33 |
FFCC66 |
FFCC99 |
FFCCCC |
FFCCFF |
210 |
FFFF00 |
FFFF33 |
FFFF66 |
FFFF99 |
FFFFCC |
FFFFFF |
To obtain the index for a given color, add the numbers in the leftmost column and top row corresponding
to this color.
Palette #2 contains the standard 16 HTML colors (alphabetically ordered by name), as follows:
Index | Color | Name | Index | Color | Name |
0 | 00FFFF | aqua | 8 | 000080 | navy |
1 | 000000 | black | 9 | 808000 | olive |
2 | 0000FF | blue | 10 | 800080 | purple |
3 | FF00FF | fuchsia | 11 | FF0000 | red |
4 | 008000 | green | 12 | C0C0C0 | silver |
5 | 808080 | grey | 13 | 008080 | teal |
6 | 00FF00 | lime | 14 | FFFFFF | white |
7 | 800000 | maroon | 15 | FFFF00 | yellow |
Palette #3 contains 256 grayscale colors from RGB(0, 0, 0) to RGB(255, 255, 255) and is not shown here.
Any single color index in a frame can be assigned to be transparent, or see-through.
This is done via the property JpegGif.TranspColor. The following code snippet
creates a new GIF image and assigns color index 216 (the first unused index in the default palette)
to be transparent, and then fills the image with a transparent background:
C# |
objGif.AddFrame( 100, 100, 0, 0 );
objGif.TranspColor = 216;
objGif.PenColor = 216;
objGif.BrushColor = 216;
objGif.FillRect( 0, 0, 100, 100 );
...
|
VB.NET |
objGif.AddFrame( 100, 100, 0, 0 )
objGif.TranspColor = 216
objGif.PenColor = 216
objGif.BrushColor = 216
objGif.FillRect( 0, 0, 100, 100 )
...
|
To remove transparency from the current frame, the property JpegGif.TranspColorSet needs to be set to false.
9.7.1 Other Frame Management Methods
In addition to the JpegGif.AddFrame and JpegGif.RemoveFrame methods covered above, there are also
JpegGif.Clear and JpegGif.MoveFrame methods.
The Clear method, which takes no arguments, simply
removes all frames from the image. An image with no frames cannot be saved or drawn on.
MoveFrame takes two arguments: the original index and desired index. It moves the frame
specified by the first argument to a new location specified by the 2nd argument.
If the current frame is affected by the move, the CurrentFrame property will
change to reflect the new position of the current frame.
The current frame remains the same, albeit at a new location.
9.7.2 Other Animation Management Properties
The JpegGif.Loops property controls how many times the animation sequence runs before stopping.
By default, this property is 0 which designates an infinite number of loops.
The JpegGif.Delay property affects the time delay of the current frame measured in 1/100 sec. By default,
this property is set to 100 (1 sec) for every frame being added.
9.7.3 Saving Individual Frames
The property JpegGif.FrameToSave, if set to a non-zero value,
instructs the JpegGif object to save only the frame specified by this property,
and no other frames, when a Save method is called. This enables you to view every individual
frame of an animated GIF. This feature was added mostly for debugging purposes.
9.7.4 Finding a Closest Color
The method JpegGif.FindClosestColor enables you to search a palette for the index
of a color closest to a given RGB trio. The method expects the global/local
flag and three RGB values. It returns an index in the specified palette
which corresponds to the color closest to the specified RGB values.
9.7.5 Disposal Methods
The property JpegGif.DisposalMethod controls how frames in an animated GIF replace each other.
The valid values are:
- Leave the current image in place and draw the next image on top of it. This is the default method.
- The canvas should be restored to the background color before the next image is rendered.
- The canvas should be restored to its previous state before the current image is drawn.
 |
Advanced
Image Management
Component for .NET |
All Rights Reserved. AspJpeg.NET is a trademark of Persits Software, Inc. |
|
 |