Article ID: 319591 - View products that this article applies to.
This article was previously published under Q319591
The CompuServe Graphics Interchange Format (GIF) is designed with a maximum of 256 colors that are arranged in a color table. To make common modifications to a .gif image file, you must change a custom color table. However, when System.Drawing edits an Image object and is then asked to save the image with the GIF encoder, the resulting .gif file contains a halftone color table.
To save an Image with a custom color table by using the GIF encoder, you must work with a 256-color copy of the Image that System.Drawing has not modified.
The System.Drawing namespace is primarily a wrapper around GDI+, therefore this article refers to the namespace as GDI+ unless behavior that is specific to the System.Drawing namespace is discussed. In this case, the term System.Drawing is used.
After GDI+ modifies an Image, and then writes an image to a file by using the GIF encoder, GDI+ writes the file by using a halftone palette to which the Image bits of the object have been color reduced. GDI+ does a color conversion from 32 bits per pixel (32 BPP) when it writes the image to the file because all modifications to the image are made with GDI+ 32-BPP graphics engine.
Although GDI+ supports the creation of Images and Bitmaps of various pixel formats and can therefore load a .gif image, the use of the 32-BPP graphics engine necessitates the conversion to 32 BPP when they are modified by GDI+. However, an Image or Bitmap that is not modified by GDI+ retains its original pixel format and can be written to a file using the Save method with the appropriate encoder. This property forms the basis for a technique that can save an Image to a .gif file with a custom color table.
The method is to copy the image data from an original Image object to a temporary Bitmap object. This temporary Bitmap is created as an 8-BPP indexed Bitmap. This is the pixel format that is used to save a .gif file. The Bitmap color table is set by using the SetPalette method, and then the image definition is copied to the temporary Bitmap. After you create the temporary Bitmap with a duplicate definition, you can use the Save() method to save it with the GIF encoder, which preserves the 8-BPP color table.
To write a .gif image to a file with a custom color table, follow these steps:
The sample function takes the following four parameters:
To create the .gif file, you must initialize the 8-BPP Bitmap object with the image definition that is to be written to the file. In the sample code, a central set of loops is used to color convert the incoming image to essentially the black and white TV color space.
For demonstration purposes, the source image pixels are accessed by means of the GetPixel() method of a Bitmap object that is a copy of the source image. A Bitmap copy is made because the Image class does not implement the GetPixel() method.
You can use other techniques to access the pixels, such as direct access to the pixels by using the LockBits() method or interop with native unmanaged code by using Windows GDI DIB Sections. When you use the BitBlt function to copy a bitmap from a Gdi+ HDC to a GDI DIB Section memory domain controller, the GBitBlt functions uses the color matching abilities of GDI.
Because the Visual Basic .NET Language cannot access memory buffers directly by means of a pointer as in other languages, an intermediate step is necessary. This code creates a working Byte buffer in which are placed the color indexes by the color conversion loops. This buffer is a managed data structure whose elements can be manipulated by Visual Basic .NET code. After the image color index defitions are placed in this buffer, interop services are used to call the RtlMoveMemory Operating System function to transfer the contents of this Byte buffer to the memory buffer that is referenced by the Scan0 IntPtr of the BitmapData object.
The Win32API class that is defined in the sample code demonstrates how to define and use an unmanaged operating system function by using .NET Framework interop services. RtlMoveMemory is declared by this class to be the CopyArrayTo method. This method is defined to marshal the appropriate Visual Basic .NET data types into the appropriate parameters for RtlMoveMemory. CopyArrayTo therefore takes the source Byte array in the second parameter and copies the contents of the Byte array to the memory that is pointed at by the value in the first parameter that is defined as an Int32. The first parameter to CopyArrayTo is an System.Int32 type because that is the value type that can be obtained from the IntPtr class.
After you create the Bitmap copy, use the Save method with the ImageFormat.Gif object to write the bitmap to the destination file.
For more information about the GIF codec, see the "References" section of this article.
Unfortunately, the ColorPalette class of the System.Drawing namespace in the .NET Framework cannot be instantiated independent of a Bitmap object. This is a restriction that only the System.Drawing.Bitmap class imposes in the .NET Framework; however, to use the approach in this article, the Bitmap object must have a new ColorPalette object that contains fewer colors than the default 256 ColorPalette.
To achieve this, the sample code defines a function named GetColorPalette. This function creates a temporary Bitmap object that has a color depth close to the requested number of colors. The function then references the Palette property and returns it to the caller. This creates a new ColorPalette with one of several possible color counts: 256 colors, 16 colors, or two colors (monochrome). Although you can create color tables in .gif files that are smaller than 256 colors, color tables are limited to sizes that are a power of two.
When you limit color table sizes to a power of two, you minimize wasted space. The resulting color table in this example is 8 colors (2x2x2). With the sample code, the .gif file would be created with a color table of 16 colors because that is the smallest PixelFormat for a Bitmap that accomodates six colors.
The code in the processing loop that copies the image's pixel definitions to the 8-BPP Bitmap takes into account the size of the palette when the code computes a pixel's index value. The GIF codec limits the size of the palette and restricts the image definition to index values that are compatible with the palette size (that is, the potential GIF color table), and can therefore create .gif files with fewer than 256 colors.
The GIF encoder identifies the first color in the ColorPalette that has an Alpha value of ZERO as the transparent color. This means that the transparent color does not have to be the first entry in the ColorPalette. It can be any one of the possible 256 colors in the palette, on the condition that all preceeding entries contain Alpha components with non-zero values. Any later entries with Alpha component values of ZERO are ignored. All entries that have non-zero Alpha components are considered opaque.
For additional information about LZW licenses and GIF, click the article number below to view the article in the Microsoft Knowledge Base:
(http://support.microsoft.com/kb/193543/EN-US/ )INFO: Unisys GIF and LZW Technology License Information
About Sample CodeMicrosoft provides programming examples for illustration only, without warranty either expressed or implied, including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose. This article assumes that you are familiar with the programming language being demonstrated and the tools used to create and debug procedures. Microsoft support professionals can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific needs.
If you have limited programming experience, you may want to contact a Microsoft Certified Partner or Microsoft Advisory Services. For more information, visit these Microsoft Web sites:
Microsoft Certified Partners - https://partner.microsoft.com/global/30000104
Microsoft Advisory Services - http://support.microsoft.com/gp/advisoryservice
For more information about the support options that are available and about how to contact Microsoft, visit the following Microsoft Web site:http://support.microsoft.com/default.aspx?scid=fh;EN-US;CNTACTMS
For additional information about GIF codec pixel formats, click the article number below to view the article in the Microsoft Knowledge Base:
318343For additional information about Image file sizes, click the article number below to view the article in the Microsoft Knowledge Base:
(http://support.microsoft.com/kb/318343/EN-US/ )INFO: GDI+ GIF Files are Saved Using the 8-BPP Format
312119For additional information about writing custom GIF files using Visual C++ and Visual C#, click the article number below to view the article in the Microsoft Knowledge Base:
(http://support.microsoft.com/kb/312119/EN-US/ )PRB: Save Method of Bitmap Class Does Not Truncate File Size
(http://support.microsoft.com/kb/315780/EN-US/ )HOWTO: Save a GIF with a New Color Table By Using GDI+
(http://support.microsoft.com/kb/319061/EN-US/ )HOW TO: Save a GIF with a New Color Table By Using Visual C#
bits per pixel - the number of bits used to represent the color value of each pixel in a digitized image; describes the physical layout of each pixel's color definition in an image. Common and generically referenced pixel formats include 32 BPP, 24 BPP, 16 BPP, 8 BPP, 4 BPP, 1 BPP.8 BPP
The image pixel format that is expressed as eight bits contained in one byte. The byte value is used as an index into a color table that contains the actual red-green-blue (RGB) color definitions. Because the index is one byte in size, the color table is limited to 256 colors.GIF
Graphics Interchange Format - a streamable image file format that was created by CompuServe.RGB
Red, green and blue - each commonly expressed as a byte, and resulting in a color 3-byte triplet.
Article ID: 319591 - Last Review: November 23, 2006 - Revision: 5.4