2008-10-13 49 views
41

为什么我得到内存不足异常?C#Image.Clone内存不足异常

所以这死在C#上在第一时间通过:

splitBitmaps.Add(neededImage.Clone(rectDimensions,neededImage.PixelFormat));

凡splitBitmaps是一个List <的BitMap >但是这个工作在VB至少4次迭代:

arlSplitBitmaps.Add(Image.Clone(rectDimensions,Image.PixelFormat))

在哪里arlSplitBitmaps是一个简单的数组列表。 (是的,我已经尝试在C#中的ArrayList)

这是fullsection:

for (Int32 splitIndex = 0; splitIndex <= numberOfResultingImages - 1; splitIndex++) 
{ 
    Rectangle rectDimensions; 

    if (splitIndex < numberOfResultingImages - 1) 
    { 
    rectDimensions = new Rectangle(splitImageWidth * splitIndex, 0, 
     splitImageWidth, splitImageHeight); 
    } 
    else 
    { 
    rectDimensions = new Rectangle(splitImageWidth * splitIndex, 0, 
    sourceImageWidth - (splitImageWidth * splitIndex), splitImageHeight); 
    } 

    splitBitmaps.Add(neededImage.Clone(rectDimensions, neededImage.PixelFormat)); 

}

neededImage是方式的位图。

我在intarweb上找不到任何有用的答案,特别是没有在VB中正常工作的原因。

更新:

我竟然找了个理由(在某种程度上)对这个工作却忘了将它张贴。它与将图像转换为位图有关,而不是如果我记得只是试图克隆原始图像。

回答

2

确保您在图像上正确调用.Dispose(),否则非托管资源不会被释放。我想知道你在这里创造了多少个图像 - 数百个?成千上万的?

+1

怀疑它是记忆,第一次爆炸。 – 2008-10-14 12:04:54

+0

是的,位图.Dispose不会影响这些OoM异常,以我的经验。 – 2009-11-09 19:17:28

3

这是一个范围,但我经常发现,如果直接从磁盘中提取图像,最好将它们复制到新的位图并处理磁盘绑定的图像。在这样做的时候,我看到内存消耗有了很大的提升。

Dave M.也在赚钱...确保完成后处置。

142

当Rectangle中指定的坐标超出位图范围时,Clone()也可能会引发内存不足异常。它不会自动为你剪切它们。

+25

来自Google的街道,这100%回答了我的问题。 – brian 2011-10-24 20:31:57

+1

这也是我的答案:-) – JTech 2014-03-19 10:51:01

+6

只是一个快速记录,以防它不明显(首先不是我):矩形构造函数的宽度和高度参数表示矩形的_area_你想要的,而不是右下角的坐标。防爆。在100x100的图像上,如果你想要矩形(15,10)到(100,100),你需要新的`矩形(15,10,85,90)`。宽度=图像宽度-x(100-15 = 85),高度=图像高度-y(100-10 = 90)。 `矩形(15,10,100,100)`会给你一个内存不足的例外。 – hawkke 2014-09-02 21:31:55

4

当我尝试使用Clone()方法更改位图的像素格式时,我也得到了这个。如果内存服务,我试图将一个24 bpp位图转换为8位索引格式,天真地希望Bitmap类能够神奇地处理调色板创建等等。显然不是: -/

6

我发现我使用Image.Clone来裁剪位图,宽度使作物超出原始图像的范围。这会导致内存不足错误。看起来有点奇怪,但可以知道。

3

我最近很难弄清楚这一点 - 上面的答案是正确的。解决这个问题的关键是确保矩形实际上在图像的边界内。看到我如何解决这个问题的例子。

简而言之,检查被克隆的区域是否在图像区域之外。

int totalWidth = rect.Left + rect.Width; //think -the same as Right property 

int allowableWidth = localImage.Width - rect.Left; 
int finalWidth = 0; 

if (totalWidth > allowableWidth){ 
    finalWidth = allowableWidth; 
} else { 
    finalWidth = totalWidth; 
} 

rect.Width = finalWidth; 

int totalHeight = rect.Top + rect.Height; //think same as Bottom property 
int allowableHeight = localImage.Height - rect.Top; 
int finalHeight = 0; 

if (totalHeight > allowableHeight){ 
    finalHeight = allowableHeight; 
} else { 
    finalHeight = totalHeight; 
} 

rect.Height = finalHeight; 
cropped = ((Bitmap)localImage).Clone(rect, System.Drawing.Imaging.PixelFormat.DontCare);