2008-10-13 76 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);