我正在尝试将多个图像(.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图像。
https://en.wikipedia.org/wiki/TIFF
TIFF文件格式使用32位偏移量,这将文件大小限制为大约4 GiB。一些实现甚至使用带符号的32位偏移,已经遇到了大约2 GiB的问题。
using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine("somepath\\test_sample_zip", s)))) {
...
...
}
ms.Dispose();