【问题标题】:Parameter is not valid error when creating image from byte[] in c#在 c# 中从 byte[] 创建图像时参数无效错误
【发布时间】:2011-03-12 20:16:47
【问题描述】:

我正在尝试在 c# 中将 byte[] 转换为 Bitmap。以下是代码:

MemoryStream ms = new MemoryStream(b);
Bitmap bmp = new Bitmap(ms);

创建Bitmap时显示错误Parameter is not valid

byte[] b 来自网络流。

但是当我将这个 byte[] 写入一个文件,并在任何图像查看器中打开这个文件时,它就可以完美地工作。以下是将 byte[] 写入文件的代码:

 var fs = new BinaryWriter(new FileStream("tmp.bmp", FileMode.Create, FileAccess.Write));
 fs.Write(b);
 fs.Close();

我在这里错过了什么?

编辑

这是导致问题的完整代码

 Socket s = listener.AcceptSocket();
 byte[] b = new byte[imgLen];
 s.Receive(b);
 MemoryStream ms = new MemoryStream(b);
 // now here I am using ms.Seek(0, SeekOrigin.Begin); that fixed my problem.
 Bitmap bmp = new Bitmap(ms);
 pictureBox1.Image = bmp;
 s.Close();

我在Form_Load 事件中使用此代码,没有任何额外内容。我只是想显示在网络上流式传输的图像。服务器是用 Java 编写的,用于传输此图像。

希望能解惑。

谢谢

【问题讨论】:

  • 您是否尝试过使用 Image.FromStream 代替?我想不出为什么这会奏效,但值得一试......
  • 试过 Image.FromStream 但也没有用。
  • @Jon 太晚了,乔恩,达林这周有你!
  • 你能显示一个(最小化的)完整工作部分的代码,它会抛出这个错误吗?也许错误来自其他地方的错误。另外:您可以在查看器中打开图像并不一定意味着图像数据对于 GDI+ 理解是有效的。如果您使用MemoryStream 从磁盘打开tmp.bmp 会发生什么?

标签: c# image


【解决方案1】:

好的,只是为了澄清一点......问题是new Bitmap(ms) 将从流的当前位置读取数据 - 如果流当前位于 end数据,它将无法读取任何内容,因此出现了问题。

问题声称代码是这样的:

MemoryStream ms = new MemoryStream(b);
Bitmap bmp = new Bitmap(ms);

在这种情况下,没有要求重置流的位置,因为它已经是 0。但是,我怀疑代码实际上更像这样:

MemoryStream ms = new MemoryStream();
// Copy data into ms here, e.g. reading from NetworkStream
Bitmap bmp = new Bitmap(ms);

或者可能:

MemoryStream ms = new MemoryStream(b);
// Other code which *reads* from ms, which will change its position,
// before we finally call the constructor:
Bitmap bmp = new Bitmap(ms);

在这种情况下,您确实需要重置位置,因为否则流的“光标”位于数据的结束而不是开始。然而,就个人而言,我更喜欢使用 Position 属性而不是 Seek 方法,只是为了简单起见,所以我会使用:

MemoryStream ms = new MemoryStream();
// Copy data into ms here, e.g. reading from NetworkStream

// Rewind the stream ready for reading
ms.Position = 0;
Bitmap bmp = new Bitmap(ms);

这只是说明问题中的示例代码代表实际代码的重要性...

【讨论】:

  • 我正在使用MemoryStream ms = new MemoryStream(b);创建内存流!
  • @Vinod:那么在调用 Bitmap 构造函数之前,你必须用它做 something else... 因为以这种方式构造的流的初始位置 是 0 。如果您可以发布所涉及的完整 代码,我们可以进一步提供帮助……但我不相信您正在为字节数组创建MemoryStream,然后立即调用new Bitmap(ms)。如果是这样,简单地倒带无济于事
  • 你写// Other code which *reads* from ms, which will change its position。这不是我第一次看到人们一步步调试,用鼠标悬停,调用 getter,调用副作用。或使用立即窗口。这是一个完美的例子,其中副作用可能导致仅在调试环境中有效(抛出)的行为。
  • @Abel:确实。我不会期望这是这里的问题,因为我只希望 OP 在已经显示问题的情况下调试到此代码中。它必须是手表或即时窗口,因为我不相信 Stream 中的任何属性获取器会改变它。
  • 我没有对内存流做任何事情。我的任务只是读取 byte[] 并从中创建位图。我编辑了我的问题,显示了我正在使用的完整实际代码,除了我没有使用任何东西。请看一下。 byte[] 流来自用 java 编写的服务器。
【解决方案2】:

尝试重置流中的当前位置

MemoryStream ms = new MemoryStream(b);
ms.Seek(0, SeekOrigin.Begin);
Bitmap bmp = new Bitmap(ms);

【讨论】:

  • 这是我的第一个想法,但是当您直接从字节数组构造 MemoryStream 时,就没有必要这样做了。
  • 谢谢!我从过去 2 小时开始伸头,也用谷歌搜索,但没有找到任何解决方案。你是个好人!再次感谢:)
  • 所以,显然,毕竟还是有需要的,或者涉及到我们没有看到的代码;)。
  • @Jon,我从来没有想出一个好的规则,什么时候需要重置流,什么时候不需要。
  • 我现在添加了一个答案来解释发生了什么,以及为什么在问题中实际显示的情况下您不需要这样做,但是 do 需要当您写入到内存流中时执行此操作。
【解决方案3】:

试试这样:

byte[] b = ...
using (var ms = new MemoryStream(b))
using (var bmp = Image.FromStream(ms))
{
    // do something with the bitmap
}

【讨论】:

  • 首先我会使用 Image.FromStream 而不是 Bitmap.FromStream (因为它在 Image 中定义,而不是 Bitmap),其次我看不出这将如何影响 构造函数 工作与否。
  • @Vinod Maurya,我刚刚通过b = File.ReadAllBytes("test.png"); 测试了这段代码,并成功加载到位图中。 @Jon,您对 Image 的看法是正确的。
  • @Darin,我刚刚在我的代码中进行了同样的测试,我得到了同样的错误。我没有从文件中读取字节,实际上我的字节来自网络流,所以这可能会导致问题。我刚刚使用了 Albin 建议的 ms.Seek(0, SeekOrigin.Begin);,现在我的代码运行良好!无论如何感谢您的快速回复!
  • 我很想知道为什么 Darin 的代码在没有 SeekOrigin.Begin 的情况下也能工作......嗯,可能 MemoryStream 不是实际的底层流?
  • @Abel:当它实际从字节数组创建 MemoryStream 时,它默认位于开头。但是,我认为问题中发布的代码并不是真实代码的公平表示。
【解决方案4】:

如果您正在处理图像,则会显示错误。尝试从代码中删除它

【讨论】:

    猜你喜欢
    • 2011-11-30
    • 2017-07-06
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    相关资源
    最近更新 更多