34

我有一个显示垂直文本的多浏览器页面。

作为让文本在所有浏览器中垂直呈现的丑陋技巧,我创建了一个自定义页面处理程序,它返回一个带有垂直绘制文本的 PNG。

这是我的基本代码(C#3,但对任何其他版本进行了小改动,直到 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 );
    }
}

这会创建一个看起来像我想要的图像,除了透明度是基于索引的。当我返回 PNG 时,它可以支持适当的 alpha 透明度。

有没有办法在.net中做到这一点?


感谢 Vlix(见评论)我做了一些改变,虽然它仍然不正确:

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

现在 alpha 似乎可以工作了,但文本看起来是块状的 - 好像它仍然有锯齿状的边缘,但在黑色背景下。

这是 .Net/GDI+ 的一些错误吗?我已经发现它甚至无法用于 gif 的索引透明胶片,所以我对它没有多大信心。

此图像显示了出错的两种方式:

垂直文本比较

顶部图像显示它没有白色背景或MakeTransparent呼叫。第二个用背景填充白色然后MakeTransparent调用添加索引透明度。

这些都不正确 - 第二个图像有我不想要的白色锯齿锯齿,第一个图像似乎与黑色完全混叠。

4

9 回答 9

14

要修复文本“块状”,你不能这样做......

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

在这条线之后...

Graphics g = Graphics.FromImage( (Image) image );
于 2009-05-04T14:44:05.483 回答
6

IIRC 您需要在位图构造函数中指定 PixelFormat。

于 2008-12-23T11:41:43.320 回答
6

您可以使用 Bitmap 上的 LockBits 方法返回一个 BitmapData 对象,并自己设置每个像素的 Alpha(您也可以使用 GetPixel 和 SetPixel,但这些方法非常慢)。看到这个答案

我知道这肯定有效,因为当我第一次开始使用该技术时,我将 alpha 值设置为 0,所以我设置的颜色都不可见。

编辑:这是鱼眼镜头效果的示例,完全在 .NET 中完成(使用 LockBits):

替代文字 http://www.freeimagehosting.net/uploads/21ca8300cc.jpg

于 2008-12-23T12:22:19.243 回答
5

对于文本抗锯齿,请使用 Graphics.TextRenderingHint 中的值。我建议不要使用 ClearType,因为它只会在 LCD 显示器(而不是 CRT)上显示得很好,并且可能由于旋转而无法工作。

PS这是 Vilx-,不是 Vlix。:D

于 2008-12-23T12:49:06.070 回答
1

或许你可以在这篇 CodeProject 文章的源码中找到答案:

C# 中的每像素 Alpha 混合

于 2008-12-23T11:47:33.247 回答
1

对不起,我没有仔细阅读你的问题。

我知道我已经成功地在彩色背景上绘制了旋转文本,而在您的示例中没有看到任何锯齿效果。当我回去查看我的代码时,我意识到我正在使用一种逻辑字体绘制旋转的文本,该字体很好地包装在 Microsoft.WindowsCE.Forms 命名空间中。此技术将绘制角度设置为逻辑字体的属性(因此您无需调用 TranslateTransform 或 RotateTransform)。

在 Windows CE 世界之外,您必须 PInvoke 来创建逻辑字体(我从未这样做过,而且我无法快速找到一个好的示例)。我不知道这会表现如何,但我确信它会绘制旋转文本,而不会出现您所看到的奇怪的锯齿效果。我认为这肯定是 GDI+ 中的一个错误(或者只是他们认为没有人会真正使用的东西)。

另一种可能比逻辑字体表现更好的替代方法是在彩色矩形背景上正常绘制文本(刚好足以容纳文本),然后将矩形旋转并复制到主图像上。Graphics.DrawImage 似乎无法进行旋转,但使用 LockBits 很容易实现此效果。

于 2008-12-24T13:40:27.620 回答
0

事实证明,作为 CodePlex 上 Asp.Net 内容的一部分,Microsoft 有一个新的 Web 动态图像库:

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

不幸的是,我想要的有点多。使用不安全的代码,我可以滚动自己的 alpha 透明度,但考虑到此代码用作高使用率 Web 应用程序的一部分,这太慢了。

这只是 MS 的 GDI+ .Net 实现中的一个错误吗?

于 2008-12-24T11:15:51.123 回答
0

创建位图时至少应指定 32 位像素格式(例如:PixelFormat.Format32bppArgb),否则 GDI+ 无法管理透明度。

要在保存时调整生成的文件,可以将 Save 与 ImageCodecInfo 和 EncoderParameters 一起使用。

于 2008-12-24T12:39:55.213 回答
0

或者,您可以只将文本呈现为不透明的 PNG,但使用与单元格背景颜色匹配的背景颜色(而不是白色)。

于 2008-12-24T14:18:05.187 回答