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

J’ai une page multi-navigateur qui affiche du texte vertical.

En tant que bidule laid pour que le texte soit rendu verticalement dans tous les navigateurs, j’ai créé un gestionnaire de page personnalisé qui renvoie un fichier PNG avec le texte dessiné verticalement.

Voici mon code de base (C # 3, mais de petites modifications à n’importe quelle version inférieure à 1):

Font f = GetSystemConfiguredFont(); //this sets the text to be rotated 90deg clockwise (ie down) SsortingngFormat ssortingngFormat = new SsortingngFormat { FormatFlags = SsortingngFormatFlags.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 ). MeasureSsortingng( text, f, 25, ssortingngFormat ); 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.DrawSsortingng( text, f, Brushes.Black, 0f, 0f, ssortingngFormat ); //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 à ce que je veux, sauf que la transparence est basée sur un index. Lorsque je retourne un fichier PNG, il pourrait prendre en charge une transparence alpha appropriée.

Est-il possible de le faire dans .net?


Grâce à Vlix (voir commentaires), j’ai apporté quelques modifications, même si ce n’est toujours pas correct:

 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.DrawSsortingng( text, f, Brushes.Black, 0f, 0f, ssortingngFormat ); //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 apparaît en bloc – comme s’il avait toujours les bords jaggie mais sur un arrière-plan noir.

Est-ce un bug avec .Net / GDI +? J’ai déjà constaté que cela échouait même pour les transparents d’index pour les gifs, donc je n’ai pas beaucoup de confiance pour le faire.

Cette image montre les deux façons dont cela se passe mal:

comparaison de texte verticale

L’image du haut le montre sans fond blanc ni appel MakeTransparent . La seconde avec l’arrière-plan rempli de blanc puis MakeTransparent appelé pour append la transparence d’index.

Aucune de celles-ci n’est correcte – la deuxième image présente des décalages de crénelage en blanc que je ne souhaite pas, la première semble être solidement aliasée contre le noir.

Pour corriger le texte “bloc”, ne pouvez-vous pas simplement faire …

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

après cette ligne …

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

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

Vous pouvez utiliser la méthode LockBits sur votre bitmap pour renvoyer un object BitmapData et définir vous-même l’alpha pour chaque pixel (vous pouvez également utiliser GetPixel et SetPixel, mais ces méthodes sont incroyablement lentes). Voir cette réponse .

Je sais que cela fonctionne à coup sûr, car lorsque j’ai commencé à utiliser la technique, je définissais la valeur alpha à 0, de sorte qu’aucune des couleurs que je définissais ne soit visible.

Edit: voici un exemple d’effet fisheye, entièrement réalisé en .NET (à l’aide de LockBits):

texte alt http://soffr.miximages.com/c%23/www.freeimagehosting.net

Pour l’anticrénelage de texte, jouez avec les valeurs de Graphics.TextRenderingHint. Je conseillerais de ne pas utiliser ClearType, car cela ne s’affichera bien que sur les moniteurs LCD (pas de tube cathodique) et pourrait ne pas fonctionner en raison de la rotation.

PS c’est Vilx, pas Vlix. :RÉ

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

Mélange alpha par pixel en C #

Désolé, je n’ai pas lu votre question assez attentivement.

Je sais que j’ai réussi à dessiner du texte pivoté sur un arrière-plan coloré sans voir aucun des effets de repliement dans vos exemples. Lorsque je suis revenu consulter mon code, j’ai réalisé que je dessinais le texte pivoté à l’aide d’une police logique, parfaitement intégrée dans l’espace de noms Microsoft.WindowsCE.Forms. Cette technique définit l’angle de dessin en tant que propriété de la police logique (afin de ne pas appeler TranslateTransform ou RotateTransform).

En dehors du monde Windows CE, vous devez PInvoke pour créer une police logique (je ne l’ai jamais fait et je ne pouvais pas trouver un bon exemple rapidement). Je ne sais pas si cela fonctionnerait bien, mais je suis certain que le texte tourné sera tourné sans les effets de repliement étranges que vous voyez. Je pense que c’est un bogue de GDI + (ou quelque chose qu’ils ne pensaient pas que quelqu’un utiliserait vraiment).

Une approche alternative qui pourrait même mieux fonctionner que la police logique est de dessiner le texte normalement sur un fond de rectangle coloré (juste assez grand pour contenir le texte), puis de faire pivoter et copier le rectangle sur votre image principale. Graphics.DrawImage ne semble pas pouvoir effectuer de rotation, mais cet effet est facile à implémenter à l’aide de LockBits.

Il s’avère que Microsoft dispose d’une nouvelle bibliothèque d’images dynamics pour le Web dans le contenu Asp.Net sur CodePlex:

http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449

Malheureusement, c’est un peu trop pour ce que je veux. En utilisant un code non sécurisé, je peux utiliser ma propre transparence alpha, mais c’est beaucoup trop lent, étant donné que ce code est utilisé dans le cadre d’une application Web à usage intensif.

Est-ce juste un bogue dans l’implémentation GDI + .Net de MS?

Vous devez au moins spécifier un format de pixel 32 bits (ex: PixelFormat.Format32bppArgb) lors de la création de votre bitmap, sinon GDI + ne peut pas gérer la transparence.

Pour ajuster le fichier résultant lors de la sauvegarde, vous pouvez utiliser Enregistrer avec ImageCodecInfo et EncoderParameters.

Vous pouvez également rendre le texte au format PNG non transparent, mais en utilisant une couleur d’arrière-plan (au lieu de blanc) qui correspond à la couleur d’arrière-plan de la cellule.