我正在构建一个可以将图像格式转换为另一种格式的管道组件(例如jpg到png):
using (System.Drawing.Bitmap bmpSource = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(msgReceived.BodyPart.Data))
{
VirtualStream strConvertedImage = new VirtualStream();
bmpSource.Save(strConvertedImage, System.Drawing.Imaging.ImageFormat.Png);
strConvertedImage.Flush();
strConvertedImage.Position = 0;
ctxPipeline.ResourceTracker.AddResource(strConvertedImage);
}
msgReceived.BodyPart.Data = strConvertedImage;
我在带有文件适配器的接收管道中使用此组件,并且执行正常,但是当我使用直通发送端口和文件适配器订阅时,写入的文件只是实际图像的一部分。
注意:
我可以在Windows控制台应用程序中使用相同的代码(除了从文件流加载源位图而不是BizTalk消息流),它工作正常,所以这似乎与BizTalk相关。
我认为它与源流有关。
这似乎很奇怪,但如果我检查msgReceived.BodyPart.Data的长度和位置属性,则长度为904678.位置为0.位置保持为0并且即使在加载和保存位图时也不会更改。我希望当我加载位图时,位置会发生变化,除非BitMap.FromStream方法在完成加载后寻找流的开头。
此外,当我将位图作为png保存到我的新流时,新的流长度始终为54789,仅代表图像的第一方。现在,如果我立即将相同的位图对象再次保存到新流,则其大小为1400868,表示整个图像,msgReceived.BodyPart.Data.Position现在为904678,表示已读取整个源流。
以下是一个例子:
using (System.Drawing.Bitmap bmpSource = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(msgReceived.BodyPart.Data))
{
VirtualStream strConvertedImage = new VirtualStream();
bmpSource.Save(strConvertedImage, System.Drawing.Imaging.ImageFormat.Png);
strConvertedImage.Flush();
strConvertedImage.Position = 0;
//msgReceived.BodyPart.Data.Position is 0
//msgReceived.BodyPart.Data.Length is 904678
//strConvertedImage.Position is 54789 (Only part of image was saved)
strConvertedImage = new VirtualStream();
bmpSource.Save(strConvertedImage, System.Drawing.Imaging.ImageFormat.Png);
//msgReceived.BodyPart.Data.Position is 904678
//msgReceived.BodyPart.Data.Length is 904678
//strConvertedImage.Position is 1400868 (full image was saved)
msgReceived.BodyPart.Data = strConvertedImage;
ctxPipeline.ResourceTracker.AddResource(strConvertedImage);
}
为什么msgReceived.BodyPart.Data的位置只会在第二次保存时前进?为什么第一次保存尝试只保存部分转换后的图像。我感到困惑!
答案 0 :(得分:1)
我要避免使用Data
属性,除非在最后设置流;每MSDN它克隆数据流,有时会出现意外行为(我已经看到Data
属性在某些适配器中为空,即使GetOriginalDataStream()
成功返回了流)。请改用GetOriginalDataStream()
。我也避免在管道中使用using
块 - 虽然我不明白为什么你的例子会出问题,但是很容易错误地处理最终处理原始数据流的流。
例如,
Stream originalStream = msgReceived.BodyPart.GetOriginalDataStream();
originalStream.Seek(0, SeekOrigin.Begin);
VirtualStream vtsConvertedImage = new VirtualStream()
System.Drawing.Bitmap bmpSource = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(originalStream);
bmpSource.Save(vtsConvertedImage, System.Drawing.Imaging.ImageFormat.Png);
vtsConvertedImage.Flush();
vts.ConvertedImage.Seek(0, SeekOrigin.Begin);
msgReceived.BodyPart.Data = vtsConvertedImage;
ctxPipeline.ResourceTracker.AddResource(vtsConvertedImage);
ctxPipeline.ResourceTracker.AddResource(bmpSource);