[英]How to convert large image files in c#
我有几个大型图像文件,需要将其转换为不同的图像格式。 我正在使用以下代码执行此操作:
using (Image img =new Bitmap(inputImageName))
{
img.Save(outputImageName, imageFormat);
}
它进行对话,而且由于图像很大,因此会生成内存不足的异常。 我读了几篇有关如何克服LOH碎片的文章,但是在这种情况下我无法使用它们。
我能做什么?
图像约为100MByte,它在打开3或4张图像后发生。
您需要在这里问的问题是“我必须在.NET和/或C#中执行此操作”吗?
虽然我明白了为什么对于许多人来说,像C#这样的灵活语言可能是执行许多任务的答案,但我也不得不说,“当你拥有的一切都是锤子时,每个问题都像钉子一样”。
如果这是一次转换,而您只需要在一个项目中使用它们,那么我对您的建议是使用更适合Job的独立工具。
有大量的收费应用程序,例如:
AcdSee照片管理器
释放诸如
Ifran View及其图像转换功能
http://www.bleepingcomputer.com/forums/topic50519.html
如果您要玩命令行脚本,请使用诸如ImageMagik之类的工具集:
http://www.imagemagick.org/script/index.php
Iamage Magik还具有.NET绑定,因此,如果您的项目需要在程序代码中即时转换它们,则可以在.NET项目以及许多其他项目中使用它的功能。
http://www.imagemagick.org/script/api.php
对于这样的场景,确实没有理由重新发明轮子,这个问题已经解决了很多次,实际上这不是您必须做出的决定。
根据本文了解一下不使用GDI的WPF图像操作类。 以下源代码是一个很好的起点:
public static void Resize(string input, string output)
{
using (var inputStream = File.OpenRead(input))
{
var photoDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
var frame = photoDecoder.Frames[0];
using (var ouputStream = File.Create(output))
{
var targetEncoder = new PngBitmapEncoder();
targetEncoder.Frames.Add(frame);
targetEncoder.Save(ouputStream);
}
}
}
它与大对象堆没有任何关系。 Bitmap类是GDI +的托管包装器,而GDI +是很大一部分非托管代码。 它在非托管内存中分配像素数据缓冲区。 您的代码使用的托管内存量很小。
100兆字节的图像文件并没有说明需要多少非托管内存。 它很可能是一种压缩图像格式,例如JPEG或PNG。 在解压缩后,确实需要更多的非托管内存。 因此,您很容易最终需要数百兆字节。
当您在32位操作系统上运行代码或选择x86作为EXE的平台目标设置(VS2010及更高版本的默认设置)时,这就是一个问题。 您的程序从代码块和已加载的数据之间的可用空洞中分配虚拟内存。 GDI +需要一个连续的内存块来加载像素数据,当程序具有大量可用的虚拟内存但分布在许多漏洞中时,这可能很难实现。 另一个问题是地址空间碎片 ,加载DLL或分配内存可能会将一个大洞的大小一分为二。
有一个简单的修复程序可以解决此问题,请在64位操作系统上运行代码。 它具有可用的虚拟内存块,而且有很大的漏洞。 对于32位操作系统上的当前问题,您可以采取任何措施的可能性很小。 您无法直接控制内存管理器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.