[OutOfMemoryException合并多个大尺寸的tiff文件时

问题描述 投票:0回答:1

我正在尝试将多个图像(.tiff / .tif)文件合并到单个图像(.tif),然后再将Zip文件(包含多个合并的tif图像)发送到AWS S3存储桶。

我对每个压缩文件的限制均不超过5GB。

我有一种情况,其中[[我正在将数千个多页的tiff图像合并到一个tiff图像中。

使用Bitmap

我正在将每个tiff图像逐步添加到其先前图像并保存该图像

但是,我正在执行

通过将所有字节读入

MemoryStream。那是我面临内存不足问题的地方。

当合并的图像达到阈值大小,即2GB(aprox)时,就不可能将字节读入流,然后附加下一个图像。这将引发OutOfMemoryException。我了解这是由于CPU RAM的限制。

但是有解决我这个问题的更好的方法吗?

请在下面找到我的代码。

private void MergeTiffFiles(string filePathWithFileName) { string[] sa; sa = Directory.GetFiles(filePathWithFileName.Substring(0, filePathWithFileName.LastIndexOf('.'))); DirectoryInfo di = new DirectoryInfo(filePathWithFileName); long totalTiffs = di.GetFiles("*.tif").Length; //get the codec for tiff files ImageCodecInfo info = null; foreach(ImageCodecInfo ice in ImageCodecInfo.GetImageEncoders()) if (ice.MimeType == "image/tiff") info = ice; //use the save encoder Encoder enc = Encoder.SaveFlag; EncoderParameters ep = new EncoderParameters(1); ep.Param[0] = new EncoderParameter(enc, (long) EncoderValue.MultiFrame); Bitmap pages = null; int frame = 0; foreach(string s in sa) { if (Path.GetExtension(s) == ".tif" || Path.GetExtension(s) == ".tiff") { if (frame == 0) { **MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine("somepath\\test_sample_zip", s)));** pages = (Bitmap) Image.FromStream(ms); var appDataPath = @ "somepath\\Desktop\\"; var filePath = Path.Combine(appDataPath, Path.GetRandomFileName() + ".tif"); //save the first frame pages.Save(filePath, info, ep); //Save the second frame if any int frameCount1 = pages.GetFrameCount(FrameDimension.Page); if (frameCount1 > 1) { for (int i = 1; i < frameCount1; i++) { ep.Param[0] = new EncoderParameter(enc, (long) EncoderValue.FrameDimensionPage); pages.SelectActiveFrame(FrameDimension.Page, i); pages.SaveAdd(pages, ep); } } } else if (frame < totalTiffs - 1) { //save the intermediate frames ep.Param[0] = new EncoderParameter(enc, (long) EncoderValue.FrameDimensionPage); try { MemoryStream mss = new MemoryStream(File.ReadAllBytes(Path.Combine("somepath\\Desktop\\test_sample_zip", s))); Bitmap bm = (Bitmap) Image.FromStream(mss); int frameCount = bm.GetFrameCount(FrameDimension.Page); for (int i = 0; i < frameCount; i++) { bm.SelectActiveFrame(FrameDimension.Page, i); pages.SaveAdd(bm, ep); } } catch (Exception e) { //LogError(e, s); } } if (frame == totalTiffs - 1) { //flush and close. ep.Param[0] = new EncoderParameter(enc, (long) EncoderValue.Flush); pages.SaveAdd(ep); } frame++; } } }

只要RAM可用内存没有用完,代码就可以在特定大小下正常工作。

引发异常的行是

** MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine("somepath\\test_sample_zip", s)));**

[可能无需将其读入MemoryStream即可合并tiff图像,这将是解决我的问题的最佳解决方案,但不知道如何完成。

或者如果有任何第三方软件合并tiff图像。

c# asp.net .net memory-management out-of-memory
1个回答
0
投票
不确定是否是OutOfMemoryException的原因,但是根据实现的不同,TIFF文件的最大限制为大约2到4 GB。

https://en.wikipedia.org/wiki/TIFF

TIFF文件格式使用32位偏移量,这将文件大小限制为大约4 GiB。一些实现甚至使用带符号的32位偏移,已经遇到了大约2 GiB的问题。

0
投票
如果是一次性用品,则应始终进行处理。最终它会被垃圾收集器本身清理掉,但是调用Dispose总是一个好习惯。

using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine("somepath\\test_sample_zip", s)))) { ... ... } ms.Dispose();

© www.soinside.com 2019 - 2024. All rights reserved.