c# - 在图像上绘制字节

标签 c# encoding drawimage

我试图让某些字节写入图像,例如:

" །༉ᵒᵗᵗ͟ᵋༀ 🐢 ͟ ͟ ͟ ͟ ͟ ͟🐢 ͟ ͟ ͟ ͟ ͟ ͟ ͟🐛 ͟ ͟ ͟ ͟ ͟ ͟🐢. . . "

当我在图像上显示它时,我得到的是以下内容......

图片:

enter image description here

我已经尝试更改字符串的编码类型,当我收到字节并且没有设置字体时,但我已经尝试了所有默认的 Microsoft 字体以及我在 Internet 上找到的一些自定义字体。我究竟做错了什么?


编辑:原来使用的是Graphics.DrawString。我已经尝试过 TextRenderer,结果几乎相同。

图片:

http://i.stack.imgur.com/kxhyU.jpg

这是我用来生成图像的代码:

string text = "[rotten4pple]  །༉ᵒᵗᵗ͟ᵋༀ 🐢 ͟ ͟ ͟ ͟ ͟ ͟🐢 ͟ ͟ ͟ ͟ ͟ ͟ ͟🐛 ͟ ͟ ͟ ͟ ͟ ͟🐢. . .";

var font = new Font("Arial", 8, FontStyle.Regular);
var bitmap = new Bitmap(1, 1);
var size = Graphics.FromImage(bitmap).MeasureString(text, font);
bitmap = new Bitmap((int)size.Width + 4, (int)size.Height + 4);
using (var gfx = Graphics.FromImage(bitmap))
{
    gfx.Clear(Color.White);
    TextRenderer.DrawText(gfx, cmd.AllArguments, font, new Point(2, 2),
        Color.Black, Color.White);
}

变量 cmd.AllArguments 被传递到方法中,我相信字符串是使用 windows-1252 编码的。

最佳答案


成像

不要对 unicode 字符使用 Graphics.DrawString

您应该改用 TextRenderer.DrawText,例如:

TextRenderer.DrawText(e.Graphics, "こんにちは", this.Font,
            new Point(10, 10), this.ForeColor, this.BackColor, flags);

缺点是您无法指定Brush


我已经测试过了。我想肯定还有其他原因,因为它似乎对我有用。这是我的代码:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    var text = " །༉ᵒᵗᵗ͟ᵋༀ 🐢 ͟ ͟ ͟ ͟ ͟ ͟🐢 ͟ ͟ ͟ ͟ ͟ ͟ ͟🐛 ͟ ͟ ͟ ͟ ͟ ͟🐢. . . ";
    TextRenderer.DrawText(e.Graphics, "TextRenderer.DrawText" + text , this.Font,
        new Point(10, 10), this.ForeColor, this.BackColor);

    e.Graphics.DrawString("Graphics.DrawString" + text, this.Font,
        new SolidBrush(this.ForeColor), new PointF(10, 30));
}

注意:字体是Arial Unicode MS 8.25pt

输出:

text drawing comparison


编码

这是原始字符串,以 UTF-8 格式存储:

[rotten4pple] །༉ᵒᵗᵗ͟ᵋༀ 🐢 ͟ ͟ ͟ ͟ ͟ ͟🐢 ͟ ͟ ͟ ͟ ͟ ͟ ͟🐛 ͟ ͟ ͟ ͟ ͟ ͟🐢. . .

这是您得到的错误字符串,存储在 Windows-1252 中:

[rotten4pple] à¼à¼‰áµ’ᵗᵗ͟ᵋༀ 🢠͟ ÍŸ ÍŸ ÍŸ ÍŸ ͟🢠͟ ÍŸ ÍŸ ÍŸ ÍŸ ÍŸ ͟🛠͟ ÍŸ ÍŸ ÍŸ ÍŸ ÍŸðŸ¢. . .

而且它们是二进制相等的。这是两个字符串的字节的十六进制表示:

5B 72 6F 74 74 65 6E 34 70 70 6C 65 5D 20 E0 BC
8D E0 BC 89 E1 B5 92 E1 B5 97 E1 B5 97 CD 9F E1
B5 8B E0 BC 80 EF A3 BF 20 F0 9F 90 A2 20 CD 9F
20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F F0
9F 90 A2 20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F 20
CD 9F 20 CD 9F 20 CD 9F F0 9F 90 9B 20 CD 9F 20
CD 9F 20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F F0 9F
90 A2 2E 20 2E 20 2E

由于这是对二进制值的重新解释而不是重新编码,因此在 .NET 中使用 Encoding.Convert 从一个值转换为另一个值是不可行的。相反,您应该以错误的编码获取字符串的二进制表示,并直接将其读取为正确的编码:

var text = cmd.AllArguments;
var bytes = Encoding.GetEncoding(1252).GetBytes(text);
text = Encoding.UTF8.GetString(bytes);

注意事项

您一直在询问什么编码使用您默认使用的 API。我不熟悉您正在使用的 API...但是,它有可能取决于机器的配置。您应该寻找允许您指定接收 UTF-8 字符串的重载。

有可能您实际上收到了 byte[],因此您可以直接在其上使用 Encoding.UTF8.GetString。如果你不能指定编码,你应该考虑改用发送byte[],这样做的目的是对编码有更多的控制。

在这方面,不要使用 Encoding.Default,因为它将是机器语言的扩展 ASCII。

顺便说一下,UTF-8 是网络的不错选择,不仅因为它独立于语言和其他区域配置,还因为它独立于字节顺序(字节顺序)。

关于c# - 在图像上绘制字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20624198/

相关文章:

audio - VoIP和对讲机的音频编码技术

.net - XmlWriter 编码问题

javascript - Canvas.drawImage 不工作

wpf - 有没有办法通过指定源矩形的子区域来执行 DrawingContext.DrawImage ?

c# - 如何设置相机与缩放物体的距离?

c# - 通过 C# 代码复制数据库对象

c# - SqlDataReader:将 varbinary 读入字节数组

c# - App.xaml 的 EventSetter 上出现错误 CS1061

Swift - 特殊字符的编码和解码字符串

swift - 绘制圆圈的按钮上的图像