2015-03-13 146 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