2015-03-13 143 views
7

我得到了一些非常大的建築圖紙,有時22466x3999的深度爲24,甚至更大。 我需要能夠將這些尺寸調整爲較小的版本,並且能夠將圖像的各部分裁剪爲較小的圖像。C#裁剪和調整大圖像

我一直在使用下面的代碼來調整圖像,我發現here

 public static void ResizeImage(string OriginalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider) 
     { 
      System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFile); 
      if (OnlyResizeIfWider) 
      { 
       if (FullsizeImage.Width <= NewWidth) 
       { 
        NewWidth = FullsizeImage.Width; 
       } 
      } 
      int NewHeight = FullsizeImage.Height * NewWidth/FullsizeImage.Width; 
      if (NewHeight > MaxHeight) 
      { 
       NewWidth = FullsizeImage.Width * MaxHeight/FullsizeImage.Height; 
       NewHeight = MaxHeight; 
      } 
      System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero); 
      FullsizeImage.Dispose(); 
      NewImage.Save(NewFile); 
     } 

而這種代碼裁剪圖像:

public static MemoryStream CropToStream(string path, int x, int y, int width, int height) 
     { 
      if (string.IsNullOrWhiteSpace(path)) return null; 
      Rectangle fromRectangle = new Rectangle(x, y, width, height); 
      using (Image image = Image.FromFile(path, true)) 
      { 
       Bitmap target = new Bitmap(fromRectangle.Width, fromRectangle.Height); 
       using (Graphics g = Graphics.FromImage(target)) 
       { 
        Rectangle croppedImageDimentions = new Rectangle(0, 0, target.Width, target.Height); 
        g.DrawImage(image, croppedImageDimentions, fromRectangle, GraphicsUnit.Pixel); 
       } 
       MemoryStream stream = new MemoryStream(); 
       target.Save(stream, image.RawFormat); 
       stream.Position = 0; 
       return stream; 
      } 
     } 

我的問題是,我得到一個Sytem.OutOfMemoryException當我嘗試調整圖像大小時,這是因爲無法將完整圖像加載到FullsizeImage中。

所以我想知道,如何在不將整個圖像加載到內存中的情況下調整圖像大小?

+0

這不是一個編程解決方案,但你可以嘗試增加*虛擬內存*你的機器的尺寸看看。 – Kurubaran 2015-03-13 08:59:14

+0

你應該使用LockBits來處理這樣的圖像大小 – Vajura 2015-03-13 08:59:29

+0

@Kurubaran我試圖增加內存大小,但這並不奏效,我不認爲它是Web項目的正確解決方案。 – 2015-03-13 10:54:04

回答

5

有機會的OutOfMemoryException是因爲圖像的大小,而是因爲你不處理所有正確耗材類:

  • Bitmap target
  • MemoryStream stream
  • System.Drawing.Image NewImage

不應按原樣處置。您應該在他們周圍添加一條using()聲明。

如果你真的遇到這個錯誤只有一個圖像,那麼你應該考慮把你的項目切換到x64。 22466x3999圖片意味着225Mb的內存,我認爲它不應該是x86的問題。 (所以嘗試首先處理你的對象)。

最後但並非最不重要,Magick.Net是非常有效的調整/裁剪大圖片。

+0

謝謝,我會在Fullsizeimage和其他地方添加'using()'。我曾嘗試過Magick.Net,但我無法完成它,但如果這無濟於事,我會試試看。 – 2015-03-13 09:14:14

+0

圖片Magick.Net必須要走,因爲添加using仍然返回'OutOfMemoryException'。如果Image Magick.Net不起作用,我將製作一個單獨的服務來處理所有的圖像大小調整和裁剪。 – 2015-03-13 10:32:53

+1

即使在大型64位系統上,您也無法創建任意大小的位圖。如果他需要使用非常大的Bitmaps,恐怕使用第三方庫是最好的選擇。 – TaW 2015-03-13 10:35:08

1

您也可以強制.Net直接從磁盤讀取映像並停止內存緩存。

使用

sourceBitmap = (Bitmap)Image.FromStream(sourceFileStream, false, false);

而不是

...System.Drawing.Image.FromFile(OriginalFile);

看到https://stackoverflow.com/a/47424918/887092