【问题标题】:There is not enough memory for the picture when using Graphics, C#使用Graphics时图片内存不足,C#
【发布时间】:2018-12-14 00:53:52
【问题描述】:

代码很简单:我按下按钮,图片被加载到PictureBox中。

    private void button1_Click(object sender, EventArgs e)
{
        using (FileStream stream = File.OpenRead(FullName))
        {
            pictureBox1.Image = (Bitmap)Bitmap.FromStream(stream).Clone();
            stream.Close();
            stream.Dispose();
        }
}

但是当我在 PictureBox'e 上使用其他函数\事件时,它发誓在 Graphics.FromImage 上没有足够的内存。不管我用这个时间表做什么。示例:

    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
{
    g.Clear(Color.FromArgb(0, 255, 255, 255));
    pictureBox1.Invalidate();
}

问题是,为什么我可以在将图片上传到 PictureBox 之前对 Graphics 做任何我想做的事情:剪切、填充、绘制;但是上传图片后我不能? p.s.图片尝试了不同的尺寸。同一张图片在上传前有效(已在默认图片框中),上传到图片框后无效。走了很多关于这个主题的论坛,但没有找到我的案例(或最相似的案例)。

【问题讨论】:

  • 在你的第一个例子中,如果你有用于 FileStream 的 using() 块,那么你不需要调用 Close()、Dispose()。正如我在第一个示例中看到的那样,您正在调用 Clone() ,因此您有另一个对象,但第二个处理了该对象。看看这些:stackoverflow.com/questions/25723855/…
  • 我认为解决方案是这样的:在图形中,“内存不足”异常主要发生在 image.propertyitems 抛出一些异常时。这时,我们需要将图像存储在流中,然后再次从流中获取图像。

标签: c# graphics picturebox


【解决方案1】:

所以问题出在流中,由 Graphics.FromImage 使用。 Documentation 说,从 Graphics.FromImage 打开的流必须在整个图像处理过程中保持打开状态。好的,我们可以使用 MemoryStream:

    MemoryStream ms;

private void button1_Click(object sender, EventArgs e)
{

    ms = new MemoryStream();
    using (FileStream stream = File.OpenRead(FullName))
    {
        stream.CopyTo(ms);
        pictureBox1.Image = Bitmap.FromStream(ms);
    }
}        


private void button2_Click(object sender, EventArgs e)
{
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.Clear(Color.FromArgb(0, 255, 255, 255));
    }     
}

并且 image.Clone() 需要删除,因为流必须具有对同一图像的引用,而不是对其副本的正确工作。 (老实说,这个简单的程序可以在没有 MemoryStream 的情况下工作)

【讨论】:

  • 哦,上面的答案(我没有马上注意到)看起来更详细。这个答案已经没有多大意义了。
【解决方案2】:

你有 3 种选择:

1) 分配Image.FromStream() 结果而不克隆它:PictureBox 控件更喜欢在底层流上自行操作(请参阅.Net Source about the PictureBox.Load() 方法)。

private void button1_Click(object sender, EventArgs e)
{
    using (FileStream stream = File.OpenRead(FullName))
    {
        pictureBox1.Image = Bitmap.FromStream(stream);
    }
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.Clear(Color.FromArgb(0, 255, 255, 255));
    }
}  

2) 执行 using 块内的所有操作。此时流仍然有效:

using (FileStream stream = File.OpenRead(FullName)
{
    pictureBox1.Image = (Image)Image.FromStream(stream).Clone();
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.Clear(Color.FromArgb(0, 255, 255, 255));
    }
}

3) 直接使用Load() 方法。

    pictureBox1.Load(FullName);

所有方法最终都将使用 PictureBox 控件内部 InstallNewImage()(.Net 源)方法。看看 Image stream 是如何处理的。

调用Graphics.FromImage() 将不再引发异常。

【讨论】:

  • 谢谢,第一种方法帮助我=)
猜你喜欢
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 2011-05-18
  • 2014-06-13
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 2011-01-27
相关资源
最近更新 更多