【问题标题】:Image.FromStream() method returns Invalid Argument exceptionImage.FromStream() 方法返回 Invalid Argument 异常
【发布时间】:2010-10-15 03:12:55
【问题描述】:

我正在从智能相机成像仪捕获图像并通过套接字编程从相机接收字节数组(.NET 应用程序是客户端,相机是服务器)。

问题是我在运行时遇到 System.InvalidArgument 异常。

private Image byteArrayToImage(byte[] byteArray) 
{
    if(byteArray != null) 
    {
        MemoryStream ms = new MemoryStream(byteArray);
        return Image.FromStream(ms, false, false); 
        /*last argument is supposed to turn Image data validation off*/
    }
    return null;
}

我在很多论坛中搜索过这个问题,并尝试了很多专家给出的建议,但没有任何帮助。

我认为字节数组本身没有任何问题,因为当我将相同的字节数组输入我的 VC++ MFC 客户端应用程序时,我得到了图像。但这在 C#.NET 中不起作用。

谁能帮帮我?

附注:

我尝试完成相同任务的其他方法是:

1.

private Image byteArrayToImage(byte[] byteArray)
{
    if(byteArray != null) 
    {
        MemoryStream ms = new MemoryStream();
        ms.Write(byteArray, 0, byteArray.Length);
        ms.Position = 0; 
        return Image.FromStream(ms, false, false);
    }
    return null;
}

2.

private Image byteArrayToImage(byte[] byteArray) 
{
    if(byteArray != null) 
    {
        TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
        Bitmap b = (Bitmap)tc.ConvertFrom(byteArray);
        return b;
    }
    return null;
}

以上方法均无效。请帮忙。

【问题讨论】:

  • 如果您只是将字节数组写入磁盘上的文件会发生什么?文件可以用 Photoshop 之类的东西打开吗?
  • 你解决了吗?我有同样的问题
  • 哪一行抛出异常?

标签: c# .net image exception memorystream


【解决方案1】:

从数据库 byteArray 加载后,字节数多于一个图像。在我的例子中是 82。

MemoryStream ms = new MemoryStream();
ms.Write(byteArray, 82, byteArray.Length - 82);
Image image = Image.FromStream(ms);

为了保存在数据库中,我插入 82 字节开始流。 Properties.Resources.ImgForDB - 它是包含那些 82 字节的二进制文件。 (我得到它的下一个路径 - 将图像从 DB 加载到 MemoryStream 并保存到二进制文件的前 82 个字节。你可以在这里拿它 - https://yadi.sk/d/bFVQk_tdEXUd-A

        MemoryStream temp = new MemoryStream();
        MemoryStream ms = new MemoryStream();
        OleDbCommand cmd;
        if (path != "")
        {
            Image.FromFile(path).Save(temp, System.Drawing.Imaging.ImageFormat.Bmp);
            ms.Write(Properties.Resources.ImgForDB, 0, Properties.Resources.ImgForDB.Length);
            ms.Write(temp.ToArray(), 0, temp.ToArray().Length);

        cmd = new OleDbCommand("insert into Someone (first, Second, Third) values (@a,@b,@c)", connP);
        cmd.Parameters.AddWithValue("@a", fio);
        cmd.Parameters.AddWithValue("@b", post);
        cmd.Parameters.AddWithValue("@c", ms.ToArray());
        cmd.ExecuteNonQuery();

【讨论】:

  • 我认为在这种情况下没有帮助。
  • 我也有同样的问题。它帮助了我。
【解决方案2】:

Image.FromStream() 需要一个只包含一个图像的流!

它将 stream.Position 重置为 0。我有一个包含多个图像或其他内容的流,您必须将图像数据读入字节数组并初始化 MemoryStream与那个:

Image.FromStream(new MemoryStream(myImageByteArray));

只要图像在使用中,MemoryStream 就必须保持打开状态。

我也很艰难地学会了这一点。

【讨论】:

    【解决方案3】:

    尝试使用类似于此处描述的内容https://social.msdn.microsoft.com/Forums/vstudio/en-US/de9ee1c9-16d3-4422-a99f-e863041e4c1d/reading-raw-rgba-data-into-a-bitmap

    Image ImageFromRawBgraArray(
        byte[] arr, 
        int charWidth, int charHeight,
        int widthInChars, 
        PixelFormat pixelFormat)
    {
        var output = new Bitmap(width, height, pixelFormat);
        var rect = new Rectangle(0, 0, width, height);
        var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);
    
        // Row-by-row copy
        var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat) / 8;
        var ptr = bmpData.Scan0;
        for (var i = 0; i < height; i++)
        {
            Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
            ptr += bmpData.Stride;
        }
    
        output.UnlockBits(bmpData);
        return output;
    }
    

    【讨论】:

      【解决方案4】:

      试试这个:

      public Image byteArrayToImage(byte[] item)
      {          
         Image img=Image.FromStream(new MemoryStream(item)); 
         img.Save(Response.OutputStream, ImageFormat.Gif);
         return img;
      }
      

      希望对你有帮助!

      【讨论】:

        【解决方案5】:

        此代码有效

                string query="SELECT * from gym_member where Registration_No ='" + textBox9.Text + "'";
        
                command = new SqlCommand(query,con);
                ad = new SqlDataAdapter(command);
                DataTable dt = new DataTable();
                ad.Fill(dt);
                textBox1.Text = dt.Rows[0][1].ToString();
                textBox2.Text = dt.Rows[0][2].ToString();
                byte[] img = (byte[])dt.Rows[0][18];
                MemoryStream ms = new MemoryStream(img);
        
                pictureBox1.Image = Image.FromStream(ms);
                ms.Dispose();
        

        【讨论】:

          【解决方案6】:

          也许图像嵌入在 OLE 字段中,您必须考虑 88 字节 OLE 标头加上有效负载:

          byteBlobData = (Byte[]) reader.GetValue(0);
          stream = new MemoryStream(byteBlobData, 88, byteBlobData.Length - 88);
          img = Image.FromStream(stream);
          

          【讨论】:

          • 就我而言,我只需要“删除”8 个字节。 new MemoryStream(byteBlobData, 8, byteBlobData.Length - 8);
          • 你怎么知道它有 8 位长?
          【解决方案7】:

          我在这样做时遇到了这个问题:

          MemoryStream stream = new MemoryStream();
          screenshot.Save(stream, ImageFormat.Png);
          byte[] bytes = new byte[stream.Length];
          stream.Save(bytes, 0, steam.Length);
          

          最后两行是问题所在。我通过这样做修复了它:

          MemoryStream stream = new MemoryStream();
          screenshot.Save(stream, ImageFormat.Png);
          byte[] bytes = stream.ToArray();
          

          然后这工作了:

          MemoryStream stream = new MemoryStream(bytes);
          var newImage = System.Drawing.Image.FromStream(stream);
          stream.Dispose();
          

          【讨论】:

            【解决方案8】:

            我猜测从服务器接收文件时出现了问题。在尝试将其转换为Image 之前,您可能只获得了文件的一部分?您确定与您提供给 C++ 应用程序的字节数组完全相同吗?

            尝试将流保存到文件中,看看会得到什么。你或许能从中发现一些线索。

            您还可以添加断点并手动将字节数组中的某些字节与它们应有的值进行比较(如果您知道的话)。


            编辑:看起来接收数据没有问题。问题是它是原始格式(不是Image.FromStream 理解的格式)。 Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr) constructor 可能在这里有用。或者,您可以创建空白位图并根据原始数据手动对其进行 blt。

            【讨论】:

            • 您好,我尝试将图像保存为 jpg、bmp 文件,但我没有得到文件中的图片。令人费解的是,它与我能够在我的 VC++ MFC 应用程序中显示图像的字节数组相同。
            • 这就是为什么我不太确定它是同一个字节数组的原因。文件大小一样吗?
            • VC++ 应用程序显示来自相机的实时图像,因此我所做的是将字节数组写入 txt 文件。同样,从我的 .NET 应用程序中,我将字节数组写入一个文件,然后比较这两个文件。我发现所有的值都被填满了,它们或多或少是一样的。
            • 事实上,我尝试将我从 VC++ 应用程序(在 txt 文件中)获得的数组提供给我的 C#.NET 应用程序。这也失败了:-(
            • 由于落在相机镜头上的光线强度波动,字节数组每次都不会相同。所以,我观察到的是 VC++ 日志和 C# 日志之间的字节数组值有一些细微的变化
            【解决方案9】:

            我过去也遇到过同样的问题,它是由 Windows GDI 库中的泄漏引起的,这就是“位图”所使用的。但是,如果这种情况一直发生在你身上,那么它可能是无关的。

            【讨论】:

            • 你好克里斯,感谢您的回复。每次我运行代码时都会发生这种情况。
            【解决方案10】:

            System.InvalidArgument 表示流没有有效的图像格式,即不支持的图像类型。

            【讨论】:

            • 您好,感谢您的回复。但是,我的 VC++ MFC 应用程序中如何使用相同的字节数组?还有什么方法可以检查我的字节数组图像数据的有效性吗? Arvind K
            猜你喜欢
            • 1970-01-01
            • 2020-03-30
            • 2016-05-04
            • 2014-09-30
            • 2019-04-03
            • 1970-01-01
            • 1970-01-01
            • 2010-09-12
            • 1970-01-01
            相关资源
            最近更新 更多