如何将多页TIFF图像保存至MemoryStream?
多页TIFF保存到MemoryStream仅生成第一页的问题解决
问题根源分析
你的代码存在几个关键错误:
- 冗余且错误的流初始化:先将单页TIFF写入
byteStream再读取为Image对象,这个tiff对象本身是单页的,后续SaveAdd操作无法正确追加帧到目标流。 - EncoderParameters参数不匹配:
flushParams构造时指定长度为1,但参数数组里包含了flushParam和lastPageParam两个参数,导致参数无效,无法正确完成多帧写入的收尾。 - 流位置未重置:写完
tiffStream后未将流的Position重置到开头,直接调用Image.FromStream只能读取到空或不完整的内容。
修正后的代码
public void Test() { // Add 3 image files to the cache list List<Image> imageCache = new List<Image>(); imageCache.Add(Image.FromFile(@"c:\test\testInput1.tif")); imageCache.Add(Image.FromFile(@"c:\test\testInput2.tif")); imageCache.Add(Image.FromFile(@"c:\test\testInput3.tif")); // Get the tiff image codec ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType == "image/tiff").First(); if (codec == null) throw new Exception("Tiff codec not found."); // Create compression encoder parameter EncoderParameter compressionParam = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT4); // Create first page frame parameter EncoderParameter firstFrameParam = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame); // Create additional pages frame parameter EncoderParameter additionalFramesParam = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage); // Create color depth parameter EncoderParameter colorDepthParam = new EncoderParameter(Encoder.ColorDepth, (long)1); // Create last frame + flush parameter EncoderParameter lastFrameFlushParam = new EncoderParameter(Encoder.SaveFlag, (long)(EncoderValue.LastFrame | EncoderValue.Flush)); // Create first page encoder parameters EncoderParameters firstFrameParams = new EncoderParameters(2) { Param = new EncoderParameter[] { compressionParam, firstFrameParam, } }; // Create additional pages encoder parameters EncoderParameters additionalFrameParams = new EncoderParameters(2) { Param = new EncoderParameter[] { compressionParam, additionalFramesParam, } }; // Create save to file encoder parameters EncoderParameters saveToFileParams = new EncoderParameters(2) { Param = new EncoderParameter[] { compressionParam, colorDepthParam, } }; // Create final flush encoder parameters (修正长度为1,因为合并了LastFrame和Flush) EncoderParameters flushParams = new EncoderParameters(1) { Param = new EncoderParameter[] { lastFrameFlushParam } }; using (MemoryStream tiffStream = new MemoryStream()) { // 直接使用第一页图像启动多帧保存 Image firstPage = imageCache[0]; firstPage.Save(tiffStream, codec, firstFrameParams); // 追加后续页面 for (int page = 1; page < imageCache.Count; page++) { firstPage.SaveAdd(imageCache[page], additionalFrameParams); } // 完成多帧写入并刷新 firstPage.SaveAdd(flushParams); // 重置流位置到开头,确保能完整读取 tiffStream.Position = 0; // 将MemoryStream中的多页TIFF保存到文件 using (Image tiffOutput = Image.FromStream(tiffStream)) { tiffOutput.Save(@"c:\test\testOutput.tif", codec, saveToFileParams); } } // 释放图像资源(避免内存泄漏) foreach (Image img in imageCache) { img.Dispose(); } }
关键修正点
- 去掉了冗余的
byteStream步骤,直接使用第一页图像初始化多帧保存流程,确保SaveAdd能正确追加帧到目标MemoryStream。 - 将
LastFrame和Flush合并为一个EncoderParameter,修正flushParams的参数长度匹配问题。 - 在读取
tiffStream前重置Position为0,保证能读取到完整的多页TIFF数据。 - 添加了图像资源的释放逻辑,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Arvo Bowen
相关产品推荐
相关产品推荐

