为什么将图像写入流中与直接保存到文件中相比,给我带来不同的结果?

时间:2019-01-28 13:05:32

标签: c# .net drawing

我正在尝试向现有图像添加一些矩形。使用以下代码时,一切正常:

var bytes = File.ReadAllBytes("myPath\\input.jpg");
var stream = new MemoryStream(bytes);

using (var i = new Bitmap(stream))
{
    using (var graphics = Graphics.FromImage(i))
    {
        var selPen = new Pen(Color.Blue);
        graphics.DrawRectangle(selPen, 10, 10, 50, 50);

        i.Save("myPath\\output.jpg", ImageFormat.Jpeg);
    }
}

但是将图像保存到相同的MemoryStream中,然后再将所有字节写入文件,就可以得到几乎只有灰色的图像。

这不起作用:

var bytes = File.ReadAllBytes("myPath\\input.jpg");
var stream = new MemoryStream(bytes);

using (var i = new Bitmap(stream))
{
    using (var graphics = Graphics.FromImage(i))
    {
        var selPen = new Pen(Color.Blue);
        graphics.DrawRectangle(selPen, 10, 10, 50, 50);

        i.Save(stream, ImageFormat.Jpeg);
    }
}

File.WriteAllBytes("myPath\\output.jpg", stream.ToArray());

(错误的)图像如下所示: enter image description here

如您所见,图像的仅一部分是灰色的。实际图像中仍有一部分可见(白色)。

为什么会这样?正确的解决方法是什么?

谢谢!

2 个答案:

答案 0 :(得分:3)

在第二个示例中,您已经双层写入Stream;它仍然包含原始数据,然后您用Save 追加了更多数据。 Stream的作用就像录像带一样。如果要覆盖流,则需要非常小心地执行此操作(并且:并非所有流都支持该概念-请考虑“网络流”,“加密流”等)。请注意,ToArray(和GetBuffer / TryGetBuffer方法)可以看到所有数据,而不仅仅是您认为的“新”数据(甚至不存在一个概念,就像录像带一样,您只有“当前”位置和长度-如果您需要知道第一场演出在哪里结束而第二场演出在哪里开始,您需要注意自己,手动)。在这种情况下,添加:

stream.Position = 0; // rewind
stream.SetLength(0); // truncate (important in case the new data is *shorter* than the old)

在阅读后Save之前,应对其进行修复。

答案 1 :(得分:1)

您正在将图像从字节数组保存到已初始化的流中。

创建一个新流并将其保存。

 var stream2 = new MemoryStream();
 i.Save(stream2, ImageFormat.Jpeg);

或者只是重置上一个

 memoryStream = new MemoryStream(stream.Capacity());