问题:
为什么用于 ImageA 的 MemoryStream 对象会影响名为 ImageB 的克隆 Image 对象?我知道 Microsoft 表示,当您从内存流创建 Image 对象时,您必须在图像的整个生命周期内保持该流打开。但我尝试从 MemoryStream 创建 ImageA,将 ImageA 克隆到 ImageB,然后处理 ImageA 和用于创建 ImageA 的 MemoryStream。之后我在处理 ImageB 时出现错误。
来源示例:
以下所有代码均用于从 3 个 tiff 文件(单页)创建新的多页 tiff 图像。最终得到一个 3 页的单个 tiff 图像。由此您获得...
- 图片 newImg
- 内存流毫秒
注意:对于一个小测试来说,这似乎有很多代码,但我想给出一个很好的例子来说明我在哪里获取我正在使用的对象。这个示例代码的很多部分取自几个不同的方法/函数,我只是做了一些改动,以便真正描绘出我从导入文件本身开始所做的一切。
Image img = Image.FromFile(@"c:\test\page001.tif");
MemoryStream ms = new MemoryStream();
List<Image> imagesToAdd = new List<Image>()
{
Image.FromFile(@"c:\test\page002.tif"),
Image.FromFile(@"c:\test\page003.tif")
};
// 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 flush parameter
EncoderParameter flushParam = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.Flush);
// Create last frame parameter
EncoderParameter lastPageParam = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.LastFrame);
// 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 flush encoder parameters
EncoderParameters flushParams = new EncoderParameters(1)
{
Param = new EncoderParameter[]
{
flushParam,
lastPageParam,
}
};
// Get the tiff image codec
ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType == "image/tiff").First();
// Save the first page to memory stream
img.Save(ms, codec, firstFrameParams);
// Save aditional pages to memory stream
foreach (Image image in imagesToAdd)
img.SaveAdd(image, additionalFrameParams);
// Finalize the new multi-page image
img.SaveAdd(flushParams);
//Image newImg = pageOne.SaveMultiPageImage(imgCol, out MemoryStream ms);
Image newImg = Image.FromStream(ms);
// Cleanup
firstFrameParams.Dispose();
additionalFrameParams.Dispose();
saveToFileParams.Dispose();
flushParam.Dispose();
compressionParam.Dispose();
firstFrameParam.Dispose();
additionalFramesParam.Dispose();
colorDepthParam.Dispose();
flushParam.Dispose();
lastPageParam.Dispose();
下面的代码实际上是在其他地方使用的。我已将所有这些功能都放在一个函数中进行测试,以便制作一个很好的示例。下面代码的思路是使用上面的代码生成的图像,然后对其进行克隆,删除原始图像和用于创建它的内存流,然后尝试使用新创建的 Image 对象。
问题:在处理用于创建 newImg 图像对象的内存流之后,从 newImg 克隆的新图像(newImg2)会损坏。
// Try to work with the newImg Image object (no issues)
int pageCount = newImg.GetFrameCount(FrameDimension.Page);
for (int i = 0; i < pageCount; i++)
{
newImg.SelectActiveFrame(FrameDimension.Page, i);
Debug.WriteLine($"BEFORE - Page:{i + 1} W/H: {newImg.Width}/{newImg.Height}");
}
// Create a new Image (newImg2) based on the original Image (newImg)
// then dispose of the original Image object as it's no longer needed
Image newImg2 = (Image)newImg.Clone();
newImg.Dispose();
// This causes issues when dealing with newImg2 going forward
ms.Dispose();
// Try to work with the newImg2 Image object (issues)
pageCount = newImg2.GetFrameCount(FrameDimension.Page);
for (int i = 0; i < pageCount; i++)
{
newImg2.SelectActiveFrame(FrameDimension.Page, i);
Debug.WriteLine($"AFTER - Page:{i + 1} W/H: {newImg2.Width}/{newImg2.Height}");
}