Last post Dec 31, 2006 07:35 AM by Hope4sun
Dec 27, 2006 04:27 PM|martinhn|LINK
I am creating an image dynamically according to information in a database. When the Image is created as an Image object i save it to the ResponseStream. I want to make that Image transparent, does anyone know how to do that? It has to be used in an ASP.NET
app, and i'm using an ImageHandler (.ashx) to show the Image on a page.
A bit of my code:
First i have an Image object:
System.Drawing.Image canvas = System.Drawing.Image.FromFile("d:\\original.jpg");
Then I do a lot of stuff with the Image
The I save it
Right before I save it, I would like to make it transparrent. Maybe 50% transparency or less...
Dec 28, 2006 05:23 AM|Hope4sun|LINK
Dec 28, 2006 03:38 PM|martinhn|LINK
Thanks for the link...
Which way should I save the Image? Right now, I write it to the
context.Response.OutputStream. But how do I make sure to use the correct format?
In my ImageHandler i set this: context.Response.ContentType =
And when i save the Image: canvas.Save(context.Response.OutputStream,
Shouldn't i set some properties to make it save the transparrency? As it is now, the Image is not transparent...
Thanks in advance...
Dec 29, 2006 06:56 AM|Hope4sun|LINK
It sounds like your saving the iamge out ok, are you applying the palette conversion to the image first?, heres another 2 links that should help, the first pretty much covers most of it. The second one will do the trick perfectly, but it will need wrap most
of the panel1_Click code into a function in the class to allow you to return the converted image, your need to have a couple of properties too, one could be to store the image the other to set a color you want to make transparent.
Let me know how you get on with the above [:)]
Dec 29, 2006 12:38 PM|martinhn|LINK
It won't really do the trick.
The first link just makes the Image better quality. The second one doesn't really work. This line:
ncp.Entries[CurrentEntry] = Color.FromArgb(0, cp.Entries[CurrentEntry]); does not work.
It throws an index out of bounds exception on the cp.Entries. I set the cp = canvas.Pallete... But the Entries collection is null!
Another thing. I'm not interested in making a single color transparent. I want to make the entire Image transparent by a percentage. I want to be able to pass any sort of Image through the function, an get an Image in return that is transparent...
Have you got any other ideas? Links?
Dec 29, 2006 03:25 PM|martinhn|LINK
Right now, I'm just trying to get a 300x300 pixel Image with a simple rectangle placed in the upper-left corner, to be transparent. Using the article from the Microsoft Knowledge Base, I can get it transparent. But it is completely transparent. I want something
Here is my code form the Generic Handler (GenerateImage.ashx)
public class GenerateImage : IHttpHandler
public void ProcessRequest(HttpContext context)
// Set the HTTP MIME Type
context.Response.ContentType = "image/gif";
// Disable caching!
// Sets the BufferOutput property to true so that the entire page will be processed
// before any content is sent to the requesting client.
context.Response.BufferOutput = true;
Bitmap bmp = new Bitmap(300, 300, PixelFormat.Format32bppArgb);
Graphics d = Graphics.FromImage((Image)bmp);
d.FillRectangle(new SolidBrush(Color.FromArgb(50, Color.Red)), new Rectangle(0, 0, 100, 100));
bmp = Util.SaveGIFWithNewColorTable(bmp, 256, true);
// Send the response to the client
public bool IsReusable
And the function inside the Util class (SaveGIFWithNewColorTable) looks like this:
public static Bitmap SaveGIFWithNewColorTable(Image image, uint nColors, bool fTransparent)
// GIF codec supports 256 colors maximum, monochrome minimum.
if (nColors > 256)
nColors = 256;
if (nColors < 2)
nColors = 2;
// Make a new 8-BPP indexed bitmap that is the same size as the source image.
int Width = image.Width;
int Height = image.Height;
// Always use PixelFormat8bppIndexed because that is the color
// table-based interface to the GIF codec.
Bitmap bitmap = new Bitmap(Width,
// Create a color palette big enough to hold the colors you want.
ColorPalette pal = GetColorPalette(nColors);
// Initialize a new color table with entries that are determined
// by some optimal palette-finding algorithm; for demonstration
// purposes, use a grayscale.
for (uint i = 0; i < nColors; i++)
uint Alpha = 0xFF; // Colors are opaque.
uint Intensity = i * 0xFF / (nColors - 1); // Even distribution.
// The GIF encoder makes the first entry in the palette
// that has a ZERO alpha the transparent color in the GIF.
// Pick the first one arbitrarily, for demonstration purposes.
if (i == 0 && fTransparent) // Make this color index...
Alpha = 0; // Transparent
// Create a gray scale for demonstration purposes.
// Otherwise, use your favorite color reduction algorithm
// and an optimum palette for that algorithm generated here.
// For example, a color histogram, or a median cut palette.
pal.Entries[i] = Color.FromArgb((int)Alpha, pal.Entries[i]);
// Set the palette into the new Bitmap object.
bitmap.Palette = pal;
// Use GetPixel below to pull out the color data of Image.
// Because GetPixel isn't defined on an Image, make a copy
// in a Bitmap instead. Make a new Bitmap that is the same size as the
// image that you want to export. Or, try to
// interpret the native pixel format of the image by using a LockBits
// call. Use PixelFormat32BppARGB so you can wrap a Graphics
// around it.
Bitmap BmpCopy = new Bitmap(Width,
Graphics g = Graphics.FromImage(BmpCopy);
g.PageUnit = GraphicsUnit.Pixel;
// Transfer the Image to the Bitmap
g.DrawImage(image, 0, 0, Width, Height);
// g goes out of scope and is marked for garbage collection.
// Force it, just to keep things clean.
// Lock a rectangular portion of the bitmap for writing.
Rectangle rect = new Rectangle(0, 0, Width, Height);
bitmapData = bitmap.LockBits(
// Write to the temporary buffer that is provided by LockBits.
// Copy the pixels from the source image in this loop.
// Because you want an index, convert RGB to the appropriate
// palette index here.
IntPtr pixels = bitmapData.Scan0;
// Get the pointer to the image bits.
// This is the unsafe operation.
if (bitmapData.Stride > 0)
pBits = (byte*)pixels.ToPointer();
// If the Stide is negative, Scan0 points to the last
// scanline in the buffer. To normalize the loop, obtain
// a pointer to the front of the buffer that is located
// (Height-1) scanlines previous.
pBits = (byte*)pixels.ToPointer() + bitmapData.Stride * (Height - 1);
uint stride = (uint)Math.Abs(bitmapData.Stride);
for (uint row = 0; row < Height; ++row)
for (uint col = 0; col < Width; ++col)
// Map palette indexes for a gray scale.
// If you use some other technique to color convert,
// put your favorite color reduction algorithm here.
Color pixel; // The source pixel.
// The destination pixel.
// The pointer to the color index byte of the
// destination; this real pointer causes this
// code to be considered unsafe.
byte* p8bppPixel = pBits + row * stride + col;
pixel = BmpCopy.GetPixel((int)col, (int)row);
// Use luminance/chrominance conversion to get grayscale.
// Basically, turn the image into black and white TV.
// Do not calculate Cr or Cb because you
// discard the color anyway.
// Y = Red * 0.299 + Green * 0.587 + Blue * 0.114
// This expression is best as integer math for performance,
// however, because GetPixel listed earlier is the slowest
// part of this loop, the expression is left as
// floating point for clarity.
double luminance = (pixel.R * 0.299) +
(pixel.G * 0.587) +
(pixel.B * 0.114);
// Gray scale is an intensity map from black to white.
// Compute the index to the grayscale entry that
// approximates the luminance, and then round the index.
// Also, constrain the index choices by the number of
// colors to do, and then set that pixel's index to the
// byte value.
*p8bppPixel = (byte)(luminance * (nColors - 1) / 255 + 0.5);
} /* end loop for col */
} /* end loop for row */
} /* end unsafe */
// To commit the changes, unlock the portion of the bitmap.
//// Bitmap goes out of scope here and is also marked for
//// garbage collection.
//// Pal is referenced by bitmap and goes away.
//// BmpCopy goes out of scope here and is marked for garbage
//// collection. Force it, because it is probably quite large.
//// The same applies to bitmap.
public static ColorPalette GetColorPalette(uint nColors)
// Assume monochrome image.
PixelFormat bitscolordepth = PixelFormat.Format1bppIndexed;
ColorPalette palette; // The Palette we are stealing
Bitmap bitmap; // The source of the stolen palette
// Determine number of colors.
if (nColors > 2)
bitscolordepth = PixelFormat.Format4bppIndexed;
if (nColors > 16)
bitscolordepth = PixelFormat.Format8bppIndexed;
// Make a new Bitmap object to get its Palette.
bitmap = new Bitmap(1, 1, bitscolordepth);
palette = bitmap.Palette; // Grab the palette
bitmap.Dispose(); // cleanup the source Bitmap
return palette; // Send the palette back
Take a look at line 36 in the above code (For the SaveGIFWithNewColorTable method)... Here Aplha is set to 0. That makes the Image completely transparent. However, if i set Aplha to 1 there is no transparency what so ever! I thought you were able to increase
and decrease the transparency level, but that doesn't seem to be the occasion...
The result I get from the code above, is a GIF image, which is 300x300 pixels. The background is completely transparent, and at the top-left-corner, there's a red rectangle which is 100x100 pixels...
The perfect situation, would be an image with a black background, and the rectangle - with the general transparency level (or opacity) set to around 50%...
Dec 30, 2006 02:15 PM|martinhn|LINK
Ok, so I found a solution to the problem.
I went back to an earlier idea, which is to create the Image with C# without any transparency, and then use the CSS filter (aplha filter / opacity) to achieve transparency. This works fine, but is it compatible with most browsers?
I used this article:
The code for the CSS filter is: <img src="ball.gif" style="filter:alpha(opacity=50); -moz-opacity:0.5">
Can you count on that one?
Dec 31, 2006 07:35 AM|Hope4sun|LINK
Sorry my early post was a little of matter, was a busy day in the office, and i think i ended up pasting a wrong link in, thougu GDI+ is not one of my strong points i took a look at just getting a transparent image back to the browser with the code below,
it is working as such but only appears to effect the image its drawn onto and not like opacity CSS, which is a good soultion as long as you cover all the different browser implementaions.
System.Drawing.Image canvas = System.Drawing.Image.FromFile(Server.MapPath("images/footer.jpg"));
System.Drawing.Image otemp = new Bitmap(canvas.Width, canvas.Height);
oEffect = Graphics.FromImage(otemp);
// oEffect.Clear(Color.Red); you can see the back color through the image if you use anything other than .Transparent
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 = cm.Matrix11 = cm.Matrix22 = cm.Matrix44 = 1;
cm.Matrix33 = (float)40/100; // The first value effects the transparent value ##/100
ImageAttributes ia = new ImageAttributes();
oEffect.DrawImage(canvas, new Rectangle(0,0,canvas.Width, canvas.Height),0,0,canvas.Width, canvas.Height, GraphicsUnit.Pixel,ia);
Sounds like you'be sorted it, but thought this may help, and did'nt want to just walk on this one [:)]