1

我正在构建一个管道组件,可以将图像格式转换为另一种格式(例如 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 的位置只会在第二次保存时前进?为什么第一次保存尝试只保存转换后的图像的一部分。我很困惑!

4

1 回答 1

1

Data除了在最后设置流外,我会避免使用该属性;根据MSDNData ,它会克隆数据流,有时会出现意外行为(即使GetOriginalDataStream()成功返回了流,我也看到某些适配器中的属性为 null)。改为使用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);
于 2015-05-15T15:12:59.433 回答