34 votes

Pouvez-vous créer un PNG transparent alpha avec C #?

J'ai un multi-navigateur page qui affiche le texte vertical.

Comme un vilain hack pour obtenir un texte pour rendre verticalement dans tous les navigateurs, j'ai créé une page personnalisée gestionnaire qui renvoie une image PNG avec le texte élaboré à la verticale.

Voici mon code de base (C#3, mais de petits changements à n'importe quelle autre version à 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 );
    }
}

Cela crée une image qui ressemble à la façon dont je le veux, sauf que la transparence est basée sur un index. Comme je suis de retour PNG il pourrait soutenir une bonne transparence alpha.

Est-il un moyen de le faire dans .net?


Grâce à Vlix (voir les commentaires) j'ai fait quelques changements, mais il n'est toujours pas le droit:

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 );
    }
}

Maintenant l'alpha semble fonctionner, mais le texte s'affiche sous forme de blocs - comme si elle a encore le jaggie bords, mais sur un fond noir.

Est-ce que certains bug avec .Net/GDI+? J'ai déjà trouvé qu'il ne parvient pas pour le même indice de transparences pour les gifs, donc je n'ai pas beaucoup confiance en elle elle.

Cette image montre les deux façons, cela ne va pas:

vertical text comparison

L'image du haut montre avec pas de fond blanc ou MakeTransparent appel. La seconde, avec le fond en blanc et ensuite, MakeTransparent appelé pour ajouter l'indice de la transparence.

N'est - il correct, la deuxième image est blanche aliasing jaggies que je ne veux pas, la première semble être solidement alias contre le noir.

14voto

fallenidol Points 494

Pour corriger le texte "blockiness", vous ne pouvez pas simplement faire ...

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

après cette ligne ...

 Graphics g = Graphics.FromImage( (Image) image );
 

6voto

leppie Points 67289

IIRC vous devez spécifier le PixelFormat dans le constructeur bitmap.

6voto

MusiGenesis Points 49273

Vous pouvez utiliser la méthode LockBits sur votre Bitmap pour retourner un objet BitmapData, et de régler la transparence de chaque pixel de vous-même (vous pouvez également utiliser la méthode GetPixel et SetPixel, mais ces méthodes sont incroyablement lent). Voir cette réponse.

Je sais que cela fonctionne pour vous, parce que quand j'ai commencé à utiliser la technique j'ai été réglage de la valeur alpha à 0, donc aucun des couleurs, j'ai été mise en scène étaient visibles.

Edit: voici un exemple de l'effet fisheye, fait entièrement en .NET (à l'aide de LockBits):

alt text

5voto

Vilx- Points 37939

Pour l'anticrénelage de texte, jouez avec les valeurs de Graphics.TextRenderingHint. Je conseillerais de ne pas utiliser ClearType, car cela n'apparaîtra bien que sur les moniteurs LCD (pas CRT), et pourrait ne pas fonctionner en raison de la rotation.

PS C'est Vilx, pas Vlix. :RÉ

1voto

splattne Points 48126

Vous pouvez peut-être trouver la réponse dans le code source de cet article CodeProject:

Mélange Alpha par pixel en C #

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X