简体   繁体   English

C#裁剪并调整大图像的大小

[英]C# Crop & resize large images

I got some very large building drawings, sometimes 22466x3999 with a bit depth of 24, or even larger. 我得到了一些非常大的建筑图纸,有时是22466x3999,深度为24,甚至更大。 I need to be able to resize these to smaller versions, and to be able to cut out sections of the image to smaller images. 我需要能够将这些版本调整为较小的版本,并能够将图像的各个部分剪切成较小的图像。

I have been using the following code to resize the images, which I found 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);
        }

And this code to crop the images: 这个代码裁剪图像:

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;
            }
        }

My problem is that i get a Sytem.OutOfMemoryException when I try to resize the image, and that's because I can't load the full image in to FullsizeImage. 我的问题是,当我尝试调整图像大小时,我得到一个Sytem.OutOfMemoryException ,这是因为我无法将完整图像加载到FullsizeImage中。

So what I would like to know, how do I resize an image without loading the entire image into memory? 那么我想知道的是,如何在不将整个图像加载到内存中的情况下调整图像大小?

There are chances the OutOfMemoryException is not because of the size of the images, but because you don't dispose all the disposables classes correctly : 有可能OutOfMemoryException不是因为图像的大小,而是因为你没有正确处理所有的一次性类:

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

are not disposed as they should. 没有按照他们的意愿处理。 You should add a using() statement around them. 您应该在它们周围添加using()语句。

If you really encounter this error with just one image, then you should consider switch your project to x64. 如果您只使用一个图像确实遇到此错误,那么您应该考虑将项目切换到x64。 A 22466x3999 picture means 225Mb in memory, I think it shouldn't be an issue for x86. 22466x3999图片在内存中意味着225Mb,我认为它不应该是x86的问题。 (so try to dispose your objects first). (所以先尝试处理你的对象)。

Last but not least, Magick.Net is very efficient about resizing / cropping large pictures. 最后但同样重要的是, Magick.Net非常有效地调整大型图片的大小/裁剪。

You can also force .Net to read the image directly from disk and stop memory caching. 您还可以强制.Net直接从磁盘读取映像并停止内存缓存。

Use 采用

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

Instead of 代替

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

see https://stackoverflow.com/a/47424918/887092 请参阅https://stackoverflow.com/a/47424918/887092

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM