Exploring the depths and potentials of ASP.NET RSS 2.0 or Subscribe to .BenRush by Email
 Monday, March 26, 2007

I was helping someone out on the newsgroups who wanted to draw a GIF from his ASP.Net web page; one of the requirements was that it had a transparent background. As it turns out, this little exercise is a bit more complicated than it at first seems due to - what I think - is either a bug or an anomaly in the GDI+ framework.

First - a bit of education. GIF is an indexed image format, meaning that it uses a color palette and individual pixels reference a color by indexing into the palette. One of the "colors" in the palette is a non-color or transparent; a transparent color is anything with an alpha value of 0 (ie both 0-255-255-255 and 0-128-128-128 are "invisible" where the first digit represents the value of the alpha octet).

Interestingly, the .Net runtime's GDI+ Graphics.FromImage() method DOES NOT like indexed file formats, so if you want to draw onto a GIF using the GDI+ framework, it cannot be done via this method. It's screwy; don't ask me why it is this way. Well, this guy wanted to draw text onto a GIF with a transparent background, so....how to you go about drawing text onto a GIF with a transparent background?

My first thought was modifying the palette so that all references to, say, black had an alpha transparency level of 0 - meaning invisible. What this would mean is that anything that referenced a black index into the color palette wouldn't be visible (100% alpha value). Another interesting "quirk" of the .Net runtime GDI+ framework, however, is that whenever you save the data to a stream (file, memory stream, output stream, etc) it will screw with the color palette. I didn't really try to understand what it was doing, but if you look at the color palette in a debugger window while using it, the save method just toys with it and mucks up your mods to it.

So...the only option, lock down the data, and reference each individual pixel in the image, pointing it to the entry in the GIFs color palette for a transparent color instead of black. And it worked....here is the code (implemented as a C# library that you may use freely - please be mindful that I have not tested this but for just a little bit, there may be resource leaks, etc):

public class TransparentGif
{
 public TransparentGif()
 {
 }
    public static MemoryStream DrawTransparentGif(
        String text, Color textColor, Int32 width, Int32 height)
    {
        Bitmap drawableBMP = new Bitmap(width, height);
        Graphics gdc = Graphics.FromImage(drawableBMP);
        try
        {
            gdc.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, width, height));
            gdc.DrawString(text, new Font("Arial", 13), new SolidBrush(textColor), 0, 0);
            MemoryStream memStream = new MemoryStream();
            drawableBMP.Save(memStream, ImageFormat.Gif);

            memStream.Seek(0, SeekOrigin.Begin);
            System.Drawing.Image gifed = System.Drawing.Image.FromStream(memStream);

            ColorPalette cp = gifed.Palette;
            Int32 alpha = 0;
            for (Int32 c = 0; c < cp.Entries.Length; c++)
            {
                if (cp.Entries[c].A == 0)
                {
                    alpha = c;
                     break;
                }
            }

            BitmapData data = ((Bitmap)gifed).LockBits(
    new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, gifed.PixelFormat);

            Byte[] buffer = new Byte[width* height];
            Marshal.Copy(data.Scan0, buffer, 0, width* height);

            for (Int32 c = 0; c < buffer.Length; c++)
            {
                if (cp.Entries[buffer[c]].ToArgb() == Color.Black.ToArgb())
                {
                    buffer[c] = (Byte)alpha;
                }
            }

            Marshal.Copy(buffer, 0, data.Scan0, buffer.Length);

            ((Bitmap)gifed).UnlockBits(data);

            MemoryStream outStream = new MemoryStream();
            gifed.Save(outStream, ImageFormat.Gif);
            outStream.Seek(0, SeekOrigin.Begin);

            return outStream;
        }
        finally
        {
            if (gdc != null)
                gdc.Dispose();
        }
    }
}

If you comment out the actual pixel manipulation, what gets drawn to my web page is the following:

...or a GIF with a black background. If you bring back in the actual pixel manipulation part of the above code, you get this:

Total alpha transparency of the GIF....

Addendum:

For an example of using this class, see here.

Recommended reading:

kick it on DotNetKicks.com
Monday, March 26, 2007 12:19:27 PM (Central Standard Time, UTC-06:00)  #    Comments [1] - Trackback
ASP.Net | Programming | WinForms and WPF
Tracked by:
"Using my image class from Page_Load" (.BenRush) [Trackback]
http://www.ben-rush.net/blog/PermaLink,guid,96783918-14c0-408c-87a0-4bb38220c731... [Pingback]
http://freewebs.com/aspxfaq/10/sitemap8.html [Pingback]
http://freewebs.com/toltom/14/sitemap10.html [Pingback]
http://freewebs.com/toltom/11/www-games-atari-com.html [Pingback]
http://freewebs.com/toltom/16/sitemap4.html [Pingback]
http://freewebs.com/toltom/09/mercury-car-insurance.html [Pingback]
"http://kevruublog.tripod.com/53.html" (http://kevruublog.tripod.com/53.html) [Pingback]
"http://fartooblog.tripod.com/38.html" (http://fartooblog.tripod.com/38.html) [Pingback]
"http://tlem3v.org/sitemap49.html" (http://tlem3v.org/sitemap49.html) [Pingback]
"http://mxfb9a.org/cruisingforsex.html" (http://mxfb9a.org/cruisingforsex.html) [Pingback]
"http://topslots.nl.eu.org/11/sitemap9.html" (http://topslots.nl.eu.org/11/sitem... [Pingback]
"http://freewebs.com/amexa/44/wind-generators.html" (http://freewebs.com/amexa/4... [Pingback]
"http://freewebs.com/amexa/01/bipolar-disorder.html" (http://freewebs.com/amexa/... [Pingback]
"http://freewebs.com/amexa/38/niagara-falls-new-york.html" (http://freewebs.com/... [Pingback]
"http://pinofranc.homestead.com/01/fashion-design-school.html" (http://pinofranc... [Pingback]
"http://pinofranc.homestead.com/01/les-miserables-lyrics.html" (http://pinofranc... [Pingback]
"http://pinofranc.homestead.com/04/casion.html" (http://pinofranc.homestead.com/... [Pingback]
"http://wdall-xxx.com/free-lesbian-orgies.html" (http://wdall-xxx.com/free-lesbi... [Pingback]
"http://pgqot-www.com/cute-anime-girls.html" (http://pgqot-www.com/cute-anime-gi... [Pingback]
"http://pohteenews.tripod.com/160.html" (http://pohteenews.tripod.com/160.html) [Pingback]
"http://pohteenews.tripod.com/181.html" (http://pohteenews.tripod.com/181.html) [Pingback]
"http://lasduunews.angelfire.com/26.html" (http://lasduunews.angelfire.com/26.ht... [Pingback]
"http://iauci-ooo.com/free-blow-job-clip.html" (http://iauci-ooo.com/free-blow-j... [Pingback]
"http://nabkoonews.tripod.com/151.html" (http://nabkoonews.tripod.com/151.html) [Pingback]
"http://xahrf-hhh.com/teens-haveing-sex.html" (http://xahrf-hhh.com/teens-havein... [Pingback]
"http://adtih-xxx.biz/cum-stain.html" (http://adtih-xxx.biz/cum-stain.html) [Pingback]
"http://hsslx-www.biz/free-teen-bukkake.html" (http://hsslx-www.biz/free-teen-bu... [Pingback]
"http://p4g2f-eee.com/wings-of-a-butterfly.html" (http://p4g2f-eee.com/wings-of-... [Pingback]
"http://freewebs.com/amexa/36/free-cell-phone-wall-paper.html" (http://freewebs.... [Pingback]
"http://freewebs.com/rimoq/00/work-from-home.html" (http://freewebs.com/rimoq/00... [Pingback]
"http://freewebs.com/niret/08/powerball-lottery-results.html" (http://freewebs.c... [Pingback]
"http://freewebs.com/amexa/05/savannah-georgia.html" (http://freewebs.com/amexa/... [Pingback]
"http://freewebs.com/bermut/06/wedding-photography.html" (http://freewebs.com/be... [Pingback]
"http://u1eah-rrr.com/pinups-sexy.html" (http://u1eah-rrr.com/pinups-sexy.html) [Pingback]
"http://unistarkom.mycv.tv/00598-blog.html" (http://unistarkom.mycv.tv/00598-blo... [Pingback]
"http://ramambo.nl.eu.org/15/charmed-spoilers.html" (http://ramambo.nl.eu.org/15... [Pingback]
"http://harum.nl.eu.org/www-msn-com-br.html" (http://harum.nl.eu.org/www-msn-com... [Pingback]
"http://ramambo.nl.eu.org/www-soul2soul-com.html" (http://ramambo.nl.eu.org/www-... [Pingback]
"http://opmg8at.biz/soft-cock.html" (http://opmg8at.biz/soft-cock.html) [Pingback]
"http://kp7ide0.biz/pictures-of-butterflies.html" (http://kp7ide0.biz/pictures-o... [Pingback]
"http://donakom.nl.eu.org/show-me-christina-aguilera-nude.html" (http://donakom.... [Pingback]
"http://fenotblog.nl.eu.org/vanessadelrio.html" (http://fenotblog.nl.eu.org/vane... [Pingback]
"http://mv8oyh3.biz/homemade-vagina-toys-sex.html" (http://mv8oyh3.biz/homemade-... [Pingback]
"http://freewebs.com/gabeganews/182.html" (http://freewebs.com/gabeganews/182.ht... [Pingback]
"http://kfaqlam.biz/free-nude-women-pictures.html" (http://kfaqlam.biz/free-nude... [Pingback]
"http://plxguhg.biz/sitemap28.html" (http://plxguhg.biz/sitemap28.html) [Pingback]
"http://rwqqwmi.biz/crossed-legs-in-nylons.html" (http://rwqqwmi.biz/crossed-leg... [Pingback]
"http://abo--blog.nl.eu.org/juvenile-justice.html" (http://abo--blog.nl.eu.org/j... [Pingback]
"http://nasferablog.netfirms.com/447.html" (http://nasferablog.netfirms.com/447.... [Pingback]
"http://aqw--blog.nl.eu.org/zabba-search.html" (http://aqw--blog.nl.eu.org/zabba... [Pingback]
"http://nasferablog.netfirms.com/229.html" (http://nasferablog.netfirms.com/229.... [Pingback]
"http://qcdals1.biz/stafford-county-schools-stafford-va.html" (http://qcdals1.bi... [Pingback]
"http://klo--blog.nl.eu.org/restaurants-san-francisco.html" (http://klo--blog.nl... [Pingback]
"http://newa--lono.nl.eu.org/hotels-lodgingreservationcenter-com.html" (http://n... [Pingback]
"http://hhtlpnh.biz/teen-titans-starfire-kisses-robin.html" (http://hhtlpnh.biz/... [Pingback]
"http://nasferablog.netfirms.com/231.html" (http://nasferablog.netfirms.com/231.... [Pingback]
"http://jmqp7tr.biz/budgetcarrentail.html" (http://jmqp7tr.biz/budgetcarrentail.... [Pingback]
"http://hjftsic.biz/wwwnew.citibank.com.html" (http://hjftsic.biz/wwwnew.citiban... [Pingback]
"http://derfoblog.ifrance.com/sitemap6.html" (http://derfoblog.ifrance.com/sitem... [Pingback]
"http://freewebs.com/sruone/nickjrcom.html" (http://freewebs.com/sruone/nickjrco... [Pingback]
"http://freewebs.com/sruone/sitemap64.html" (http://freewebs.com/sruone/sitemap6... [Pingback]
"http://lopbafrea.homestead.com/168.html" (http://lopbafrea.homestead.com/168.ht... [Pingback]
"http://mrwqmcw.info/girl-ejaculation.html" (http://mrwqmcw.info/girl-ejaculatio... [Pingback]
"http://freewebs.com/vuter/13/lobster-recipes.html" (http://freewebs.com/vuter/1... [Pingback]
"http://euter.homestead.com/00/www-legalzoom-com.html" (http://euter.homestead.c... [Pingback]
"http://freewebs.com/vuter/06/sitemap8.html" (http://freewebs.com/vuter/06/sitem... [Pingback]
"http://vuter.homestead.com/01/maywood-park-horse-racing-entries.html" (http://v... [Pingback]
"http://freewebs.com/datingblogger/807.html" (http://freewebs.com/datingblogger/... [Pingback]
"http://freewebs.com/datingblogger/1029.html" (http://freewebs.com/datingblogger... [Pingback]
"http://fasxen.netfirms.com/21.html" (http://fasxen.netfirms.com/21.html) [Pingback]
Wednesday, June 27, 2007 6:07:21 AM (Central Standard Time, UTC-06:00)
Small buggy ...

Try using a width of 129 ... the bottom lines are not transparent.

solution:
instead of width, you should use data.Stride,
e.g. Byte[] buffer = new Byte[data.Stride* height];
Jacco Compier
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview

Computers Blogs - Blog Top Sites

Archive
<November 2008>
SunMonTueWedThuFriSat
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
Blogroll
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008
Benjamin Rush
Sign In
Statistics
Total Posts: 444
This Year: 0
This Month: 0
This Week: 0
Comments: 127
Themes
Pick a theme:
All Content © 2008, Benjamin Rush
DasBlog theme 'Business' created by Christoph De Baene (delarou)