C# 裁剪和调整大图像
C# Crop & resize large images
我得到了一些非常大的建筑图纸,有时是 22466x3999,位深度为 24,甚至更大。
我需要能够将这些调整为更小的版本,并且能够将图像的部分剪切为更小的图像。
我一直在使用以下代码调整图像大小,我发现 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。
那么我想知道的是,如何在不将整个图像加载到内存的情况下调整图像大小?
有可能 OutOfMemoryException
不是因为图像的大小,而是因为您没有正确处理所有一次性用品 类 :
Bitmap target
MemoryStream stream
System.Drawing.Image NewImage
没有按应有的方式处理。您应该在它们周围添加一个 using()
语句。
如果你真的遇到只有一张图片的这个错误,那么你应该考虑将你的项目切换到 x64。一张 22466x3999 的图片意味着 225Mb 的内存,我认为这对于 x86 应该不是问题。 (因此请先尝试处理您的对象)。
最后但同样重要的是,Magick.Net 在调整/裁剪大图片方面非常有效。
您也可以强制 .Net 直接从磁盘读取图像并停止内存缓存。
使用
sourceBitmap = (Bitmap)Image.FromStream(sourceFileStream, false, false);
而不是
...System.Drawing.Image.FromFile(OriginalFile);
见
我得到了一些非常大的建筑图纸,有时是 22466x3999,位深度为 24,甚至更大。 我需要能够将这些调整为更小的版本,并且能够将图像的部分剪切为更小的图像。
我一直在使用以下代码调整图像大小,我发现 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。
那么我想知道的是,如何在不将整个图像加载到内存的情况下调整图像大小?
有可能 OutOfMemoryException
不是因为图像的大小,而是因为您没有正确处理所有一次性用品 类 :
Bitmap target
MemoryStream stream
System.Drawing.Image NewImage
没有按应有的方式处理。您应该在它们周围添加一个 using()
语句。
如果你真的遇到只有一张图片的这个错误,那么你应该考虑将你的项目切换到 x64。一张 22466x3999 的图片意味着 225Mb 的内存,我认为这对于 x86 应该不是问题。 (因此请先尝试处理您的对象)。
最后但同样重要的是,Magick.Net 在调整/裁剪大图片方面非常有效。
您也可以强制 .Net 直接从磁盘读取图像并停止内存缓存。
使用
sourceBitmap = (Bitmap)Image.FromStream(sourceFileStream, false, false);
而不是
...System.Drawing.Image.FromFile(OriginalFile);
见