Question

I'm trying to return a transparent GIF from an .aspx page for display within a web page. I am trying to get the image to have transparency, but I just keep getting Black being where the image should be Transparent.

Does anyone know what I'm doing wrong?

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
  Handles Me.Load
    '' Change the response headers to output a GIF image.
    Response.Clear()
    Response.ContentType = "image/gif"

    Dim width = 110
    Dim height = width

    '' Create a new 32-bit bitmap image
    Dim b = New Bitmap(width, height)

    '' Create Grahpics object for drawing
    Dim g = Graphics.FromImage(b)

    Dim rect = New Rectangle(0, 0, width - 1, height - 1)

    '' Fill in with Transparent
    Dim tbrush = New System.Drawing.SolidBrush(Color.Transparent)
    g.FillRectangle(tbrush, rect)

    '' Draw Circle Border
    Dim bPen = Pens.Red
    g.DrawPie(bPen, rect, 0, 365)

    '' Fill in Circle
    Dim cbrush = New SolidBrush(Color.LightBlue)
    g.FillPie(cbrush, rect, 0, 365)


    '' Clean up
    g.Flush()
    g.Dispose()

    '' Make Transparent
    b.MakeTransparent()

    b.Save(Response.OutputStream, Imaging.ImageFormat.Gif)
    Response.Flush()
    Response.End()
End Sub
Was it helpful?

Solution

Unfortunately, there is no easy way to create a transparent Gif using a Bitmap object. (See this KB article)

You can alternatively use the PNG format that supports transparency with the code you are using.

OTHER TIPS

Yes, as Jerome stated, there isn't anyway to create transparent GIF's using a Bitmap object. Crap!

Well, anyway, I changed my code to generate a PNG and all works as expected.

There is one small work around I did need to do since you cannot write PNG's directly to the OutputStream. I needed to write the PNG to a MemoryStream, and then write that out to the OutputStream.

Here's the final code for my implementation:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
  Handles Me.Load
    '' Change the response headers to output a JPEG image.
    Response.Clear()
    Response.ContentType = "image/png"

    Dim width = 11
    Dim height = width

    '' Create a new 32-bit bitmap image
    Dim b = New Bitmap(width, height)

    '' Create Grahpics object for drawing
    Dim g = Graphics.FromImage(b)

    '' Fill the image with a color to be made Transparent after drawing is finished.
    g.Clear(Color.Gray)

    '' Get rectangle where the Circle will be drawn
    Dim rect = New Rectangle(0, 0, width - 1, height - 1)

    '' Draw Circle Border
    Dim bPen = Pens.Black
    g.DrawPie(bPen, rect, 0, 365)

    '' Fill in Circle
    Dim cbrush = New SolidBrush(Color.Red)
    g.FillPie(cbrush, rect, 0, 365)

    '' Clean up
    g.Flush()
    g.Dispose()

    '' Make Transparent
    b.MakeTransparent(Color.Gray)

    '' Write PNG to Memory Stream then write to OutputStream
    Dim ms = New MemoryStream()
    b.Save(ms, Imaging.ImageFormat.Png)
    ms.WriteTo(Response.OutputStream)

    Response.Flush()
    Response.End()
End Sub

It is possible, but not easy
If you are able to use unsafe code in your project, there are a few methods to use pointers to rip through the colour table and make the transparency work.

A sample forms app by Bob Powell is available here http://www.bobpowell.net/giftransparency.htm. I used a variation on this method on a web handler a few years ago that was getting hit about 10 million times a month, and it seemed to work fine.

If you are only using a limited colour pallete you can reduce the colour table processing to just the colours you need (can't remember exactly how I did that...).

That being said, png is a metric crapload easier.

here is some code to have a gif (that already have transparency in it) transformed (supposed you want to resize it) in bitmap and then can be showed properly with it's transparency.

imagePath = System.Web.HttpContext.Current.Request.MapPath(libraryPath + reqImageFile);
System.Drawing.Image image = null;
Bitmap resizedImage = null;

if (reqWidth == 0) { reqWidth = image.Width; }
if (reqHeight == 0) { reqHeight = image.Height; }
image = System.Drawing.Image.FromFile(imagePath);
reqWidth = image.Width;
reqHeight = image.Height;

//here is the transparency 'special' treatment
resizedImage = new Bitmap(reqWidth, reqHeight, PixelFormat.Format8bppIndexed);
ColorPalette pal = resizedImage.Palette;
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);
}
resizedImage.Palette = pal;
BitmapData src = ((Bitmap)image).LockBits(new Rectangle(0, 0, reqWidth, reqHeight),  ImageLockMode.ReadOnly, image.PixelFormat);
BitmapData dst = resizedImage.LockBits(new Rectangle(0, 0, resizedImage.Width, resizedImage.Height),
ImageLockMode.WriteOnly, resizedImage.PixelFormat);
((Bitmap)image).UnlockBits(src);
resizedImage.UnlockBits(dst);

Good luck !

Grégoire Lafortune

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top