我试图让某些字节写入图像,例如:
" །༉ᵒᵗᵗ͟ᵋༀ 🐢 ͟ ͟ ͟ ͟ ͟ ͟🐢 ͟ ͟ ͟ ͟ ͟ ͟ ͟🐛 ͟ ͟ ͟ ͟ ͟ ͟🐢. . . "
当我在图像上显示它时,我得到的是以下内容......
图片:
我已经尝试更改字符串的编码类型,当我收到字节并且没有设置字体时,但我已经尝试了所有默认的 Microsoft 字体以及我在 Internet 上找到的一些自定义字体。我究竟做错了什么?
编辑:原来使用的是Graphics.DrawString
。我已经尝试过 TextRenderer
,结果几乎相同。
图片:
这是我用来生成图像的代码:
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
。
输出:
编码
这是原始字符串,以 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/