合并多个大型tiff文件时出现OutOfMemoryException

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

每个zip文件的限制都不得超过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图像。

zuzhangw 回答:合并多个大型tiff文件时出现OutOfMemoryException

不确定这是否是OutOfMemoryException的原因,但是根据实现的不同,TIFF文件的最大限制为大约2到4 GB。

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

  

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

,

如果某些物品是一次性的,则应始终将其丢弃。最终它会被垃圾收集器本身清除,但是调用Dispose始终是一个好习惯。

您应该在下一次迭代之前处理memorystream对象,这很可能也可以解决您的问题。

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

您是否尝试过使用FileStream而不是MemoryStream

代替

MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine("somepath\\test_sample_zip",s)));
pages = (Bitmap) Image.FromStream(ms);

尝试

Stream m = File.OpenRead(Path.Combine("somepath\\test_sample_zip",s));
pages = (Bitmap) Image.FromStream(m);
本文链接:https://www.f2er.com/3050595.html

大家都在问