【问题标题】:Creating, Drawing Lines and saving bitmap gives Generic GDI+ error创建、绘制线条和保存位图会导致通用 GDI+ 错误
【发布时间】:2015-10-14 21:34:04
【问题描述】:

我有一个非常简单的方法,它将签名作为点列表并将它们绘制为位图上的线。我想获取该位图并将其保存到文件中,但是当我调用 Save 方法时,我得到“GDI+ 中发生一般错误”并且没有内部异常。

这似乎是非常简单的代码,所以我不确定问题出在哪里。

using (var b = new Bitmap(width, height))
{
    var g = Graphics.FromImage(b);
    var lastPoint = points[0];
    for (int i = 1; i < points.Length; i++)
    {
        var p = points[i];
        // When the user takes the pen off the device, X/Y is set to -1
        if ((lastPoint.X >= 0 || lastPoint.Y >= 0) && (p.X >= 0 || p.Y >= 0))
            g.DrawLine(Pens.Black, lastPoint.X, lastPoint.Y, p.X, p.Y);
        lastPoint = p;
    }
    g.Flush();
    pictureBox.Image = b;
    b.Save("C:\\test.bmp");
}

我尝试使用所有可能的 ImageFormats 进行保存,将图形对象放在 using 语句中,而且我什至尝试过:

using (var ms = new MemoryStream())
{
    b.Save(ms, ImageFormats.Bmp); // And b.Save(ms, ImageFormats.MemoryBmp);
    Image.FromStream(ms).Save("C:\\test.bmp");
}

奇怪的是,如果我删除 b.Save(或忽略异常),pictureBox 会完美显示图像。

任何帮助将不胜感激。

【问题讨论】:

  • 您是否可能没有对该位置的写入权限?
  • g 在哪里被声明?在保存之前尝试处理它。保存到根驱动器不是一个好位置——Windows 可能会遇到安全问题。
  • 对不起,我忘记了图形声明,我编辑了我的问题。我只是出于测试目的而写入根目录,但我确实拥有完全的写入权限。
  • 好吧,你不应该拥有完全的写入权限,因为这被认为是操作系统领域。无论如何尝试不同的路径。
  • 你不应该在 using 块中包含该位图,因为 PictureBox 正在尝试使用它。

标签: c# image winforms bitmap


【解决方案1】:

我会使用来自Paint 事件的相应Graphics 绘制到PictureBox,然后保存到位图:

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        MyDrawing(e.Graphics);

        Bitmap b = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        pictureBox1.DrawToBitmap(b, pictureBox1.ClientRectangle);
        b.Save(@"C:\test.bmp");

    }
    private void MyDrawing(Graphics g)
    {
        var lastPoint = points[0];

        for (int i = 1; i < points.Count; i++)
        {
            var p = points[i];
            // When the user takes the pen off the device, X/Y is set to -1
            if ((lastPoint.X >= 0 || lastPoint.Y >= 0) && (p.X >= 0 || p.Y >= 0))
                g.DrawLine(Pens.Black, lastPoint.X, lastPoint.Y, p.X, p.Y);
            lastPoint = p;
        }
        g.Flush();
    }

保存的 BMP:

【讨论】:

    【解决方案2】:

    您的代码有两个问题,一个隐藏另一个:

    • 您的应用程序可能对C: 的根没有写入权限,因此Save 失败。
    • 您也不能让 PictureBox 显示 Bitmap,然后在 using 块中销毁它。

    所以你应该把代码改成这样:

    var b = new Bitmap(width, height);
    
    using (Graphics g = Graphics.FromImage(b))
    {
        var lastPoint = points[0];
        for (int i = 1; i < points.Length; i++)
        {
            var p = points[i];
            // When the user takes the pen off the device, X/Y is set to -1
            if ((lastPoint.X >= 0 || lastPoint.Y >= 0) && (p.X >= 0 || p.Y >= 0))
                g.DrawLine(Pens.Black, lastPoint.X, lastPoint.Y, p.X, p.Y);
            lastPoint = p;
        }
        // g.Flush(); not necessary
        pictureBox1.Image = b;
        b.Save("C:\\temp\\test.bmp");
    }
    

    您还应该检查数组的Length,并考虑使用List&lt;Points&gt;,同时检查其Count 并在points.ToArray() 上使用DrawLines,以获得更好的线连接,尤其是粗线连接,半透明线条!

    【讨论】:

    • 我假设由于我能够在我的根目录上创建/修改文件,因此应用程序也具有写访问权限,我还假设如果是这种情况我会收到拒绝访问异常。在那方面吸取了教训。我还从位图中删除了 using 并将其添加到 Graphics 声明中,感谢您的洞察力。
    • 另外,我没有使用 DrawLines,因为有些点的 X/Y 为 -1,表示笔已从垫子上移开
    • 至于 DrawLines:不透明或细线无关紧要;我通常使用List&lt;List&gt;Point&gt;&gt; 来保存多个直线或曲线序列;对于最自然的外观DrawCurves 效果更好..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多