Click here to Skip to main content
15,879,095 members
Articles / Web Development / ASP.NET

ASP.NET Transparent GIF

Rate me:
Please Sign up or sign in to vote.
2.23/5 (4 votes)
4 Sep 2007CPOL2 min read 48.4K   193   11   8
Writing a transparent GIF directly into the output stream via ASP.NET and C#.

Screenshot - transparent-gif.jpg

Introduction

Writing images into the output stream of an HTTP-Response is a simple task. Writing a transparent GIF into the output stream is not. The reason is the GDI+ handler for saving the image data to the output stream. Here is a workaround.

Background

Webmasters need some cool tools to maintain their websites and keep on track to get their business better. That's why many of these webmasters have something like Google Analytics running to track user behaviour and to track where the surfers come from (e.g., search strings via Google, referrers, natural type-ins, etc).

For some reasons, a customer of mine wasn't happy with using Google Analytics, because of two main reasons:

  1. The use of JavaScript was against their policies.
  2. The data Google Analytics gets is property of Google Inc.

So they needed a small and simple tracking solution that works without JavaScript and covers their needs.

Using the Code

To track referrers, you need to have an application that can be requested. Because of Corporate Design issues, the response of the request should be a transparent image - so a transparent GIF was exactly what I needed.

I prepared a transparent GIF and tried the following:

VB
Bitmap bm = new Bitmap(Server.MapPath("transparent.gif")); 
Response.ContentType = "image/gif";
bm.Save(Response.OutputStream, ImageFormat.Gif);
bm.Dispose();
Response.Flush();

Well, this didn't work. The image delivered to the output stream was black. Then I played a little with:

VB
bm.MakeTransparent(Color.Transparent);

But this didn't work, too. My thought was that my prepared GIF was broken, so I created a clean black GIF and tried to use MakeTransparent(Color.Black), but with no success.

Solution

VB
System.Drawing.Image _gifImage;

_gifImage = System.Drawing.Image.FromFile(Server.MapPath("white.JPG"));
Bitmap bm = new Bitmap(_gifImage.Width, _gifImage.Height, 
        PixelFormat.Format8bppIndexed);

// Get the palette from the bitmap
ColorPalette pal = bm.Palette;

// Set Alpha to 0
for (int i = 0; i < pal.Entries.Length; i++)
{
    Color col = pal.Entries[i];
    pal.Entries[i] = Color.FromArgb(0, col.R, col.G, col.B);
}

// assign palette
bm.Palette = pal;

//to copy the bitmap data we need to lock the source & 
//destination bits
BitmapData src = ((Bitmap)_gifImage).LockBits(new Rectangle
(0, 0, _gifImage.Width, _gifImage.Height), ImageLockMode.ReadOnly,
 _gifImage.PixelFormat);
BitmapData dst = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), 
ImageLockMode.WriteOnly, bm.PixelFormat);

//finished, unlock the bits
((Bitmap)_gifImage).UnlockBits(src);
bm.UnlockBits(dst);

//Set Response Type to "image/gif"
Response.ContentType = "image/gif";

//Writing the gif directly into the Output-Stream
bm.Save(Response.OutputStream, ImageFormat.Gif);

//cleaning up
bm.Dispose();
_gifImage.Dispose();

//Send output stream
Response.Flush(); 

In short, we're creating a new color palette for our GIF. Then, we're changing all the Alpha entries to zero - the GIF encoder will now encode the transparent color for every entry that has Alpha == 0.

Points of Interest

The Bitmap.Save() method promotes the format of the GIF to 32 bpp before giving the image to the GIF-encoder. The GIF-encoder color-reduces it to a 256-entry color table. When the dynamically generated image format is at 8 bpp, the GIF-encoder just encodes its palette entries into the smallest GIF color table possible. And, this exactly is the problem in here.

Links & Resources

History

  • 2007/04/09: Initial publishing.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralInteresting code... Pin
Eric Clsner25-May-10 7:18
Eric Clsner25-May-10 7:18 
GeneralNGif Pin
dB.5-Sep-07 2:14
dB.5-Sep-07 2:14 
GeneralAlternate solution Pin
Jelle Hissink4-Sep-07 3:42
Jelle Hissink4-Sep-07 3:42 
GeneralRe: Alternate solution Pin
hartertobak4-Sep-07 4:57
hartertobak4-Sep-07 4:57 
GeneralRe: Alternate solution Pin
Jelle Hissink4-Sep-07 20:06
Jelle Hissink4-Sep-07 20:06 
GeneralSome artificial problem. Pin
Gevorg4-Sep-07 3:37
Gevorg4-Sep-07 3:37 
GeneralRe: Some artificial problem. Pin
hartertobak4-Sep-07 4:54
hartertobak4-Sep-07 4:54 
GeneralRe: Some artificial problem. Pin
Gevorg4-Sep-07 7:06
Gevorg4-Sep-07 7:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.