Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you make an alpha transparent PNG with C#?

Tags:

c#

.net

gdi+

I have a multi-browser page that shows vertical text.

As an ugly hack to get text to render vertically in all browsers I've created a custom page handler that returns a PNG with the text drawn vertically.

Here's my basic code (C#3, but small changes to any other version down to 1):

Font f = GetSystemConfiguredFont(); //this sets the text to be rotated 90deg clockwise (i.e. down) StringFormat stringFormat = new StringFormat { FormatFlags = StringFormatFlags.DirectionVertical };  SizeF size; // creates 1Kx1K image buffer and uses it to find out how bit the image needs to be to fit the text using ( Image imageg = (Image) new Bitmap( 1000, 1000 ) )     size = Graphics.FromImage( imageg ).         MeasureString( text, f, 25, stringFormat );  using ( Bitmap image = new Bitmap( (int) size.Width, (int) size.Height ) ) {     Graphics g = Graphics.FromImage( (Image) image );     g.FillRectangle( Brushes.White, 0f, 0f, image.Width, image.Height );     g.TranslateTransform( image.Width, image.Height );     g.RotateTransform( 180.0F ); //note that we need the rotation as the default is down      // draw text     g.DrawString( text, f, Brushes.Black, 0f, 0f, stringFormat );      //make be background transparent - this will be an index (rather than an alpha) transparency     image.MakeTransparent( Color.White );      //note that this image has to be a PNG, as GDI+'s gif handling renders any transparency as black.     context.Response.AddHeader( "ContentType", "image/png" );     using ( MemoryStream memStream = new MemoryStream() )     {         image.Save( memStream, ImageFormat.Png );         memStream.WriteTo( context.Response.OutputStream );     } } 

This creates an image that looks how I want it to, except that the transparency is index based. As I'm returning a PNG it could support a proper alpha transparency.

Is there any way to do this in .net?


Thanks to Vlix (see comments) I've made some changes, though it still isn't right:

using ( Bitmap image = new Bitmap( (int) size.Width, (int) size.Height, PixelFormat.Format32bppArgb ) ) {     Graphics g = Graphics.FromImage( (Image) image );     g.TranslateTransform( image.Width, image.Height );     g.RotateTransform( 180.0F ); //note that we need the rotation as the default is down      // draw text     g.DrawString( text, f, Brushes.Black, 0f, 0f, stringFormat );      //note that this image has to be a PNG, as GDI+'s gif handling renders any transparency as black.     context.Response.AddHeader( "ContentType", "image/png" );     using ( MemoryStream memStream = new MemoryStream() )     {         //note that context.Response.OutputStream doesn't support the Save, but does support WriteTo         image.Save( memStream, ImageFormat.Png );         memStream.WriteTo( context.Response.OutputStream );     } } 

Now the alpha appears to work, but the text appears blocky - as if it still has the jaggie edges but against a black background.

Is this some bug with .Net/GDI+? I've already found that it fails for even index transparencies for gifs, so I don't have much confidence it it.

This image shows the two ways this goes wrong:

vertical text comparison

The top image shows it with no white background or MakeTransparent call. The second with the background filled with white and then MakeTransparent called to add the index transparency.

Neither of these is correct - the second image has white aliasing jaggies that I don't want, the first appears to be solidly aliased against black.

like image 821
Keith Avatar asked Dec 23 '08 11:12

Keith


People also ask

Does PNG support alpha transparency?

PNG files support transparency, but JPGs do not. If you save a PNG image as a JPG file, the JPG format doesn't know what to do with the alpha channel. That's why all the transparency turns into an opaque white background instead.


2 Answers

To fix the text "blockiness", can't you just do...

g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; 

after this line...

Graphics g = Graphics.FromImage( (Image) image ); 
like image 63
pmcilreavy Avatar answered Sep 28 '22 17:09

pmcilreavy


IIRC you need to specify the PixelFormat in the bitmap constructor.

like image 45
leppie Avatar answered Sep 28 '22 16:09

leppie