图片上有不同颜色的文字

问题描述 投票:0回答:2

我试图在图像上绘制文本,其中某些单词必须以不同的颜色突出显示。 我在 SO 中找到了一个解决方案,它使用 TextRenderer.DrawText 和 MeasureCharacterRanges 拆分字符串中的单词,如果单词与关键字匹配,则用不同的颜色单独呈现它们。

    private void AddText1(string txt, Graphics g, Rectangle rect)
    {
        TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter |
                    TextFormatFlags.NoPadding | TextFormatFlags.NoClipping;

        using (StringFormat format = new StringFormat())
        {
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            MatchCollection mc = Regex.Matches(txt, @"[^\s]+");
            CharacterRange[] ranges = mc.Cast<Match>().Select(m => new CharacterRange(m.Index, m.Length)).ToArray();
            format.SetMeasurableCharacterRanges(ranges);

            using (Font font = new Font("Times New Roman", 40, FontStyle.Regular, GraphicsUnit.Point))
            {
                Region[] regions = g.MeasureCharacterRanges(txt, font, rect, format);

                for (int i = 0; i < ranges.Length; i++)
                {
                    Rectangle WordBounds = Rectangle.Round(regions[i].GetBounds(g));
                    string word = txt.Substring(ranges[i].First, ranges[i].Length);
                    if (word == "keyword")
                        TextRenderer.DrawText(g, word, font, WordBounds, Color.YellowGreen, flags);
                    else
                        TextRenderer.DrawText(g, word, font, WordBounds, Color.White, flags);
                }
            }
        }
    }

当我将位图和文本渲染到屏幕上(直接渲染到绘画事件中的表单)时,这段代码工作得很好。

但是当我使用图像中的图形对象时,为了将其保存到文件中,我从 MeasureCharacterRanges 得到完全不同的边界矩形,在保存的图像中文本位置完全扭曲。

我不确定这是 MeasureCharacterRanges 方法中的错误还是我错过了什么。如果没有解决方案或解决方法,我愿意接受其他解决方案。

编辑:问题似乎来自其他地方。我有这样的伪代码。

Image imgResize = resizeImage(strfile); 
Graphics g = Graphics.FromImage(imgResize);
AddText1(strText, g, rect);

这行不通。但是当我这样做

Image imgResize = resizeImage(strfile);
Image img2 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img2);
g.DrawImage(imgResize, new Rectangle(0, 0, width, height));
AddText1(strText, g, rect);

在这两种情况下,调整后的图像大小和分辨率相同。但是我不知道在使用中间图像创建图形对象后显式绘制调整大小的图像时到底是什么让它起作用。请告诉我,如果你知道什么可以有所作为。

感谢您的回答。

c# winforms gdi
2个回答
0
投票

我认为您需要使用同一组方法来测量文本和绘制文本。即要么

var size = TextRenderer.MeasureText(word, font) ;
...
TextRenderer.DrawText(g, word, font, ...);

var ranges = g.MeasureCharacterRanges(word, font, rect, format);
...
g.DrawString(word, font, ...);

您可以在此处了解

TextRenderer.DrawText
Graphics.DrawString
之间的区别。我不希望
Graphics.MeasureCharacterRanges
TextRenderer.DrawText
兼容,至少不是在所有用例中。


0
投票

您的问题是关于以一种能够正确保存到文件的方式将彩色文本叠加在图像之上。由于您提到您“对其他解决方案持开放态度”,实现这一结果的众多方法之一是创建一个

PictureBox
控件并将
Label
控件添加到
pictureBox.Controls
集合。


添加图片

private void onClickAddImage(object sender, EventArgs e)
{
    pictureBox.Image = Image.FromFile(Path.Combine(
        AppDomain.CurrentDomain.BaseDirectory,
        "Images",
        "20221205_172318.bmp"
    ));
}

添加一些标签

Font H1 = new Font("TimesNewRoman", 20F);
Font Body = new Font("TimesNewRoman", 12F);
private void onClickAddLabels(object sender, EventArgs e)
{
    pictureBox.Controls.Clear();
    Label label;
    label = new Label
    {
        BackColor = Color.Transparent,
        AutoSize= true,
        BorderStyle = BorderStyle.None,
        ForeColor= Color.White,
        Text = "Label 1",
        Font= H1,
        Location= new Point(50, 20),
        TextAlign = ContentAlignment.MiddleCenter,
    };
    pictureBox.Controls.Add(label);

    label = new Label
    {
        BackColor = Color.White,
        AutoSize= true,
        BorderStyle = BorderStyle.None,
        ForeColor = Color.Red,
        Text = "Label 2",
        Font = Body,
        Location = new Point(60, 100),
        TextAlign = ContentAlignment.MiddleCenter,
    };
    pictureBox.Controls.Add(label);
}

保存到文件

现在只需将

PictureBox
画成
Bitmap
并保存即可。

private void onClickSave(object sender, EventArgs e)
{
    Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
    pictureBox.DrawToBitmap(bitmap, pictureBox.ClientRectangle);
    bitmap.Save("tmp.bmp");
    Process.Start("explorer.exe", "tmp.bmp");
}
© www.soinside.com 2019 - 2024. All rights reserved.