Pouvez-vous faire un alpha transparent PNG avec C#?
j'ai une page multi-navigateur qui montre du texte vertical.
comme un hack laid pour obtenir du texte à rendre verticalement dans tous les navigateurs, j'ai créé un gestionnaire de page personnalisé qui renvoie un PNG avec le texte dessiné verticalement.
Voici mon code de base (C#3, mais de petits changements à toute autre version vers le bas à 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 à ce que je veux, sauf que la transparence est basée sur un index. Comme je suis retourner un PNG pourrait supporter une transparence alpha correcte.
y a-t-il un moyen de faire ça à .net?
merci à Vlix (voir les commentaires) j'ai fait quelques changements, mais ce n'est toujours pas juste:
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 semble bloqué - comme s'il avait encore les bords de jaggie mais sur un fond noir.
est-ce un bug avec .Net/GDI+? J'ai déjà constaté qu'il ne fonctionne pas, même pour indexer les transparences pour les GIF, donc je n'ai pas beaucoup confiance en lui.
cette image montre les deux façons dont cela va mal:
l'image du haut la montre sans fond blanc ou appel MakeTransparent
. Le second avec le fond rempli de blanc et ensuite MakeTransparent
appelé pour ajouter la transparence de l'index.
n'est correct - la deuxième image a des jaggies d'aliasing blancs que je ne veux pas, la première semble être solidement aliasé contre Noir.
9 réponses
pour corriger le texte "blockiness", vous ne pouvez pas juste faire...
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
après cette ligne...
Graphics g = Graphics.FromImage( (Image) image );
IIRC vous devez spécifier le format de pixel dans le constructeur bitmap.
vous pouvez utiliser la méthode LockBits sur votre Bitmap pour retourner un objet BitmapData, et définir L'Alpha pour chaque pixel vous-même (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, parce que quand j'ai commencé à utiliser la technique, je définissais la valeur alpha à 0, donc aucune des couleurs que je définissais n'était visible.
Edit: voici un échantillon d'un effet de lentille fisheye, entièrement réalisé en filet (à L'aide de LockBits):
alt texte http://www.freeimagehosting.net/uploads/21ca8300cc.jpg
pour le texte antialiasing jouer avec des valeurs dans les graphiques.TextRenderingHint. Je conseillerais de ne pas utiliser ClearType, parce que cela ne se verra nice sur les moniteurs LCD (pas CRT), et pourrait ne pas fonctionner en raison de la rotation.
P.S. C'est Vilx-, pas Vlix. : D
peut-être que vous pouvez trouver la réponse dans le code source de cet article de Codeprojet:
Désolé, je n'ai pas lu votre question assez attentivement.
je sais que j'ai réussi à dessiner un texte tournant sur un fond coloré sans voir aucun des effets d'alias dans vos exemples. Quand je suis retourné pour regarder mon code, j'ai réalisé que je dessinais le texte tournant en utilisant une police logique, qui est joliment enveloppé dans le Microsoft.WindowsCE.Les formes de l'espace de noms. Cette technique définit l'angle de dessin comme une propriété de la police logique (donc vous ne appel TranslateTransform ou RotateTransform).
en dehors du Monde Windows CE, vous devez PInvoke pour créer une police logique (je n'ai jamais fait cela et je n'ai pas pu trouver un bon exemple rapidement). Je ne sais pas si ça marcherait bien, mais je suis sûr que ça fera tourner le texte sans les effets d'alias bizarres que tu vois. Je pense que c'est un bug dans GDI+ (ou juste quelque chose qu'ils ne pensaient pas que quelqu'un utiliserait).
An l'approche alternative qui pourrait même fonctionner mieux que la police logique est de dessiner le texte normalement sur un fond de rectangle coloré (juste assez grand pour tenir le texte), puis tourner-et-copier le rectangle sur votre image principale. Graphique.DrawImage ne semble pas capable de faire de rotation, mais cet effet est facile à mettre en œuvre à L'aide de LockBits.
il s'avère que Microsoft ont une nouvelle bibliothèque d'image dynamique pour le web dans le cadre de la Asp.Net contenu de CodePlex:
http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449
malheureusement, c'est un peu trop pour ce que je veux. En utilisant du code dangereux, je peux lancer ma propre transparence alpha, mais c'est beaucoup trop lent étant donné l'utilisation de ce code dans le cadre d'une application web à forte utilisation.
est-ce juste un bug 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 Save avec ImageCodecInfo et EncoderParameters.
ou, vous pouvez simplement rendre le texte à un PNG non transparent, mais utilisez une couleur de fond (au lieu de blanc) qui correspond à la couleur de fond de la cellule.