2012-11-18 123 views
1

嘗試將巨大圖像(例如9000x9000像素圖像)加載到位圖對象中可能會產生內存不足錯誤,並且無疑會造成其他相關問題。如何在沒有內存問題的情況下加載/處理大圖像?

如何從磁盤加載9000x9000像素圖像,最終在保存到磁盤之前調整大小,而不會導致致命錯誤(例如內存不足)?

讓我們假設一個帶有2gb內存的C#4.0的32位環境,並且將使用jpg,gif,bmp,tif,png等圖像格式。

我已經嘗試了以下3個片段,並且每個都會出現內存錯誤。

嘗試1:

using (Bitmap srcImg = new Bitmap(@"C:\9000x9000.jpg")) 
{ 
    // boom 
} 

嘗試2:

using (Image srcImg = Image.FromFile(@"C:\9000x9000.jpg")) 
{ 
    // kapow 
} 

嘗試3:

using (FileStream fs = new FileStream(@"C:\9000x9000.jpg", FileMode.Open, FileAccess.Read)) 
{ 
    using (Image srcImg = Image.FromStream(fs)) 
    { 
     // kelly clarkson 
    } 
} 

我給一個可能的解決方案的想法是直接加載的圖像文件到一個數組(所以你沒有Bitmap對象的巨大開銷),以某種方式調整它使用該數組更小(可能需要編碼爲D不同的圖像格式標題?),然後才能最終轉換爲可管理大小的位圖對象。

想法或可能的解決方案?

+0

什麼是錯誤信息?首先在簡單的控制檯應用程序中嘗試它,然後在您的應用程序中應用該解決方案 –

+0

什麼是圖像的位深度?我很好奇圖像試圖消耗多少內存。我的猜測是一個很大的32位圖像意味着至少310MB。考慮到你的其他問題,我強烈建議你升級到至少有8GB內存的64位系統..可能更多。並且我會建議您獲取用於處理如此大圖像的內置工具 – NotMe

+0

您是否確實發生錯誤,或者您是否只是猜測可能出現的問題?我認爲沒有先驗理由認爲18 Mpx的圖像會導致任何悲傷,除非你真的想把它做得更大。它將佔用幾百MB。 –

回答

1

看看AForge.Net library,這是supposedly good在處理大文件。

+0

我感覺他的系統非常糟糕,並且使用像這樣的庫可能是一種很好的方式。 – NotMe

+0

關於「約束」,最大的限制是32位系統。在32位系統上,單個對象的可用空間有限,而Bitmap對象的開銷很大,因此在32位系統上獲取內存不足錯誤並不會花太多時間系統,即使系統實際上可能有內存可用。無論如何,即使在64位環境下,優化代碼以儘可能少地佔用內存仍然很棒。 –

+0

關於AForge的初步想法:它似乎最初將圖像直接加載到Bitmap對象中,所以它會有完全相同的內存問題(註釋結束處的鏈接顯示AForge FromFile方法)。我會運行一些測試來驗證。 http://www.aforgenet.com/framework/docs/html/4b467feb-9cf0-c2b5-4a16-a1862d6e2531.htm –

0

這裏是我遵循得到它的工作步驟:

1.Go到http://www.opennetcf.org/PermaLink.aspx?guid=d57ace50-2762-4b19-b07d-39421829d410並下載下載自衛隊2.0 Beta1的再分發。安裝。

2.在VS.NET 2005中創建一個智能設備項目,目標是PPC 2003 SE設備。我必須右鍵單擊我的項目並選擇「升級」以確保它的目標是.NET CF v2.0而不是.NET CF 1.1 SP3。

3.I加入OpenNETCF.dll和OpenNETCF.Drawing.dll文件從默認安裝目錄(C:\ Program Files文件\ OpenNETCF \智能設備框架2.0)引用

4,我創建了一個簡單應用程序與一個窗體上的圖片框,加載窗體時加載我的圖像。下面是相關的代碼,一些從Alex Feinman的網絡日誌複製而來:

#region Using directives 
using System; 
using System.Drawing; 
using System.Collections; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using OpenNETCF.Drawing.Imaging; 
using System.IO; 
#endregion 

.... 

const string szFileName = @"\Storage Card\TEMP\2MBJPEG.JPG"; 



private void Form1_Load(object sender, EventArgs e) 
{ 
IBitmapImage imageBitmap; 
FileStream fsImage; 
fsImage = new FileStream(
    szFileName, 
    FileMode.Open); 
imageBitmap = CreateThumbnail(
    fsImage, 
    new Size(100, 100)); 

Bitmap bm = ImageUtils.IBitmapImageToBitmap(
    imageBitmap); 
pictureBox1.Image = bm; 
} 


static public IBitmapImage CreateThumbnail(Stream stream, Size size) 
{ 
IBitmapImage imageBitmap; 
ImageInfo ii; 
IImage image; 
ImagingFactory factory = new ImagingFactoryClass(); 
    factory.CreateImageFromStream(
    new StreamOnFile(stream), 
    out image); 
image.GetImageInfo(out ii); 
factory.CreateBitmapFromImage(
    image, 
    (uint)size.Width, 
    (uint)size.Height, 
    ii.PixelFormat, 
    InterpolationHint.InterpolationHintDefault, 
    out imageBitmap); 
    return imageBitmap; 
} 
+0

你是說這允許你在32位系統上處理巨大的圖像? –

相關問題