Click here to Skip to main content
Click here to Skip to main content

ASP.NET Transparent GIF

, 4 Sep 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

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:

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

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)

Share

About the Author

hartertobak

Germany Germany
No Biography provided

Comments and Discussions

 
GeneralInteresting code... PinmemberEric Clsner25-May-10 7:18 
GeneralNGif PinmemberdB.5-Sep-07 2:14 
GeneralAlternate solution PinmemberJelle Hissink4-Sep-07 3:42 
GeneralRe: Alternate solution Pinmemberhartertobak4-Sep-07 4:57 
GeneralRe: Alternate solution PinmemberJelle Hissink4-Sep-07 20:06 
GeneralSome artificial problem. PinmemberGevorg4-Sep-07 3:37 
GeneralRe: Some artificial problem. Pinmemberhartertobak4-Sep-07 4:54 
GeneralRe: Some artificial problem. PinmemberGevorg4-Sep-07 7:06 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 4 Sep 2007
Article Copyright 2007 by hartertobak
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid