Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在透明像素上使用抽绳渲染错误的文本_C#_Winforms_Gdi+_System.drawing_Drawstring - Fatal编程技术网

C# 在透明像素上使用抽绳渲染错误的文本

C# 在透明像素上使用抽绳渲染错误的文本,c#,winforms,gdi+,system.drawing,drawstring,C#,Winforms,Gdi+,System.drawing,Drawstring,在将文本渲染为位图时,我发现在具有非不透明alpha的区域顶部渲染时,文本看起来非常糟糕。随着底层像素变得更加透明,问题会越来越严重。如果我不得不猜测,我会说,当底层像素是透明的时,文本渲染器会将任何抗锯齿的“灰色”像素绘制为纯黑色 以下是一些屏幕截图: 在透明像素上绘制的文本: 在半透明像素上绘制的文本: 在不透明像素上绘制的文本: 以下是用于呈现文本的代码: g.SmoothingMode = SmoothingMode.HighQuality; g.DrawString("Press

在将文本渲染为位图时,我发现在具有非不透明alpha的区域顶部渲染时,文本看起来非常糟糕。随着底层像素变得更加透明,问题会越来越严重。如果我不得不猜测,我会说,当底层像素是透明的时,文本渲染器会将任何抗锯齿的“灰色”像素绘制为纯黑色

以下是一些屏幕截图:

在透明像素上绘制的文本:

在半透明像素上绘制的文本:

在不透明像素上绘制的文本:

以下是用于呈现文本的代码:

g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawString("Press the spacebar", Font, Brushes.Black, textLeft, textTop);

第一个输出是在黑色背景(可能是Color.Transparent)上绘制黑色文本时得到的结果。第二张画在几乎是黑色的背景上。第三个是在显示的相同背景上绘制的

在透明背景上时,抗锯齿无法工作。当文本以不同背景显示时,用于抗锯齿像素的颜色不会将字母形状混合到背景中。这些像素现在将变得非常明显,并使文本看起来非常糟糕

请注意,SmoothingMode不会影响文本输出。如果使用质量较低的TextRenderingHint,背景颜色为灰色,alpha值为零,看起来就不会那么糟糕了。只有TextRenderingHint.SingleBitPerPixelGridFit可以避免所有抗锯齿问题


很难找到一个完美的解决方案。Vista在窗口标题栏上的玻璃效果使用非常精细的着色,为文本提供定义良好的背景色。您需要SysInternals的ZoomIt工具才能真正看到它。具有非零iGlowSize的DrawThemeTextEx()函数。

我用于解决此问题的选项是:

Graphics graphics = new Graphics();
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
TextRenderingHint中还有其他一些有用的选项


希望它有帮助

如果您正在寻找比GDI+在默认情况下更好地保留抗锯齿的功能,您可以调用
Graphics。使用色度键清除
,然后手动删除产生的色度瑕疵。(见和。)

以下是我最终解决类似问题的方式:

static Bitmap TextToBitmap(string text, Font font, Color foregroundColor)
{
  SizeF textSize;

  using ( var g = Graphics.FromHwndInternal(IntPtr.Zero) )
    textSize = g.MeasureString(text, font);

  var image = new Bitmap((int)Math.Ceiling(textSize.Width), (int)Math.Ceiling(textSize.Height));
  var brush = new SolidBrush(foregroundColor);

  using ( var g = Graphics.FromImage(image) )
  {
    g.Clear(Color.Magenta);
    g.SmoothingMode = SmoothingMode.AntiAlias;
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
    g.DrawString(text, font, brush, 0, 0);
    g.Flush();
  }

  image.MakeTransparent(Color.Magenta);

  // The image now has a transparent background, but around each letter are antialiasing artifacts still keyed to magenta.  We need to remove those.
  RemoveChroma(image, foregroundColor, Color.Magenta);
  return image;
}

static unsafe void RemoveChroma(Bitmap image, Color foregroundColor, Color chroma)
{
  if (image == null) throw new ArgumentNullException("image");
  BitmapData data = null;

  try
  {
    data = image.LockBits(new Rectangle(Point.Empty, image.Size), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

    for ( int y = data.Height - 1; y >= 0; --y )
    {
      int* row = (int*)(data.Scan0 + (y * data.Stride));
      for ( int x = data.Width - 1; x >= 0; --x )
      {
        if ( row[x] == 0 ) continue;
        Color pixel = Color.FromArgb(row[x]);

        if ( (pixel != foregroundColor) &&
             ((pixel.B >= foregroundColor.B) && (pixel.B <= chroma.B)) &&
             ((pixel.G >= foregroundColor.G) && (pixel.G <= chroma.G)) &&
             ((pixel.R >= foregroundColor.R) && (pixel.R <= chroma.R)) )
        {
          row[x] = Color.FromArgb(
            255 - ((int)
              ((Math.Abs(pixel.B - foregroundColor.B) +
                Math.Abs(pixel.G - foregroundColor.G) +
                Math.Abs(pixel.R - foregroundColor.R)) / 3)),
            foregroundColor).ToArgb();
        }
      }
    }
  }
  finally
  {
    if (data != null) image.UnlockBits(data);
  }
}
静态位图文本到位图(字符串文本、字体字体、颜色foregroundColor)
{
SizeF textSize;
使用(var g=Graphics.fromHwnInternal(IntPtr.Zero))
textSize=g.MeasureString(文本,字体);
var image=新位图((int)数学天花板(textSize.Width),(int)数学天花板(textSize.Height));
var笔刷=新的SolidBrush(foregroundColor);
使用(var g=Graphics.FromImage(image))
{
g、 清晰(颜色为洋红色);
g、 SmoothingMode=SmoothingMode.AntiAlias;
g、 插值模式=插值模式。高质量双三次;
g、 PixelOffsetMode=PixelOffsetMode.HighQuality;
g、 抽绳(文本、字体、画笔、0、0);
g、 冲洗();
}
图像。使透明(颜色为洋红色);
//图像现在有一个透明的背景,但是每个字母周围都有抗锯齿伪影,仍然是洋红色。我们需要删除这些伪影。
去除色素(图像,前底色,颜色.品红色);
返回图像;
}
静态消除色度(位图图像、彩色背景色、彩色色度)
{
如果(image==null)抛出新的ArgumentNullException(“image”);
BitmapData数据=null;
尝试
{
数据=image.LockBits(新矩形(Point.Empty,image.Size),ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb);
对于(int y=data.Height-1;y>=0;--y)
{
int*行=(int*)(data.Scan0+(y*data.Stride));
对于(int x=data.Width-1;x>=0;--x)
{
如果(行[x]==0)继续;
颜色像素=Color.FromArgb(行[x]);
if((像素!=foregroundColor)&&

((pixel.B>=foregroundColor.B)和&(pixel.B=foregroundColor.G)和&(pixel.G=foregroundColor.R)和&(pixel.R对此有一个非常简单的答案

g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
如果在呈现文本之前设置此选项,则文本将清晰显示。此外,此方法支持更多字体大小(默认值仅为56)


感谢您阅读本文。

我相信结果也将取决于ClearType是否启用。看起来您不是在“清除”(或者更确切地说是失效)透明背景。有完整源代码的最终解决方案吗?你能上传包含到堆栈溢出的图像吗?它们不再从Dropbox中下载。呃。我想我可以在临时位图上将黑色文本绘制为白色,将白色转换为透明,将灰色转换为半透明黑色,然后将其绘制到最终的bitmap。我将尝试不同的文本渲染提示。否则,我认为部分背景透明度的效果还不错。不过有一件事——在每种情况下,背景都是相同的颜色(灰白色)使用不同的透明度,所以我不希望文本以“有效”的黑色背景色绘制。不确定你的意思。关键问题是GDI看不到透明度,它可以看到透明颜色的RGB值。颜色。透明是一个非常糟糕的选择,它的RGB值为零。黑色。我的意思是背景是p用灰白色绘制,带有alpha成分。不确定从何处获得颜色。透明来自。@mack-是的,花太多时间在计算机上的人通常会遇到这种情况。这在家庭中不起作用,很好。请求很简单,请删除答案标记。SingleBitPerPixelGridFit指针+1可以绕过这个问题-谢谢。虽然这是一个非常老的问题,我还没有测试过这个答案,但将答案换成了这个。user3470185的答案(g.TextRenderingHint=Drawing.Text.TextRenderingHint.AntiAliasGridFit)会产生更好的结果。这适用于我正在修改的控件(但我使用
textrendinghint.ClearTypeGridFit
只是为了修复应用于该控件文本的默认错误提示)