在图像上绘制字节

时间:2013-12-17 01:17:27

标签: c# encoding drawimage

我试图在Image上写入某些字节,例如:

  

“་。༉ᵒᵗᵗ͟ᵋༀ͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟.......”

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

图像

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编码的。

1 个答案:

答案 0 :(得分:3)


成像

不要将Graphics.DrawString用于unicode字符。

您应该迁移到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是网络的不错选择,不仅因为它独立于语言和其他区域配置,还因为它独立于字节顺序(字节顺序)。